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