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