CompilerTemplateAsm-armv5te-vfp.S revision 9f601a917c8878204482c37aec7005054b6776fa
1/*
2 * This file was generated automatically by gen-template.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24#if defined(WITH_JIT)
25
26/*
27 * ARMv5 definitions and declarations.
28 */
29
30/*
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-vfp/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, .LdvmFastJavaMethodTraceExit
175    ldmfd   sp!, {r0-r2,lr}             @ restore live registers
176#endif
177    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
178    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
179    ldr     r8, [rSELF, #offThread_suspendCount] @ r8<- suspendCount
180    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
181#if !defined(WITH_SELF_VERIFICATION)
182    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
183#else
184    mov     r9, #0                      @ disable chaining
185#endif
186    ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
187                                        @ r2<- method we're returning to
188    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 suspendCount
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     r1, #0                      @ changeInterp = false
216    mov     r0, rSELF                   @ Expecting rSELF in r0
217    blx     r2                          @ exit the interpreter
218
219/* ------------------------------ */
220    .balign 4
221    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
222dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
223/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
224    /*
225     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
226     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
227     * runtime-resolved callee.
228     */
229    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
230    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
231    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
232    ldr     r9, [rSELF, #offThread_interpStackEnd]    @ r9<- interpStackEnd
233    ldr     r8, [rSELF, #offThread_suspendCount] @ r8<- suspendCount
234    add     r3, r1, #1  @ Thumb addr is odd
235    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
236    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
237    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
238    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
239    cmp     r10, r9                     @ bottom < interpStackEnd?
240    bxlo    lr                          @ return to raise stack overflow excep.
241    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
242    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
243    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
244    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
245    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
246    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
247
248
249    @ set up newSaveArea
250    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
251    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
252    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
253    cmp     r8, #0                      @ suspendCount != 0
254    bxne    lr                          @ bail to the interpreter
255    tst     r10, #ACC_NATIVE
256#if !defined(WITH_SELF_VERIFICATION)
257    bne     .LinvokeNative
258#else
259    bxne    lr                          @ bail to the interpreter
260#endif
261
262    ldr     r10, .LdvmJitToInterpTraceSelectNoChain
263    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
264
265    @ Update "thread" values for the new method
266    str     r0, [rSELF, #offThread_method]    @ self->method = methodToCall
267    str     r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
268    mov     rFP, r1                         @ fp = newFp
269    str     rFP, [rSELF, #offThread_curFrame]  @ self->curFrame = newFp
270#if defined(TEMPLATE_INLINE_PROFILING)
271    stmfd   sp!, {r0-r3}                    @ preserve r0-r3
272    mov     r1, r6
273    @ r0=methodToCall, r1=rSELF
274    mov     lr, pc
275    ldr     pc, .LdvmFastMethodTraceEnter
276    ldmfd   sp!, {r0-r3}                    @ restore r0-r3
277#endif
278
279    @ Start executing the callee
280#if defined(WITH_JIT_TUNING)
281    mov     r0, #kInlineCacheMiss
282#endif
283    mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
284
285/* ------------------------------ */
286    .balign 4
287    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
288dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
289/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
290    /*
291     * For monomorphic callsite, setup the Dalvik frame and return to the
292     * Thumb code through the link register to transfer control to the callee
293     * method through a dedicated chaining cell.
294     */
295    @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
296    @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
297    @ methodToCall is guaranteed to be non-native
298.LinvokeChain:
299    ldr     r9, [rSELF, #offThread_interpStackEnd]    @ r9<- interpStackEnd
300    ldr     r8, [rSELF, #offThread_suspendCount]      @ r8<- suspendCount
301    add     r3, r1, #1  @ Thumb addr is odd
302    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
303    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
304    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
305    add     r12, lr, #2                 @ setup the punt-to-interp address
306    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
307    cmp     r10, r9                     @ bottom < interpStackEnd?
308    bxlo    r12                         @ return to raise stack overflow excep.
309    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
310    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
311    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
312    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
313
314    @ set up newSaveArea
315    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
316    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
317    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
318    cmp     r8, #0                      @ suspendCount != 0
319    bxne    r12                         @ bail to the interpreter
320
321    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
322
323    @ Update "thread" values for the new method
324    str     r0, [rSELF, #offThread_method]    @ self->method = methodToCall
325    str     r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
326    mov     rFP, r1                         @ fp = newFp
327    str     rFP, [rSELF, #offThread_curFrame]  @ self->curFrame = newFp
328#if defined(TEMPLATE_INLINE_PROFILING)
329    stmfd   sp!, {r0-r2,lr}             @ preserve clobbered live registers
330    mov     r1, r6
331    @ r0=methodToCall, r1=rSELF
332    mov     lr, pc
333    ldr     pc, .LdvmFastMethodTraceEnter
334    ldmfd   sp!, {r0-r2,lr}             @ restore registers
335#endif
336
337    bx      lr                              @ return to the callee-chaining cell
338
339/* ------------------------------ */
340    .balign 4
341    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
342dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
343/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
344    /*
345     * For polymorphic callsite, check whether the cached class pointer matches
346     * the current one. If so setup the Dalvik frame and return to the
347     * Thumb code through the link register to transfer control to the callee
348     * method through a dedicated chaining cell.
349     *
350     * The predicted chaining cell is declared in ArmLIR.h with the
351     * following layout:
352     *
353     *  typedef struct PredictedChainingCell {
354     *      u4 branch;
355     *      const ClassObject *clazz;
356     *      const Method *method;
357     *      u4 counter;
358     *  } PredictedChainingCell;
359     *
360     * Upon returning to the callsite:
361     *    - lr  : to branch to the chaining cell
362     *    - lr+2: to punt to the interpreter
363     *    - lr+4: to fully resolve the callee and may rechain.
364     *            r3 <- class
365     *            r9 <- counter
366     */
367    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
368    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
369    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
370    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
371    ldr     r9, [rSELF, #offThread_icRechainCount] @ r1 <- shared rechainCount
372    cmp     r3, r8          @ predicted class == actual class?
373#if defined(WITH_JIT_TUNING)
374    ldr     r7, .LdvmICHitCount
375#if defined(WORKAROUND_CORTEX_A9_745320)
376    /* Don't use conditional loads if the HW defect exists */
377    bne     101f
378    ldr     r10, [r7, #0]
379101:
380#else
381    ldreq   r10, [r7, #0]
382#endif
383    add     r10, r10, #1
384    streq   r10, [r7, #0]
385#endif
386    ldreqh  r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
387    ldreqh  r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
388    beq     .LinvokeChain   @ predicted chain is valid
389    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
390    cmp     r8, #0          @ initialized class or not
391    moveq   r1, #0
392    subne   r1, r9, #1      @ count--
393    strne   r1, [rSELF, #offThread_icRechainCount]  @ write back to thread
394    add     lr, lr, #4      @ return to fully-resolve landing pad
395    /*
396     * r1 <- count
397     * r2 <- &predictedChainCell
398     * r3 <- this->class
399     * r4 <- dPC
400     * r7 <- this->class->vtable
401     */
402    bx      lr
403
404/* ------------------------------ */
405    .balign 4
406    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
407dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
408/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
409    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
410    @ r7 = methodToCall->registersSize
411    ldr     r9, [rSELF, #offThread_interpStackEnd]    @ r9<- interpStackEnd
412    ldr     r8, [rSELF, #offThread_suspendCount]      @ r8<- suspendCount
413    add     r3, r1, #1  @ Thumb addr is odd
414    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
415    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
416    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
417    cmp     r10, r9                     @ bottom < interpStackEnd?
418    bxlo    lr                          @ return to raise stack overflow excep.
419    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
420    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
421    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
422
423    @ set up newSaveArea
424    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
425    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
426    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
427    cmp     r8, #0                      @ suspendCount != 0
428    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
429#if !defined(WITH_SELF_VERIFICATION)
430    bxne    lr                          @ bail to the interpreter
431#else
432    bx      lr                          @ bail to interpreter unconditionally
433#endif
434
435    @ go ahead and transfer control to the native code
436    ldr     r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
437    mov     r2, #0
438    str     r1, [rSELF, #offThread_curFrame]   @ self->curFrame = newFp
439    str     r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
440    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
441                                        @ newFp->localRefCookie=top
442    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
443
444    mov     r2, r0                        @ arg2<- methodToCall
445    mov     r0, r1                        @ arg0<- newFP
446    add     r1, rSELF, #offThread_retval  @ arg1<- &retval
447    mov     r3, rSELF                     @ arg3<- self
448#if defined(TEMPLATE_INLINE_PROFILING)
449    @ r2=methodToCall, r6=rSELF
450    stmfd   sp!, {r2,r6}                @ to be consumed after JNI return
451    stmfd   sp!, {r0-r3}                @ preserve r0-r3
452    mov     r0, r2
453    mov     r1, r6
454    @ r0=JNIMethod, r1=rSELF
455    mov     lr, pc
456    ldr     pc, .LdvmFastMethodTraceEnter
457    ldmfd   sp!, {r0-r3}                @ restore r0-r3
458#endif
459
460    blx     r8                          @ off to the native code
461
462#if defined(TEMPLATE_INLINE_PROFILING)
463    ldmfd   sp!, {r0-r1}                @ restore r2 and r6
464    @ r0=JNIMethod, r1=rSELF
465    mov     lr, pc
466    ldr     pc, .LdvmFastNativeMethodTraceExit
467#endif
468    @ native return; r10=newSaveArea
469    @ equivalent to dvmPopJniLocals
470    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
471    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
472    ldr     r1, [rSELF, #offThread_exception] @ check for exception
473    str     rFP, [rSELF, #offThread_curFrame]  @ self->curFrame = fp
474    cmp     r1, #0                      @ null?
475    str     r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
476    ldr     r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
477
478    @ r0 = dalvikCallsitePC
479    bne     .LhandleException           @ no, handle exception
480
481    str     r2, [rSELF, #offThread_inJitCodeCache] @ set the mode properly
482    cmp     r2, #0                      @ return chaining cell still exists?
483    bxne    r2                          @ yes - go ahead
484
485    @ continue executing the next instruction through the interpreter
486    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
487    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
488#if defined(WITH_JIT_TUNING)
489    mov     r0, #kCallsiteInterpreted
490#endif
491    mov     pc, r1
492
493/* ------------------------------ */
494    .balign 4
495    .global dvmCompiler_TEMPLATE_MUL_LONG
496dvmCompiler_TEMPLATE_MUL_LONG:
497/* File: armv5te/TEMPLATE_MUL_LONG.S */
498    /*
499     * Signed 64-bit integer multiply.
500     *
501     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
502     *
503     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
504     *        WX
505     *      x YZ
506     *  --------
507     *     ZW ZX
508     *  YW YX
509     *
510     * The low word of the result holds ZX, the high word holds
511     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
512     * it doesn't fit in the low 64 bits.
513     *
514     * Unlike most ARM math operations, multiply instructions have
515     * restrictions on using the same register more than once (Rd and Rm
516     * cannot be the same).
517     */
518    /* mul-long vAA, vBB, vCC */
519    mul     ip, r2, r1                  @  ip<- ZxW
520    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
521    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
522    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
523    mov     r0,r9
524    mov     r1,r10
525    bx      lr
526
527/* ------------------------------ */
528    .balign 4
529    .global dvmCompiler_TEMPLATE_SHL_LONG
530dvmCompiler_TEMPLATE_SHL_LONG:
531/* File: armv5te/TEMPLATE_SHL_LONG.S */
532    /*
533     * Long integer shift.  This is different from the generic 32/64-bit
534     * binary operations because vAA/vBB are 64-bit but vCC (the shift
535     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
536     * 6 bits.
537     */
538    /* shl-long vAA, vBB, vCC */
539    and     r2, r2, #63                 @ r2<- r2 & 0x3f
540    mov     r1, r1, asl r2              @  r1<- r1 << r2
541    rsb     r3, r2, #32                 @  r3<- 32 - r2
542    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
543    subs    ip, r2, #32                 @  ip<- r2 - 32
544    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
545    mov     r0, r0, asl r2              @  r0<- r0 << r2
546    bx      lr
547
548/* ------------------------------ */
549    .balign 4
550    .global dvmCompiler_TEMPLATE_SHR_LONG
551dvmCompiler_TEMPLATE_SHR_LONG:
552/* File: armv5te/TEMPLATE_SHR_LONG.S */
553    /*
554     * Long integer shift.  This is different from the generic 32/64-bit
555     * binary operations because vAA/vBB are 64-bit but vCC (the shift
556     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
557     * 6 bits.
558     */
559    /* shr-long vAA, vBB, vCC */
560    and     r2, r2, #63                 @ r0<- r0 & 0x3f
561    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
562    rsb     r3, r2, #32                 @  r3<- 32 - r2
563    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
564    subs    ip, r2, #32                 @  ip<- r2 - 32
565    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
566    mov     r1, r1, asr r2              @  r1<- r1 >> r2
567    bx      lr
568
569/* ------------------------------ */
570    .balign 4
571    .global dvmCompiler_TEMPLATE_USHR_LONG
572dvmCompiler_TEMPLATE_USHR_LONG:
573/* File: armv5te/TEMPLATE_USHR_LONG.S */
574    /*
575     * Long integer shift.  This is different from the generic 32/64-bit
576     * binary operations because vAA/vBB are 64-bit but vCC (the shift
577     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
578     * 6 bits.
579     */
580    /* ushr-long vAA, vBB, vCC */
581    and     r2, r2, #63                 @ r0<- r0 & 0x3f
582    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
583    rsb     r3, r2, #32                 @  r3<- 32 - r2
584    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
585    subs    ip, r2, #32                 @  ip<- r2 - 32
586    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
587    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
588    bx      lr
589
590/* ------------------------------ */
591    .balign 4
592    .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
593dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
594/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
595/* File: armv5te-vfp/fbinop.S */
596    /*
597     * Generic 32-bit floating point operation.  Provide an "instr" line that
598     * specifies an instruction that performs s2 = s0 op s1.
599     *
600     * On entry:
601     *     r0 = target dalvik register address
602     *     r1 = op1 address
603     *     r2 = op2 address
604     */
605     flds    s0,[r1]
606     flds    s1,[r2]
607     fadds   s2, s0, s1
608     fsts    s2,[r0]
609     bx      lr
610
611
612/* ------------------------------ */
613    .balign 4
614    .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
615dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
616/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
617/* File: armv5te-vfp/fbinop.S */
618    /*
619     * Generic 32-bit floating point operation.  Provide an "instr" line that
620     * specifies an instruction that performs s2 = s0 op s1.
621     *
622     * On entry:
623     *     r0 = target dalvik register address
624     *     r1 = op1 address
625     *     r2 = op2 address
626     */
627     flds    s0,[r1]
628     flds    s1,[r2]
629     fsubs   s2, s0, s1
630     fsts    s2,[r0]
631     bx      lr
632
633
634/* ------------------------------ */
635    .balign 4
636    .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
637dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
638/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
639/* File: armv5te-vfp/fbinop.S */
640    /*
641     * Generic 32-bit floating point operation.  Provide an "instr" line that
642     * specifies an instruction that performs s2 = s0 op s1.
643     *
644     * On entry:
645     *     r0 = target dalvik register address
646     *     r1 = op1 address
647     *     r2 = op2 address
648     */
649     flds    s0,[r1]
650     flds    s1,[r2]
651     fmuls   s2, s0, s1
652     fsts    s2,[r0]
653     bx      lr
654
655
656/* ------------------------------ */
657    .balign 4
658    .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
659dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
660/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
661/* File: armv5te-vfp/fbinop.S */
662    /*
663     * Generic 32-bit floating point operation.  Provide an "instr" line that
664     * specifies an instruction that performs s2 = s0 op s1.
665     *
666     * On entry:
667     *     r0 = target dalvik register address
668     *     r1 = op1 address
669     *     r2 = op2 address
670     */
671     flds    s0,[r1]
672     flds    s1,[r2]
673     fdivs   s2, s0, s1
674     fsts    s2,[r0]
675     bx      lr
676
677
678/* ------------------------------ */
679    .balign 4
680    .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
681dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
682/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
683/* File: armv5te-vfp/fbinopWide.S */
684    /*
685     * Generic 64-bit floating point operation.  Provide an "instr" line that
686     * specifies an instruction that performs s2 = s0 op s1.
687     *
688     * On entry:
689     *     r0 = target dalvik register address
690     *     r1 = op1 address
691     *     r2 = op2 address
692     */
693     fldd    d0,[r1]
694     fldd    d1,[r2]
695     faddd   d2, d0, d1
696     fstd    d2,[r0]
697     bx      lr
698
699
700/* ------------------------------ */
701    .balign 4
702    .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
703dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
704/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
705/* File: armv5te-vfp/fbinopWide.S */
706    /*
707     * Generic 64-bit floating point operation.  Provide an "instr" line that
708     * specifies an instruction that performs s2 = s0 op s1.
709     *
710     * On entry:
711     *     r0 = target dalvik register address
712     *     r1 = op1 address
713     *     r2 = op2 address
714     */
715     fldd    d0,[r1]
716     fldd    d1,[r2]
717     fsubd   d2, d0, d1
718     fstd    d2,[r0]
719     bx      lr
720
721
722/* ------------------------------ */
723    .balign 4
724    .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
725dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
726/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
727/* File: armv5te-vfp/fbinopWide.S */
728    /*
729     * Generic 64-bit floating point operation.  Provide an "instr" line that
730     * specifies an instruction that performs s2 = s0 op s1.
731     *
732     * On entry:
733     *     r0 = target dalvik register address
734     *     r1 = op1 address
735     *     r2 = op2 address
736     */
737     fldd    d0,[r1]
738     fldd    d1,[r2]
739     fmuld   d2, d0, d1
740     fstd    d2,[r0]
741     bx      lr
742
743
744/* ------------------------------ */
745    .balign 4
746    .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
747dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
748/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
749/* File: armv5te-vfp/fbinopWide.S */
750    /*
751     * Generic 64-bit floating point operation.  Provide an "instr" line that
752     * specifies an instruction that performs s2 = s0 op s1.
753     *
754     * On entry:
755     *     r0 = target dalvik register address
756     *     r1 = op1 address
757     *     r2 = op2 address
758     */
759     fldd    d0,[r1]
760     fldd    d1,[r2]
761     fdivd   d2, d0, d1
762     fstd    d2,[r0]
763     bx      lr
764
765
766/* ------------------------------ */
767    .balign 4
768    .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
769dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
770/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
771/* File: armv5te-vfp/funopNarrower.S */
772    /*
773     * Generic 64bit-to-32bit floating point unary operation.  Provide an
774     * "instr" line that specifies an instruction that performs "s0 = op d0".
775     *
776     * For: double-to-int, double-to-float
777     *
778     * On entry:
779     *     r0 = target dalvik register address
780     *     r1 = src dalvik register address
781     */
782    /* unop vA, vB */
783    fldd    d0, [r1]                    @ d0<- vB
784    fcvtsd  s0, d0                              @ s0<- op d0
785    fsts    s0, [r0]                    @ vA<- s0
786    bx      lr
787
788
789/* ------------------------------ */
790    .balign 4
791    .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
792dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
793/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
794/* File: armv5te-vfp/funopNarrower.S */
795    /*
796     * Generic 64bit-to-32bit floating point unary operation.  Provide an
797     * "instr" line that specifies an instruction that performs "s0 = op d0".
798     *
799     * For: double-to-int, double-to-float
800     *
801     * On entry:
802     *     r0 = target dalvik register address
803     *     r1 = src dalvik register address
804     */
805    /* unop vA, vB */
806    fldd    d0, [r1]                    @ d0<- vB
807    ftosizd  s0, d0                              @ s0<- op d0
808    fsts    s0, [r0]                    @ vA<- s0
809    bx      lr
810
811
812/* ------------------------------ */
813    .balign 4
814    .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
815dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
816/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
817/* File: armv5te-vfp/funopWider.S */
818    /*
819     * Generic 32bit-to-64bit floating point unary operation.  Provide an
820     * "instr" line that specifies an instruction that performs "d0 = op s0".
821     *
822     * For: int-to-double, float-to-double
823     *
824     * On entry:
825     *     r0 = target dalvik register address
826     *     r1 = src dalvik register address
827     */
828    /* unop vA, vB */
829    flds    s0, [r1]                    @ s0<- vB
830    fcvtds  d0, s0                              @ d0<- op s0
831    fstd    d0, [r0]                    @ vA<- d0
832    bx      lr
833
834
835/* ------------------------------ */
836    .balign 4
837    .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
838dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
839/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
840/* File: armv5te-vfp/funop.S */
841    /*
842     * Generic 32bit-to-32bit floating point unary operation.  Provide an
843     * "instr" line that specifies an instruction that performs "s1 = op s0".
844     *
845     * For: float-to-int, int-to-float
846     *
847     * On entry:
848     *     r0 = target dalvik register address
849     *     r1 = src dalvik register address
850     */
851    /* unop vA, vB */
852    flds    s0, [r1]                    @ s0<- vB
853    ftosizs s1, s0                              @ s1<- op s0
854    fsts    s1, [r0]                    @ vA<- s1
855    bx      lr
856
857
858/* ------------------------------ */
859    .balign 4
860    .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
861dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
862/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
863/* File: armv5te-vfp/funopWider.S */
864    /*
865     * Generic 32bit-to-64bit floating point unary operation.  Provide an
866     * "instr" line that specifies an instruction that performs "d0 = op s0".
867     *
868     * For: int-to-double, float-to-double
869     *
870     * On entry:
871     *     r0 = target dalvik register address
872     *     r1 = src dalvik register address
873     */
874    /* unop vA, vB */
875    flds    s0, [r1]                    @ s0<- vB
876    fsitod  d0, s0                              @ d0<- op s0
877    fstd    d0, [r0]                    @ vA<- d0
878    bx      lr
879
880
881/* ------------------------------ */
882    .balign 4
883    .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
884dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
885/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
886/* File: armv5te-vfp/funop.S */
887    /*
888     * Generic 32bit-to-32bit floating point unary operation.  Provide an
889     * "instr" line that specifies an instruction that performs "s1 = op s0".
890     *
891     * For: float-to-int, int-to-float
892     *
893     * On entry:
894     *     r0 = target dalvik register address
895     *     r1 = src dalvik register address
896     */
897    /* unop vA, vB */
898    flds    s0, [r1]                    @ s0<- vB
899    fsitos  s1, s0                              @ s1<- op s0
900    fsts    s1, [r0]                    @ vA<- s1
901    bx      lr
902
903
904/* ------------------------------ */
905    .balign 4
906    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
907dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
908/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
909    /*
910     * Compare two floating-point values.  Puts 0, 1, or -1 into the
911     * destination register based on the results of the comparison.
912     *
913     * int compare(x, y) {
914     *     if (x == y) {
915     *         return 0;
916     *     } else if (x < y) {
917     *         return -1;
918     *     } else if (x > y) {
919     *         return 1;
920     *     } else {
921     *         return 1;
922     *     }
923     * }
924     *
925     * On entry:
926     *    r0 = &op1 [vBB]
927     *    r1 = &op2 [vCC]
928     */
929    /* op vAA, vBB, vCC */
930    fldd    d0, [r0]                    @ d0<- vBB
931    fldd    d1, [r1]                    @ d1<- vCC
932    fcmpd  d0, d1                       @ compare (vBB, vCC)
933    mov     r0, #1                      @ r0<- 1 (default)
934    fmstat                              @ export status flags
935    mvnmi   r0, #0                      @ (less than) r0<- -1
936    moveq   r0, #0                      @ (equal) r0<- 0
937    bx      lr
938
939/* ------------------------------ */
940    .balign 4
941    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
942dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
943/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
944    /*
945     * Compare two floating-point values.  Puts 0, 1, or -1 into the
946     * destination register based on the results of the comparison.
947     *
948     * int compare(x, y) {
949     *     if (x == y) {
950     *         return 0;
951     *     } else if (x > y) {
952     *         return 1;
953     *     } else if (x < y) {
954     *         return -1;
955     *     } else {
956     *         return -1;
957     *     }
958     * }
959     * On entry:
960     *    r0 = &op1 [vBB]
961     *    r1 = &op2 [vCC]
962     */
963    /* op vAA, vBB, vCC */
964    fldd    d0, [r0]                    @ d0<- vBB
965    fldd    d1, [r1]                    @ d1<- vCC
966    fcmped  d0, d1                      @ compare (vBB, vCC)
967    mvn     r0, #0                      @ r0<- -1 (default)
968    fmstat                              @ export status flags
969    movgt   r0, #1                      @ (greater than) r0<- 1
970    moveq   r0, #0                      @ (equal) r0<- 0
971    bx      lr
972
973/* ------------------------------ */
974    .balign 4
975    .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
976dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
977/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
978    /*
979     * Compare two floating-point values.  Puts 0, 1, or -1 into the
980     * destination register based on the results of the comparison.
981     *
982     * int compare(x, y) {
983     *     if (x == y) {
984     *         return 0;
985     *     } else if (x < y) {
986     *         return -1;
987     *     } else if (x > y) {
988     *         return 1;
989     *     } else {
990     *         return 1;
991     *     }
992     * }
993     * On entry:
994     *    r0 = &op1 [vBB]
995     *    r1 = &op2 [vCC]
996     */
997    /* op vAA, vBB, vCC */
998    flds    s0, [r0]                    @ d0<- vBB
999    flds    s1, [r1]                    @ d1<- vCC
1000    fcmps  s0, s1                      @ compare (vBB, vCC)
1001    mov     r0, #1                      @ r0<- 1 (default)
1002    fmstat                              @ export status flags
1003    mvnmi   r0, #0                      @ (less than) r0<- -1
1004    moveq   r0, #0                      @ (equal) r0<- 0
1005    bx      lr
1006
1007/* ------------------------------ */
1008    .balign 4
1009    .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
1010dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
1011/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
1012    /*
1013     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1014     * destination register based on the results of the comparison.
1015     *
1016     * int compare(x, y) {
1017     *     if (x == y) {
1018     *         return 0;
1019     *     } else if (x > y) {
1020     *         return 1;
1021     *     } else if (x < y) {
1022     *         return -1;
1023     *     } else {
1024     *         return -1;
1025     *     }
1026     * }
1027     * On entry:
1028     *    r0 = &op1 [vBB]
1029     *    r1 = &op2 [vCC]
1030     */
1031    /* op vAA, vBB, vCC */
1032    flds    s0, [r0]                    @ d0<- vBB
1033    flds    s1, [r1]                    @ d1<- vCC
1034    fcmps  s0, s1                      @ compare (vBB, vCC)
1035    mvn     r0, #0                      @ r0<- -1 (default)
1036    fmstat                              @ export status flags
1037    movgt   r0, #1                      @ (greater than) r0<- 1
1038    moveq   r0, #0                      @ (equal) r0<- 0
1039    bx      lr
1040
1041/* ------------------------------ */
1042    .balign 4
1043    .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
1044dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
1045/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
1046    /*
1047     * 64-bit floating point vfp sqrt operation.
1048     * If the result is a NaN, bail out to library code to do
1049     * the right thing.
1050     *
1051     * On entry:
1052     *     r2 src addr of op1
1053     * On exit:
1054     *     r0,r1 = res
1055     */
1056    fldd    d0, [r2]
1057    fsqrtd  d1, d0
1058    fcmpd   d1, d1
1059    fmstat
1060    fmrrd   r0, r1, d1
1061    bxeq    lr   @ Result OK - return
1062    ldr     r2, .Lsqrt
1063    fmrrd   r0, r1, d0   @ reload orig operand
1064    bx      r2   @ tail call to sqrt library routine
1065
1066.Lsqrt:
1067    .word   sqrt
1068
1069/* ------------------------------ */
1070    .balign 4
1071    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
1072dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
1073/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
1074    /*
1075     * Throw an exception from JIT'ed code.
1076     * On entry:
1077     *    r0    Dalvik PC that raises the exception
1078     */
1079    b       .LhandleException
1080
1081/* ------------------------------ */
1082    .balign 4
1083    .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
1084dvmCompiler_TEMPLATE_MEM_OP_DECODE:
1085/* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */
1086#if defined(WITH_SELF_VERIFICATION)
1087    /*
1088     * This handler encapsulates heap memory ops for selfVerification mode.
1089     *
1090     * The call to the handler is inserted prior to a heap memory operation.
1091     * This handler then calls a function to decode the memory op, and process
1092     * it accordingly. Afterwards, the handler changes the return address to
1093     * skip the memory op so it never gets executed.
1094     */
1095    vpush   {d0-d15}                    @ save out all fp registers
1096    push    {r0-r12,lr}                 @ save out all registers
1097    ldr     r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
1098    mov     r0, lr                      @ arg0 <- link register
1099    mov     r1, sp                      @ arg1 <- stack pointer
1100    blx     r2                          @ decode and handle the mem op
1101    pop     {r0-r12,lr}                 @ restore all registers
1102    vpop    {d0-d15}                    @ restore all fp registers
1103    bx      lr                          @ return to compiled code
1104#endif
1105
1106/* ------------------------------ */
1107    .balign 4
1108    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
1109dvmCompiler_TEMPLATE_STRING_COMPARETO:
1110/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
1111    /*
1112     * String's compareTo.
1113     *
1114     * Requires r0/r1 to have been previously checked for null.  Will
1115     * return negative if this's string is < comp, 0 if they are the
1116     * same and positive if >.
1117     *
1118     * IMPORTANT NOTE:
1119     *
1120     * This code relies on hard-coded offsets for string objects, and must be
1121     * kept in sync with definitions in UtfString.h.  See asm-constants.h
1122     *
1123     * On entry:
1124     *    r0:   this object pointer
1125     *    r1:   comp object pointer
1126     *
1127     */
1128
1129    mov    r2, r0         @ this to r2, opening up r0 for return value
1130    subs   r0, r2, r1     @ Same?
1131    bxeq   lr
1132
1133    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
1134    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
1135    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
1136    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
1137    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
1138    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
1139
1140    /*
1141     * At this point, we have:
1142     *    value:  r2/r1
1143     *    offset: r4/r9
1144     *    count:  r7/r10
1145     * We're going to compute
1146     *    r11 <- countDiff
1147     *    r10 <- minCount
1148     */
1149     subs  r11, r7, r10
1150     movls r10, r7
1151
1152     /* Now, build pointers to the string data */
1153     add   r2, r2, r4, lsl #1
1154     add   r1, r1, r9, lsl #1
1155     /*
1156      * Note: data pointers point to previous element so we can use pre-index
1157      * mode with base writeback.
1158      */
1159     add   r2, #16-2   @ offset to contents[-1]
1160     add   r1, #16-2   @ offset to contents[-1]
1161
1162     /*
1163      * At this point we have:
1164      *   r2: *this string data
1165      *   r1: *comp string data
1166      *   r10: iteration count for comparison
1167      *   r11: value to return if the first part of the string is equal
1168      *   r0: reserved for result
1169      *   r3, r4, r7, r8, r9, r12 available for loading string data
1170      */
1171
1172    subs  r10, #2
1173    blt   do_remainder2
1174
1175      /*
1176       * Unroll the first two checks so we can quickly catch early mismatch
1177       * on long strings (but preserve incoming alignment)
1178       */
1179
1180    ldrh  r3, [r2, #2]!
1181    ldrh  r4, [r1, #2]!
1182    ldrh  r7, [r2, #2]!
1183    ldrh  r8, [r1, #2]!
1184    subs  r0, r3, r4
1185    subeqs  r0, r7, r8
1186    bxne  lr
1187    cmp   r10, #28
1188    bgt   do_memcmp16
1189    subs  r10, #3
1190    blt   do_remainder
1191
1192loopback_triple:
1193    ldrh  r3, [r2, #2]!
1194    ldrh  r4, [r1, #2]!
1195    ldrh  r7, [r2, #2]!
1196    ldrh  r8, [r1, #2]!
1197    ldrh  r9, [r2, #2]!
1198    ldrh  r12,[r1, #2]!
1199    subs  r0, r3, r4
1200    subeqs  r0, r7, r8
1201    subeqs  r0, r9, r12
1202    bxne  lr
1203    subs  r10, #3
1204    bge   loopback_triple
1205
1206do_remainder:
1207    adds  r10, #3
1208    beq   returnDiff
1209
1210loopback_single:
1211    ldrh  r3, [r2, #2]!
1212    ldrh  r4, [r1, #2]!
1213    subs  r0, r3, r4
1214    bxne  lr
1215    subs  r10, #1
1216    bne     loopback_single
1217
1218returnDiff:
1219    mov   r0, r11
1220    bx    lr
1221
1222do_remainder2:
1223    adds  r10, #2
1224    bne   loopback_single
1225    mov   r0, r11
1226    bx    lr
1227
1228    /* Long string case */
1229do_memcmp16:
1230    mov   r4, lr
1231    ldr   lr, .Lmemcmp16
1232    mov   r7, r11
1233    add   r0, r2, #2
1234    add   r1, r1, #2
1235    mov   r2, r10
1236    blx   lr
1237    cmp   r0, #0
1238    bxne  r4
1239    mov   r0, r7
1240    bx    r4
1241
1242.Lmemcmp16:
1243    .word __memcmp16
1244
1245/* ------------------------------ */
1246    .balign 4
1247    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
1248dvmCompiler_TEMPLATE_STRING_INDEXOF:
1249/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
1250    /*
1251     * String's indexOf.
1252     *
1253     * Requires r0 to have been previously checked for null.  Will
1254     * return index of match of r1 in r0.
1255     *
1256     * IMPORTANT NOTE:
1257     *
1258     * This code relies on hard-coded offsets for string objects, and must be
1259     * kept in sync wth definitions in UtfString.h  See asm-constants.h
1260     *
1261     * On entry:
1262     *    r0:   string object pointer
1263     *    r1:   char to match
1264     *    r2:   Starting offset in string data
1265     */
1266
1267    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
1268    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
1269    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
1270
1271    /*
1272     * At this point, we have:
1273     *    r0: object pointer
1274     *    r1: char to match
1275     *    r2: starting offset
1276     *    r7: offset
1277     *    r8: string length
1278     */
1279
1280     /* Build pointer to start of string data */
1281     add   r0, #16
1282     add   r0, r0, r7, lsl #1
1283
1284     /* Save a copy of starting data in r7 */
1285     mov   r7, r0
1286
1287     /* Clamp start to [0..count] */
1288     cmp   r2, #0
1289     movlt r2, #0
1290     cmp   r2, r8
1291     movgt r2, r8
1292
1293     /* Build pointer to start of data to compare and pre-bias */
1294     add   r0, r0, r2, lsl #1
1295     sub   r0, #2
1296
1297     /* Compute iteration count */
1298     sub   r8, r2
1299
1300     /*
1301      * At this point we have:
1302      *   r0: start of data to test
1303      *   r1: chat to compare
1304      *   r8: iteration count
1305      *   r7: original start of string
1306      *   r3, r4, r9, r10, r11, r12 available for loading string data
1307      */
1308
1309    subs  r8, #4
1310    blt   indexof_remainder
1311
1312indexof_loop4:
1313    ldrh  r3, [r0, #2]!
1314    ldrh  r4, [r0, #2]!
1315    ldrh  r10, [r0, #2]!
1316    ldrh  r11, [r0, #2]!
1317    cmp   r3, r1
1318    beq   match_0
1319    cmp   r4, r1
1320    beq   match_1
1321    cmp   r10, r1
1322    beq   match_2
1323    cmp   r11, r1
1324    beq   match_3
1325    subs  r8, #4
1326    bge   indexof_loop4
1327
1328indexof_remainder:
1329    adds    r8, #4
1330    beq     indexof_nomatch
1331
1332indexof_loop1:
1333    ldrh  r3, [r0, #2]!
1334    cmp   r3, r1
1335    beq   match_3
1336    subs  r8, #1
1337    bne   indexof_loop1
1338
1339indexof_nomatch:
1340    mov   r0, #-1
1341    bx    lr
1342
1343match_0:
1344    sub   r0, #6
1345    sub   r0, r7
1346    asr   r0, r0, #1
1347    bx    lr
1348match_1:
1349    sub   r0, #4
1350    sub   r0, r7
1351    asr   r0, r0, #1
1352    bx    lr
1353match_2:
1354    sub   r0, #2
1355    sub   r0, r7
1356    asr   r0, r0, #1
1357    bx    lr
1358match_3:
1359    sub   r0, r7
1360    asr   r0, r0, #1
1361    bx    lr
1362
1363/* ------------------------------ */
1364    .balign 4
1365    .global dvmCompiler_TEMPLATE_INTERPRET
1366dvmCompiler_TEMPLATE_INTERPRET:
1367/* File: armv5te/TEMPLATE_INTERPRET.S */
1368    /*
1369     * This handler transfers control to the interpeter without performing
1370     * any lookups.  It may be called either as part of a normal chaining
1371     * operation, or from the transition code in header.S.  We distinquish
1372     * the two cases by looking at the link register.  If called from a
1373     * translation chain, it will point to the chaining Dalvik PC -3.
1374     * On entry:
1375     *    lr - if NULL:
1376     *        r1 - the Dalvik PC to begin interpretation.
1377     *    else
1378     *        [lr, #3] contains Dalvik PC to begin interpretation
1379     *    rSELF - pointer to thread
1380     *    rFP - Dalvik frame pointer
1381     */
1382    cmp     lr, #0
1383#if defined(WORKAROUND_CORTEX_A9_745320)
1384    /* Don't use conditional loads if the HW defect exists */
1385    beq     101f
1386    ldr     r1,[lr, #3]
1387101:
1388#else
1389    ldrne   r1,[lr, #3]
1390#endif
1391    ldr     r2, .LinterpPunt
1392    mov     r0, r1                       @ set Dalvik PC
1393    bx      r2
1394    @ doesn't return
1395
1396.LinterpPunt:
1397    .word   dvmJitToInterpPunt
1398
1399/* ------------------------------ */
1400    .balign 4
1401    .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1402dvmCompiler_TEMPLATE_MONITOR_ENTER:
1403/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1404    /*
1405     * Call out to the runtime to lock an object.  Because this thread
1406     * may have been suspended in THREAD_MONITOR state and the Jit's
1407     * translation cache subsequently cleared, we cannot return directly.
1408     * Instead, unconditionally transition to the interpreter to resume.
1409     *
1410     * On entry:
1411     *    r0 - self pointer
1412     *    r1 - the object (which has already been null-checked by the caller
1413     *    r4 - the Dalvik PC of the following instruction.
1414     */
1415    ldr     r2, .LdvmLockObject
1416    mov     r3, #0                       @ Record that we're not returning
1417    str     r3, [r0, #offThread_inJitCodeCache]
1418    blx     r2                           @ dvmLockObject(self, obj)
1419    @ refresh Jit's on/off status
1420    ldr     r3, [rSELF, #offThread_ppJitProfTable]
1421    ldr     r3, [r3]
1422    ldr     r2, .LdvmJitToInterpNoChain
1423    str     r3, [rSELF, #offThread_pJitProfTable]
1424    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1425#if defined(WITH_JIT_TUNING)
1426    mov     r0, #kHeavyweightMonitor
1427#endif
1428    bx      r2
1429
1430/* ------------------------------ */
1431    .balign 4
1432    .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1433dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1434/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1435    /*
1436     * To support deadlock prediction, this version of MONITOR_ENTER
1437     * will always call the heavyweight dvmLockObject, check for an
1438     * exception and then bail out to the interpreter.
1439     *
1440     * On entry:
1441     *    r0 - self pointer
1442     *    r1 - the object (which has already been null-checked by the caller
1443     *    r4 - the Dalvik PC of the following instruction.
1444     *
1445     */
1446    ldr     r2, .LdvmLockObject
1447    mov     r3, #0                       @ Record that we're not returning
1448    str     r3, [r0, #offThread_inJitCodeCache]
1449    blx     r2             @ dvmLockObject(self, obj)
1450    @ refresh Jit's on/off status & test for exception
1451    ldr     r3, [rSELF, #offThread_ppJitProfTable]
1452    ldr     r3, [r3]
1453    ldr     r1, [rSELF, #offThread_exception]
1454    str     r3, [rSELF, #offThread_pJitProfTable]
1455    cmp     r1, #0
1456    beq     1f
1457    ldr     r2, .LhandleException
1458    sub     r0, r4, #2     @ roll dPC back to this monitor instruction
1459    bx      r2
14601:
1461    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1462#if defined(WITH_JIT_TUNING)
1463    mov     r0, #kHeavyweightMonitor
1464#endif
1465    ldr     pc, .LdvmJitToInterpNoChain
1466
1467/* ------------------------------ */
1468    .balign 4
1469    .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING
1470dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
1471/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */
1472    /*
1473     * Increment profile counter for this trace, and decrement
1474     * sample counter.  If sample counter goes below zero, turn
1475     * off profiling.
1476     *
1477     * On entry
1478     * (lr-11) is address of pointer to counter.  Note: the counter
1479     *    actually exists 10 bytes before the return target, but because
1480     *    we are arriving from thumb mode, lr will have its low bit set.
1481     */
1482     ldr    r0, [lr,#-11]
1483     ldr    r1, [rSELF, #offThread_pProfileCountdown]
1484     ldr    r2, [r0]                    @ get counter
1485     ldr    r3, [r1]                    @ get countdown timer
1486     add    r2, #1
1487     subs   r2, #1
1488     blt    .LTEMPLATE_PERIODIC_PROFILING_disable_profiling
1489     str    r2, [r0]
1490     str    r3, [r1]
1491     bx     lr
1492
1493.LTEMPLATE_PERIODIC_PROFILING_disable_profiling:
1494     mov    r4, lr                     @ preserve lr
1495     ldr    r0, .LdvmJitTraceProfilingOff
1496     blx    r0
1497     bx     r4
1498
1499/* ------------------------------ */
1500    .balign 4
1501    .global dvmCompiler_TEMPLATE_RETURN_PROF
1502dvmCompiler_TEMPLATE_RETURN_PROF:
1503/* File: armv5te/TEMPLATE_RETURN_PROF.S */
1504#define TEMPLATE_INLINE_PROFILING
1505/* File: armv5te/TEMPLATE_RETURN.S */
1506    /*
1507     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
1508     * If the stored value in returnAddr
1509     * is non-zero, the caller is compiled by the JIT thus return to the
1510     * address in the code cache following the invoke instruction. Otherwise
1511     * return to the special dvmJitToInterpNoChain entry point.
1512     */
1513#if defined(TEMPLATE_INLINE_PROFILING)
1514    stmfd   sp!, {r0-r2,lr}             @ preserve live registers
1515    mov     r0, r6
1516    @ r0=rSELF
1517    mov     lr, pc
1518    ldr     pc, .LdvmFastJavaMethodTraceExit
1519    ldmfd   sp!, {r0-r2,lr}             @ restore live registers
1520#endif
1521    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
1522    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
1523    ldr     r8, [rSELF, #offThread_suspendCount] @ r8<- suspendCount
1524    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
1525#if !defined(WITH_SELF_VERIFICATION)
1526    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
1527#else
1528    mov     r9, #0                      @ disable chaining
1529#endif
1530    ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
1531                                        @ r2<- method we're returning to
1532    cmp     r2, #0                      @ break frame?
1533#if !defined(WITH_SELF_VERIFICATION)
1534    beq     1f                          @ bail to interpreter
1535#else
1536    blxeq   lr                          @ punt to interpreter and compare state
1537#endif
1538    ldr     r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
1539    mov     rFP, r10                    @ publish new FP
1540    ldr     r10, [r2, #offMethod_clazz] @ r10<- method->clazz
1541
1542    str     r2, [rSELF, #offThread_method]@ self->method = newSave->method
1543    ldr     r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
1544    str     rFP, [rSELF, #offThread_curFrame] @ self->curFrame = fp
1545    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
1546    str     r0, [rSELF, #offThread_methodClassDex]
1547    cmp     r8, #0                      @ check the suspendCount
1548    movne   r9, #0                      @ clear the chaining cell address
1549    str     r9, [rSELF, #offThread_inJitCodeCache] @ in code cache or not
1550    cmp     r9, #0                      @ chaining cell exists?
1551    blxne   r9                          @ jump to the chaining cell
1552#if defined(WITH_JIT_TUNING)
1553    mov     r0, #kCallsiteInterpreted
1554#endif
1555    mov     pc, r1                      @ callsite is interpreted
15561:
1557    stmia   rSELF, {rPC, rFP}           @ SAVE_PC_FP_TO_SELF()
1558    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
1559    mov     r1, #0                      @ changeInterp = false
1560    mov     r0, rSELF                   @ Expecting rSELF in r0
1561    blx     r2                          @ exit the interpreter
1562
1563#undef TEMPLATE_INLINE_PROFILING
1564
1565/* ------------------------------ */
1566    .balign 4
1567    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF
1568dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF:
1569/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */
1570#define TEMPLATE_INLINE_PROFILING
1571/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
1572    /*
1573     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
1574     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
1575     * runtime-resolved callee.
1576     */
1577    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
1578    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
1579    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
1580    ldr     r9, [rSELF, #offThread_interpStackEnd]    @ r9<- interpStackEnd
1581    ldr     r8, [rSELF, #offThread_suspendCount] @ r8<- suspendCount
1582    add     r3, r1, #1  @ Thumb addr is odd
1583    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
1584    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
1585    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
1586    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
1587    cmp     r10, r9                     @ bottom < interpStackEnd?
1588    bxlo    lr                          @ return to raise stack overflow excep.
1589    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
1590    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
1591    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
1592    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1593    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
1594    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
1595
1596
1597    @ set up newSaveArea
1598    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
1599    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
1600    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
1601    cmp     r8, #0                      @ suspendCount != 0
1602    bxne    lr                          @ bail to the interpreter
1603    tst     r10, #ACC_NATIVE
1604#if !defined(WITH_SELF_VERIFICATION)
1605    bne     .LinvokeNative
1606#else
1607    bxne    lr                          @ bail to the interpreter
1608#endif
1609
1610    ldr     r10, .LdvmJitToInterpTraceSelectNoChain
1611    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
1612
1613    @ Update "thread" values for the new method
1614    str     r0, [rSELF, #offThread_method]    @ self->method = methodToCall
1615    str     r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
1616    mov     rFP, r1                         @ fp = newFp
1617    str     rFP, [rSELF, #offThread_curFrame]  @ self->curFrame = newFp
1618#if defined(TEMPLATE_INLINE_PROFILING)
1619    stmfd   sp!, {r0-r3}                    @ preserve r0-r3
1620    mov     r1, r6
1621    @ r0=methodToCall, r1=rSELF
1622    mov     lr, pc
1623    ldr     pc, .LdvmFastMethodTraceEnter
1624    ldmfd   sp!, {r0-r3}                    @ restore r0-r3
1625#endif
1626
1627    @ Start executing the callee
1628#if defined(WITH_JIT_TUNING)
1629    mov     r0, #kInlineCacheMiss
1630#endif
1631    mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
1632
1633#undef TEMPLATE_INLINE_PROFILING
1634
1635/* ------------------------------ */
1636    .balign 4
1637    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF
1638dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF:
1639/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */
1640#define TEMPLATE_INLINE_PROFILING
1641/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
1642    /*
1643     * For monomorphic callsite, setup the Dalvik frame and return to the
1644     * Thumb code through the link register to transfer control to the callee
1645     * method through a dedicated chaining cell.
1646     */
1647    @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
1648    @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
1649    @ methodToCall is guaranteed to be non-native
1650.LinvokeChainProf:
1651    ldr     r9, [rSELF, #offThread_interpStackEnd]    @ r9<- interpStackEnd
1652    ldr     r8, [rSELF, #offThread_suspendCount]      @ r8<- suspendCount
1653    add     r3, r1, #1  @ Thumb addr is odd
1654    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
1655    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
1656    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
1657    add     r12, lr, #2                 @ setup the punt-to-interp address
1658    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
1659    cmp     r10, r9                     @ bottom < interpStackEnd?
1660    bxlo    r12                         @ return to raise stack overflow excep.
1661    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
1662    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
1663    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1664    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
1665
1666    @ set up newSaveArea
1667    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
1668    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
1669    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
1670    cmp     r8, #0                      @ suspendCount != 0
1671    bxne    r12                         @ bail to the interpreter
1672
1673    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
1674
1675    @ Update "thread" values for the new method
1676    str     r0, [rSELF, #offThread_method]    @ self->method = methodToCall
1677    str     r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
1678    mov     rFP, r1                         @ fp = newFp
1679    str     rFP, [rSELF, #offThread_curFrame]  @ self->curFrame = newFp
1680#if defined(TEMPLATE_INLINE_PROFILING)
1681    stmfd   sp!, {r0-r2,lr}             @ preserve clobbered live registers
1682    mov     r1, r6
1683    @ r0=methodToCall, r1=rSELF
1684    mov     lr, pc
1685    ldr     pc, .LdvmFastMethodTraceEnter
1686    ldmfd   sp!, {r0-r2,lr}             @ restore registers
1687#endif
1688
1689    bx      lr                              @ return to the callee-chaining cell
1690
1691#undef TEMPLATE_INLINE_PROFILING
1692
1693/* ------------------------------ */
1694    .balign 4
1695    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF
1696dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF:
1697/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */
1698#define TEMPLATE_INLINE_PROFILING
1699/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
1700    /*
1701     * For polymorphic callsite, check whether the cached class pointer matches
1702     * the current one. If so setup the Dalvik frame and return to the
1703     * Thumb code through the link register to transfer control to the callee
1704     * method through a dedicated chaining cell.
1705     *
1706     * The predicted chaining cell is declared in ArmLIR.h with the
1707     * following layout:
1708     *
1709     *  typedef struct PredictedChainingCell {
1710     *      u4 branch;
1711     *      const ClassObject *clazz;
1712     *      const Method *method;
1713     *      u4 counter;
1714     *  } PredictedChainingCell;
1715     *
1716     * Upon returning to the callsite:
1717     *    - lr  : to branch to the chaining cell
1718     *    - lr+2: to punt to the interpreter
1719     *    - lr+4: to fully resolve the callee and may rechain.
1720     *            r3 <- class
1721     *            r9 <- counter
1722     */
1723    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
1724    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
1725    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
1726    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
1727    ldr     r9, [rSELF, #offThread_icRechainCount] @ r1 <- shared rechainCount
1728    cmp     r3, r8          @ predicted class == actual class?
1729#if defined(WITH_JIT_TUNING)
1730    ldr     r7, .LdvmICHitCount
1731#if defined(WORKAROUND_CORTEX_A9_745320)
1732    /* Don't use conditional loads if the HW defect exists */
1733    bne     101f
1734    ldr     r10, [r7, #0]
1735101:
1736#else
1737    ldreq   r10, [r7, #0]
1738#endif
1739    add     r10, r10, #1
1740    streq   r10, [r7, #0]
1741#endif
1742    ldreqh  r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
1743    ldreqh  r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
1744    beq     .LinvokeChainProf   @ predicted chain is valid
1745    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
1746    cmp     r8, #0          @ initialized class or not
1747    moveq   r1, #0
1748    subne   r1, r9, #1      @ count--
1749    strne   r1, [rSELF, #offThread_icRechainCount]  @ write back to thread
1750    add     lr, lr, #4      @ return to fully-resolve landing pad
1751    /*
1752     * r1 <- count
1753     * r2 <- &predictedChainCell
1754     * r3 <- this->class
1755     * r4 <- dPC
1756     * r7 <- this->class->vtable
1757     */
1758    bx      lr
1759
1760#undef TEMPLATE_INLINE_PROFILING
1761
1762/* ------------------------------ */
1763    .balign 4
1764    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF
1765dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF:
1766/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */
1767#define TEMPLATE_INLINE_PROFILING
1768/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
1769    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
1770    @ r7 = methodToCall->registersSize
1771    ldr     r9, [rSELF, #offThread_interpStackEnd]    @ r9<- interpStackEnd
1772    ldr     r8, [rSELF, #offThread_suspendCount]      @ r8<- suspendCount
1773    add     r3, r1, #1  @ Thumb addr is odd
1774    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
1775    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
1776    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
1777    cmp     r10, r9                     @ bottom < interpStackEnd?
1778    bxlo    lr                          @ return to raise stack overflow excep.
1779    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
1780    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1781    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
1782
1783    @ set up newSaveArea
1784    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
1785    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
1786    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
1787    cmp     r8, #0                      @ suspendCount != 0
1788    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
1789#if !defined(WITH_SELF_VERIFICATION)
1790    bxne    lr                          @ bail to the interpreter
1791#else
1792    bx      lr                          @ bail to interpreter unconditionally
1793#endif
1794
1795    @ go ahead and transfer control to the native code
1796    ldr     r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
1797    mov     r2, #0
1798    str     r1, [rSELF, #offThread_curFrame]   @ self->curFrame = newFp
1799    str     r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
1800    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1801                                        @ newFp->localRefCookie=top
1802    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1803
1804    mov     r2, r0                        @ arg2<- methodToCall
1805    mov     r0, r1                        @ arg0<- newFP
1806    add     r1, rSELF, #offThread_retval  @ arg1<- &retval
1807    mov     r3, rSELF                     @ arg3<- self
1808#if defined(TEMPLATE_INLINE_PROFILING)
1809    @ r2=methodToCall, r6=rSELF
1810    stmfd   sp!, {r2,r6}                @ to be consumed after JNI return
1811    stmfd   sp!, {r0-r3}                @ preserve r0-r3
1812    mov     r0, r2
1813    mov     r1, r6
1814    @ r0=JNIMethod, r1=rSELF
1815    mov     lr, pc
1816    ldr     pc, .LdvmFastMethodTraceEnter
1817    ldmfd   sp!, {r0-r3}                @ restore r0-r3
1818#endif
1819
1820    blx     r8                          @ off to the native code
1821
1822#if defined(TEMPLATE_INLINE_PROFILING)
1823    ldmfd   sp!, {r0-r1}                @ restore r2 and r6
1824    @ r0=JNIMethod, r1=rSELF
1825    mov     lr, pc
1826    ldr     pc, .LdvmFastNativeMethodTraceExit
1827#endif
1828    @ native return; r10=newSaveArea
1829    @ equivalent to dvmPopJniLocals
1830    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1831    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1832    ldr     r1, [rSELF, #offThread_exception] @ check for exception
1833    str     rFP, [rSELF, #offThread_curFrame]  @ self->curFrame = fp
1834    cmp     r1, #0                      @ null?
1835    str     r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
1836    ldr     r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1837
1838    @ r0 = dalvikCallsitePC
1839    bne     .LhandleException           @ no, handle exception
1840
1841    str     r2, [rSELF, #offThread_inJitCodeCache] @ set the mode properly
1842    cmp     r2, #0                      @ return chaining cell still exists?
1843    bxne    r2                          @ yes - go ahead
1844
1845    @ continue executing the next instruction through the interpreter
1846    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1847    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
1848#if defined(WITH_JIT_TUNING)
1849    mov     r0, #kCallsiteInterpreted
1850#endif
1851    mov     pc, r1
1852
1853#undef TEMPLATE_INLINE_PROFILING
1854
1855    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1856/* File: armv5te/footer.S */
1857/*
1858 * ===========================================================================
1859 *  Common subroutines and data
1860 * ===========================================================================
1861 */
1862
1863    .text
1864    .align  2
1865.LinvokeNative:
1866    @ Prep for the native call
1867    @ r1 = newFP, r0 = methodToCall
1868    mov     r2, #0
1869    ldr     r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
1870    str     r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache
1871    str     r1, [rSELF, #offThread_curFrame]   @ self->curFrame = newFp
1872    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1873                                        @ newFp->localRefCookie=top
1874    ldr     lr, [rSELF, #offThread_pInterpBreak]
1875    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1876
1877    mov     r2, r0                      @ r2<- methodToCall
1878    ldr     lr, [lr]                    @ lr<- set of active profilers
1879    mov     r0, r1                      @ r0<- newFP
1880    add     r1, rSELF, #offThread_retval  @ r1<- &retval
1881    mov     r3, rSELF                   @ arg3<- self
1882    ands    lr, #kSubModeMethodTrace
1883    beq     121f                        @ hop if not profiling
1884    @ r2: methodToCall, r6: rSELF
1885    stmfd   sp!, {r2,r6}
1886    stmfd   sp!, {r0-r3}
1887    mov     r0, r2
1888    mov     r1, r6
1889    mov     lr, pc
1890    ldr     pc, .LdvmFastMethodTraceEnter
1891    ldmfd   sp!, {r0-r3}
1892
1893    mov     lr, pc
1894    ldr     pc, [r2, #offMethod_nativeFunc]
1895
1896    ldmfd   sp!, {r0-r1}
1897    mov     lr, pc
1898    ldr     pc, .LdvmFastNativeMethodTraceExit
1899    b       212f
1900121:
1901    mov     lr, pc
1902    ldr     pc, [r2, #offMethod_nativeFunc]
1903212:
1904    @ Refresh Jit's on/off status
1905    ldr     r3, [rSELF, #offThread_ppJitProfTable]
1906
1907    @ native return; r10=newSaveArea
1908    @ equivalent to dvmPopJniLocals
1909    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1910    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1911    ldr     r1, [rSELF, #offThread_exception] @ check for exception
1912    ldr     r3, [r3]    @ r1 <- pointer to Jit profile table
1913    str     rFP, [rSELF, #offThread_curFrame]  @ self->curFrame = fp
1914    cmp     r1, #0                      @ null?
1915    str     r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
1916    str     r3, [rSELF, #offThread_pJitProfTable]  @ cache current JitProfTable
1917    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1918
1919    @ r0 = dalvikCallsitePC
1920    bne     .LhandleException           @ no, handle exception
1921
1922    str     r2, [rSELF, #offThread_inJitCodeCache] @ set the new mode
1923    cmp     r2, #0                      @ return chaining cell still exists?
1924    bxne    r2                          @ yes - go ahead
1925
1926    @ continue executing the next instruction through the interpreter
1927    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1928    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
1929#if defined(WITH_JIT_TUNING)
1930    mov     r0, #kCallsiteInterpreted
1931#endif
1932    mov     pc, r1
1933
1934/*
1935 * On entry:
1936 * r0  Faulting Dalvik PC
1937 */
1938.LhandleException:
1939#if defined(WITH_SELF_VERIFICATION)
1940    ldr     pc, .LdeadFood @ should not see this under self-verification mode
1941.LdeadFood:
1942    .word   0xdeadf00d
1943#endif
1944    mov     r2, #0
1945    str     r2, [rSELF, #offThread_inJitCodeCache] @ in interpreter land
1946    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1947    ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1948    mov     rPC, r0                 @ reload the faulting Dalvik address
1949    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1950
1951    .align  2
1952.LdvmAsmInstructionStart:
1953    .word   dvmAsmInstructionStart
1954.LdvmJitToInterpNoChainNoProfile:
1955    .word   dvmJitToInterpNoChainNoProfile
1956.LdvmJitToInterpTraceSelectNoChain:
1957    .word   dvmJitToInterpTraceSelectNoChain
1958.LdvmJitToInterpNoChain:
1959    .word   dvmJitToInterpNoChain
1960.LdvmMterpStdBail:
1961    .word   dvmMterpStdBail
1962.LdvmMterpCommonExceptionThrown:
1963    .word   dvmMterpCommonExceptionThrown
1964.LdvmLockObject:
1965    .word   dvmLockObject
1966.LdvmJitTraceProfilingOff:
1967    .word   dvmJitTraceProfilingOff
1968#if defined(WITH_JIT_TUNING)
1969.LdvmICHitCount:
1970    .word   gDvmICHitCount
1971#endif
1972#if defined(WITH_SELF_VERIFICATION)
1973.LdvmSelfVerificationMemOpDecode:
1974    .word   dvmSelfVerificationMemOpDecode
1975#endif
1976.LdvmFastMethodTraceEnter:
1977    .word   dvmFastMethodTraceEnter
1978.LdvmFastNativeMethodTraceExit:
1979    .word   dvmFastNativeMethodTraceExit
1980.LdvmFastJavaMethodTraceExit:
1981    .word   dvmFastJavaMethodTraceExit
1982.L__aeabi_cdcmple:
1983    .word   __aeabi_cdcmple
1984.L__aeabi_cfcmple:
1985    .word   __aeabi_cfcmple
1986
1987    .global dmvCompilerTemplateEnd
1988dmvCompilerTemplateEnd:
1989
1990#endif /* WITH_JIT */
1991
1992