CompilerTemplateAsm-armv5te.S revision 7a2697d327936e20ef5484f7819e2e4bf91c891f
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    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
181    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
182    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
183    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
184#if !defined(WITH_SELF_VERIFICATION)
185    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
186#else
187    mov     r9, #0                      @ disable chaining
188#endif
189    ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
190                                        @ r2<- method we're returning to
191    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
192    cmp     r2, #0                      @ break frame?
193#if !defined(WITH_SELF_VERIFICATION)
194    beq     1f                          @ bail to interpreter
195#else
196    blxeq   lr                          @ punt to interpreter and compare state
197#endif
198    ldr     r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
199    mov     rFP, r10                    @ publish new FP
200    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
201    ldr     r8, [r8]                    @ r8<- suspendCount
202
203    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
204    ldr     r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
205    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
206    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
207    str     r0, [rGLUE, #offGlue_methodClassDex]
208    cmp     r8, #0                      @ check the suspendCount
209    movne   r9, #0                      @ clear the chaining cell address
210    str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
211    cmp     r9, #0                      @ chaining cell exists?
212    blxne   r9                          @ jump to the chaining cell
213#if defined(WITH_JIT_TUNING)
214    mov     r0, #kCallsiteInterpreted
215#endif
216    mov     pc, r1                      @ callsite is interpreted
2171:
218    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
219    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
220    mov     r1, #0                      @ changeInterp = false
221    mov     r0, rGLUE                   @ Expecting rGLUE in r0
222    blx     r2                          @ exit the interpreter
223
224/* ------------------------------ */
225    .balign 4
226    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
227dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
228/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
229    /*
230     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
231     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
232     * runtime-resolved callee.
233     */
234    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
235    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
236    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
237    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
238    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
239    add     r3, r1, #1  @ Thumb addr is odd
240    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
241    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
242    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
243    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
244    ldr     r8, [r8]                    @ r8<- suspendCount (int)
245    cmp     r10, r9                     @ bottom < interpStackEnd?
246    bxlo    lr                          @ return to raise stack overflow excep.
247    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
248    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
249    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
250    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
251    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
252    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
253
254
255    @ set up newSaveArea
256    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
257    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
258    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
259    cmp     r8, #0                      @ suspendCount != 0
260    bxne    lr                          @ bail to the interpreter
261    tst     r10, #ACC_NATIVE
262#if !defined(WITH_SELF_VERIFICATION)
263    bne     .LinvokeNative
264#else
265    bxne    lr                          @ bail to the interpreter
266#endif
267
268    ldr     r10, .LdvmJitToInterpTraceSelectNoChain
269    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
270    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
271
272    @ Update "glue" values for the new method
273    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
274    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
275    mov     rFP, r1                         @ fp = newFp
276    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
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, rPC = dalvikCallsite
295    @ methodToCall is guaranteed to be non-native
296.LinvokeChain:
297    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
298    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
299    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
300    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
301    add     r3, r1, #1  @ Thumb addr is odd
302    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
303    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
304    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
305    add     r12, lr, #2                 @ setup the punt-to-interp address
306    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
307    ldr     r8, [r8]                    @ r8<- suspendCount (int)
308    cmp     r10, r9                     @ bottom < interpStackEnd?
309    bxlo    r12                         @ return to raise stack overflow excep.
310    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
311    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
312    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
313    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
314    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
315
316
317    @ set up newSaveArea
318    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
319    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
320    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
321    cmp     r8, #0                      @ suspendCount != 0
322    bxne    r12                         @ bail to the interpreter
323
324    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
325    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
326
327    @ Update "glue" values for the new method
328    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
329    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
330    mov     rFP, r1                         @ fp = newFp
331    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
332
333    bx      lr                              @ return to the callee-chaining cell
334
335/* ------------------------------ */
336    .balign 4
337    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
338dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
339/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
340    /*
341     * For polymorphic callsite, check whether the cached class pointer matches
342     * the current one. If so setup the Dalvik frame and return to the
343     * Thumb code through the link register to transfer control to the callee
344     * method through a dedicated chaining cell.
345     *
346     * The predicted chaining cell is declared in ArmLIR.h with the
347     * following layout:
348     *
349     *  typedef struct PredictedChainingCell {
350     *      u4 branch;
351     *      const ClassObject *clazz;
352     *      const Method *method;
353     *      u4 counter;
354     *  } PredictedChainingCell;
355     *
356     * Upon returning to the callsite:
357     *    - lr  : to branch to the chaining cell
358     *    - lr+2: to punt to the interpreter
359     *    - lr+4: to fully resolve the callee and may rechain.
360     *            r3 <- class
361     *            r9 <- counter
362     */
363    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
364    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
365    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
366    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
367    ldr     r9, [rGLUE, #offGlue_icRechainCount]   @ r1 <- shared rechainCount
368    cmp     r3, r8          @ predicted class == actual class?
369#if defined(WITH_JIT_TUNING)
370    ldr     r7, .LdvmICHitCount
371    ldreq   r10, [r7, #0]
372    add     r10, r10, #1
373    streq   r10, [r7, #0]
374#endif
375    beq     .LinvokeChain   @ predicted chain is valid
376    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
377    cmp     r8, #0          @ initialized class or not
378    moveq   r1, #0
379    subne   r1, r9, #1      @ count--
380    strne   r1, [rGLUE, #offGlue_icRechainCount]   @ write back to InterpState
381    add     lr, lr, #4      @ return to fully-resolve landing pad
382    /*
383     * r1 <- count
384     * r2 <- &predictedChainCell
385     * r3 <- this->class
386     * r4 <- dPC
387     * r7 <- this->class->vtable
388     */
389    bx      lr
390
391/* ------------------------------ */
392    .balign 4
393    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
394dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
395/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
396    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
397    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
398    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
399    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
400    add     r3, r1, #1  @ Thumb addr is odd
401    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
402    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
403    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
404    ldr     r8, [r8]                    @ r3<- suspendCount (int)
405    cmp     r10, r9                     @ bottom < interpStackEnd?
406    bxlo    lr                          @ return to raise stack overflow excep.
407    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
408    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
409    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
410    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
411
412
413    @ set up newSaveArea
414    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
415    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
416    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
417    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
418    cmp     r8, #0                      @ suspendCount != 0
419    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
420#if !defined(WITH_SELF_VERIFICATION)
421    bxne    lr                          @ bail to the interpreter
422#else
423    bx      lr                          @ bail to interpreter unconditionally
424#endif
425
426    @ go ahead and transfer control to the native code
427    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
428    mov     r2, #0
429    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
430    str     r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
431    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
432                                        @ newFp->localRefCookie=top
433    mov     r9, r3                      @ r9<- glue->self (preserve)
434    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
435
436    mov     r2, r0                      @ r2<- methodToCall
437    mov     r0, r1                      @ r0<- newFP
438    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
439
440    blx     r8                          @ off to the native code
441
442    @ native return; r9=self, r10=newSaveArea
443    @ equivalent to dvmPopJniLocals
444    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
445    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
446    ldr     r1, [r9, #offThread_exception] @ check for exception
447    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
448    cmp     r1, #0                      @ null?
449    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
450    ldr     r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
451
452    @ r0 = dalvikCallsitePC
453    bne     .LhandleException           @ no, handle exception
454
455    str     r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
456    cmp     r2, #0                      @ return chaining cell still exists?
457    bxne    r2                          @ yes - go ahead
458
459    @ continue executing the next instruction through the interpreter
460    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
461    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
462#if defined(WITH_JIT_TUNING)
463    mov     r0, #kCallsiteInterpreted
464#endif
465    mov     pc, r1
466
467/* ------------------------------ */
468    .balign 4
469    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE
470dvmCompiler_TEMPLATE_CMPG_DOUBLE:
471/* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */
472/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
473    /*
474     * For the JIT: incoming arguments in r0-r1, r2-r3
475     *              result in r0
476     *
477     * Compare two floating-point values.  Puts 0, 1, or -1 into the
478     * destination register based on the results of the comparison.
479     *
480     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
481     * on what value we'd like to return when one of the operands is NaN.
482     *
483     * See OP_CMPL_FLOAT for an explanation.
484     *
485     * For: cmpl-double, cmpg-double
486     */
487    /* op vAA, vBB, vCC */
488    push    {r0-r3}                     @ save operands
489    mov     r11, lr                     @ save return address
490    LDR_PC_LR ".L__aeabi_cdcmple"       @ PIC way of "bl __aeabi_cdcmple"
491    bhi     .LTEMPLATE_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
492    mvncc   r0, #0                      @ (less than) r1<- -1
493    moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
494    add     sp, #16                     @ drop unused operands
495    bx      r11
496
497    @ Test for NaN with a second comparison.  EABI forbids testing bit
498    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
499    @ make the library call.
500.LTEMPLATE_CMPG_DOUBLE_gt_or_nan:
501    pop     {r2-r3}                     @ restore operands in reverse order
502    pop     {r0-r1}                     @ restore operands in reverse order
503    LDR_PC_LR ".L__aeabi_cdcmple"       @ r0<- Z set if eq, C clear if <
504    movcc   r0, #1                      @ (greater than) r1<- 1
505    bxcc    r11
506    mov     r0, #1                            @ r1<- 1 or -1 for NaN
507    bx      r11
508
509
510/* ------------------------------ */
511    .balign 4
512    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE
513dvmCompiler_TEMPLATE_CMPL_DOUBLE:
514/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
515    /*
516     * For the JIT: incoming arguments in r0-r1, r2-r3
517     *              result in r0
518     *
519     * Compare two floating-point values.  Puts 0, 1, or -1 into the
520     * destination register based on the results of the comparison.
521     *
522     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
523     * on what value we'd like to return when one of the operands is NaN.
524     *
525     * See OP_CMPL_FLOAT for an explanation.
526     *
527     * For: cmpl-double, cmpg-double
528     */
529    /* op vAA, vBB, vCC */
530    push    {r0-r3}                     @ save operands
531    mov     r11, lr                     @ save return address
532    LDR_PC_LR ".L__aeabi_cdcmple"       @ PIC way of "bl __aeabi_cdcmple"
533    bhi     .LTEMPLATE_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
534    mvncc   r0, #0                      @ (less than) r1<- -1
535    moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
536    add     sp, #16                     @ drop unused operands
537    bx      r11
538
539    @ Test for NaN with a second comparison.  EABI forbids testing bit
540    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
541    @ make the library call.
542.LTEMPLATE_CMPL_DOUBLE_gt_or_nan:
543    pop     {r2-r3}                     @ restore operands in reverse order
544    pop     {r0-r1}                     @ restore operands in reverse order
545    LDR_PC_LR ".L__aeabi_cdcmple"       @ r0<- Z set if eq, C clear if <
546    movcc   r0, #1                      @ (greater than) r1<- 1
547    bxcc    r11
548    mvn     r0, #0                            @ r1<- 1 or -1 for NaN
549    bx      r11
550
551/* ------------------------------ */
552    .balign 4
553    .global dvmCompiler_TEMPLATE_CMPG_FLOAT
554dvmCompiler_TEMPLATE_CMPG_FLOAT:
555/* File: armv5te/TEMPLATE_CMPG_FLOAT.S */
556/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
557    /*
558     * For the JIT: incoming arguments in r0-r1, r2-r3
559     *              result in r0
560     *
561     * Compare two floating-point values.  Puts 0, 1, or -1 into the
562     * destination register based on the results of the comparison.
563     *
564     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
565     * on what value we'd like to return when one of the operands is NaN.
566     *
567     * The operation we're implementing is:
568     *   if (x == y)
569     *     return 0;
570     *   else if (x < y)
571     *     return -1;
572     *   else if (x > y)
573     *     return 1;
574     *   else
575     *     return {-1,1};  // one or both operands was NaN
576     *
577     * The straightforward implementation requires 3 calls to functions
578     * that return a result in r0.  We can do it with two calls if our
579     * EABI library supports __aeabi_cfcmple (only one if we want to check
580     * for NaN directly):
581     *   check x <= y
582     *     if <, return -1
583     *     if ==, return 0
584     *   check y <= x
585     *     if <, return 1
586     *   return {-1,1}
587     *
588     * for: cmpl-float, cmpg-float
589     */
590    /* op vAA, vBB, vCC */
591    mov     r9, r0                      @ Save copies - we may need to redo
592    mov     r10, r1
593    mov     r11, lr                     @ save return address
594    LDR_PC_LR ".L__aeabi_cfcmple"       @ cmp <=: C clear if <, Z set if eq
595    bhi     .LTEMPLATE_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
596    mvncc   r0, #0                      @ (less than) r0<- -1
597    moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
598    bx      r11
599    @ Test for NaN with a second comparison.  EABI forbids testing bit
600    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
601    @ make the library call.
602.LTEMPLATE_CMPG_FLOAT_gt_or_nan:
603    mov     r0, r10                     @ restore in reverse order
604    mov     r1, r9
605    LDR_PC_LR ".L__aeabi_cfcmple"       @ r0<- Z set if eq, C clear if <
606    movcc   r0, #1                      @ (greater than) r1<- 1
607    bxcc    r11
608    mov     r0, #1                            @ r1<- 1 or -1 for NaN
609    bx      r11
610
611
612/* ------------------------------ */
613    .balign 4
614    .global dvmCompiler_TEMPLATE_CMPL_FLOAT
615dvmCompiler_TEMPLATE_CMPL_FLOAT:
616/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
617    /*
618     * For the JIT: incoming arguments in r0-r1, r2-r3
619     *              result in r0
620     *
621     * Compare two floating-point values.  Puts 0, 1, or -1 into the
622     * destination register based on the results of the comparison.
623     *
624     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
625     * on what value we'd like to return when one of the operands is NaN.
626     *
627     * The operation we're implementing is:
628     *   if (x == y)
629     *     return 0;
630     *   else if (x < y)
631     *     return -1;
632     *   else if (x > y)
633     *     return 1;
634     *   else
635     *     return {-1,1};  // one or both operands was NaN
636     *
637     * The straightforward implementation requires 3 calls to functions
638     * that return a result in r0.  We can do it with two calls if our
639     * EABI library supports __aeabi_cfcmple (only one if we want to check
640     * for NaN directly):
641     *   check x <= y
642     *     if <, return -1
643     *     if ==, return 0
644     *   check y <= x
645     *     if <, return 1
646     *   return {-1,1}
647     *
648     * for: cmpl-float, cmpg-float
649     */
650    /* op vAA, vBB, vCC */
651    mov     r9, r0                      @ Save copies - we may need to redo
652    mov     r10, r1
653    mov     r11, lr                     @ save return address
654    LDR_PC_LR ".L__aeabi_cfcmple"       @ cmp <=: C clear if <, Z set if eq
655    bhi     .LTEMPLATE_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
656    mvncc   r0, #0                      @ (less than) r0<- -1
657    moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
658    bx      r11
659    @ Test for NaN with a second comparison.  EABI forbids testing bit
660    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
661    @ make the library call.
662.LTEMPLATE_CMPL_FLOAT_gt_or_nan:
663    mov     r0, r10                     @ restore in reverse order
664    mov     r1, r9
665    LDR_PC_LR ".L__aeabi_cfcmple"       @ r0<- Z set if eq, C clear if <
666    movcc   r0, #1                      @ (greater than) r1<- 1
667    bxcc    r11
668    mvn     r0, #0                            @ r1<- 1 or -1 for NaN
669    bx      r11
670
671/* ------------------------------ */
672    .balign 4
673    .global dvmCompiler_TEMPLATE_MUL_LONG
674dvmCompiler_TEMPLATE_MUL_LONG:
675/* File: armv5te/TEMPLATE_MUL_LONG.S */
676    /*
677     * Signed 64-bit integer multiply.
678     *
679     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
680     *
681     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
682     *        WX
683     *      x YZ
684     *  --------
685     *     ZW ZX
686     *  YW YX
687     *
688     * The low word of the result holds ZX, the high word holds
689     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
690     * it doesn't fit in the low 64 bits.
691     *
692     * Unlike most ARM math operations, multiply instructions have
693     * restrictions on using the same register more than once (Rd and Rm
694     * cannot be the same).
695     */
696    /* mul-long vAA, vBB, vCC */
697    mul     ip, r2, r1                  @  ip<- ZxW
698    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
699    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
700    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
701    mov     r0,r9
702    mov     r1,r10
703    bx      lr
704
705/* ------------------------------ */
706    .balign 4
707    .global dvmCompiler_TEMPLATE_SHL_LONG
708dvmCompiler_TEMPLATE_SHL_LONG:
709/* File: armv5te/TEMPLATE_SHL_LONG.S */
710    /*
711     * Long integer shift.  This is different from the generic 32/64-bit
712     * binary operations because vAA/vBB are 64-bit but vCC (the shift
713     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
714     * 6 bits.
715     */
716    /* shl-long vAA, vBB, vCC */
717    and     r2, r2, #63                 @ r2<- r2 & 0x3f
718    mov     r1, r1, asl r2              @  r1<- r1 << r2
719    rsb     r3, r2, #32                 @  r3<- 32 - r2
720    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
721    subs    ip, r2, #32                 @  ip<- r2 - 32
722    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
723    mov     r0, r0, asl r2              @  r0<- r0 << r2
724    bx      lr
725
726/* ------------------------------ */
727    .balign 4
728    .global dvmCompiler_TEMPLATE_SHR_LONG
729dvmCompiler_TEMPLATE_SHR_LONG:
730/* File: armv5te/TEMPLATE_SHR_LONG.S */
731    /*
732     * Long integer shift.  This is different from the generic 32/64-bit
733     * binary operations because vAA/vBB are 64-bit but vCC (the shift
734     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
735     * 6 bits.
736     */
737    /* shr-long vAA, vBB, vCC */
738    and     r2, r2, #63                 @ r0<- r0 & 0x3f
739    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
740    rsb     r3, r2, #32                 @  r3<- 32 - r2
741    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
742    subs    ip, r2, #32                 @  ip<- r2 - 32
743    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
744    mov     r1, r1, asr r2              @  r1<- r1 >> r2
745    bx      lr
746
747/* ------------------------------ */
748    .balign 4
749    .global dvmCompiler_TEMPLATE_USHR_LONG
750dvmCompiler_TEMPLATE_USHR_LONG:
751/* File: armv5te/TEMPLATE_USHR_LONG.S */
752    /*
753     * Long integer shift.  This is different from the generic 32/64-bit
754     * binary operations because vAA/vBB are 64-bit but vCC (the shift
755     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
756     * 6 bits.
757     */
758    /* ushr-long vAA, vBB, vCC */
759    and     r2, r2, #63                 @ r0<- r0 & 0x3f
760    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
761    rsb     r3, r2, #32                 @  r3<- 32 - r2
762    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
763    subs    ip, r2, #32                 @  ip<- r2 - 32
764    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
765    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
766    bx      lr
767
768/* ------------------------------ */
769    .balign 4
770    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
771dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
772/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
773    /*
774     * Throw an exception from JIT'ed code.
775     * On entry:
776     *    r0    Dalvik PC that raises the exception
777     */
778    b       .LhandleException
779
780/* ------------------------------ */
781    .balign 4
782    .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
783dvmCompiler_TEMPLATE_MEM_OP_DECODE:
784/* File: armv5te/TEMPLATE_MEM_OP_DECODE.S */
785#if defined(WITH_SELF_VERIFICATION)
786    /*
787     * This handler encapsulates heap memory ops for selfVerification mode.
788     *
789     * The call to the handler is inserted prior to a heap memory operation.
790     * This handler then calls a function to decode the memory op, and process
791     * it accordingly. Afterwards, the handler changes the return address to
792     * skip the memory op so it never gets executed.
793     */
794    push    {r0-r12,lr}                 @ save out all registers
795    mov     r0, lr                      @ arg0 <- link register
796    mov     r1, sp                      @ arg1 <- stack pointer
797    ldr     r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
798    blx     r2                          @ decode and handle the mem op
799    pop     {r0-r12,lr}                 @ restore all registers
800    bx      lr                          @ return to compiled code
801#endif
802
803/* ------------------------------ */
804    .balign 4
805    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
806dvmCompiler_TEMPLATE_STRING_COMPARETO:
807/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
808    /*
809     * String's compareTo.
810     *
811     * Requires r0/r1 to have been previously checked for null.  Will
812     * return negative if this's string is < comp, 0 if they are the
813     * same and positive if >.
814     *
815     * IMPORTANT NOTE:
816     *
817     * This code relies on hard-coded offsets for string objects, and must be
818     * kept in sync with definitions in UtfString.h.  See asm-constants.h
819     *
820     * On entry:
821     *    r0:   this object pointer
822     *    r1:   comp object pointer
823     *
824     */
825
826    mov    r2, r0         @ this to r2, opening up r0 for return value
827    subs   r0, r2, r1     @ Same?
828    bxeq   lr
829
830    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
831    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
832    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
833    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
834    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
835    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
836
837    /*
838     * At this point, we have:
839     *    value:  r2/r1
840     *    offset: r4/r9
841     *    count:  r7/r10
842     * We're going to compute
843     *    r11 <- countDiff
844     *    r10 <- minCount
845     */
846     subs  r11, r7, r10
847     movls r10, r7
848
849     /* Now, build pointers to the string data */
850     add   r2, r2, r4, lsl #1
851     add   r1, r1, r9, lsl #1
852     /*
853      * Note: data pointers point to previous element so we can use pre-index
854      * mode with base writeback.
855      */
856     add   r2, #16-2   @ offset to contents[-1]
857     add   r1, #16-2   @ offset to contents[-1]
858
859     /*
860      * At this point we have:
861      *   r2: *this string data
862      *   r1: *comp string data
863      *   r10: iteration count for comparison
864      *   r11: value to return if the first part of the string is equal
865      *   r0: reserved for result
866      *   r3, r4, r7, r8, r9, r12 available for loading string data
867      */
868
869    subs  r10, #2
870    blt   do_remainder2
871
872      /*
873       * Unroll the first two checks so we can quickly catch early mismatch
874       * on long strings (but preserve incoming alignment)
875       */
876
877    ldrh  r3, [r2, #2]!
878    ldrh  r4, [r1, #2]!
879    ldrh  r7, [r2, #2]!
880    ldrh  r8, [r1, #2]!
881    subs  r0, r3, r4
882    subeqs  r0, r7, r8
883    bxne  lr
884    cmp   r10, #28
885    bgt   do_memcmp16
886    subs  r10, #3
887    blt   do_remainder
888
889loopback_triple:
890    ldrh  r3, [r2, #2]!
891    ldrh  r4, [r1, #2]!
892    ldrh  r7, [r2, #2]!
893    ldrh  r8, [r1, #2]!
894    ldrh  r9, [r2, #2]!
895    ldrh  r12,[r1, #2]!
896    subs  r0, r3, r4
897    subeqs  r0, r7, r8
898    subeqs  r0, r9, r12
899    bxne  lr
900    subs  r10, #3
901    bge   loopback_triple
902
903do_remainder:
904    adds  r10, #3
905    beq   returnDiff
906
907loopback_single:
908    ldrh  r3, [r2, #2]!
909    ldrh  r4, [r1, #2]!
910    subs  r0, r3, r4
911    bxne  lr
912    subs  r10, #1
913    bne     loopback_single
914
915returnDiff:
916    mov   r0, r11
917    bx    lr
918
919do_remainder2:
920    adds  r10, #2
921    bne   loopback_single
922    mov   r0, r11
923    bx    lr
924
925    /* Long string case */
926do_memcmp16:
927    mov   r4, lr
928    ldr   lr, .Lmemcmp16
929    mov   r7, r11
930    add   r0, r2, #2
931    add   r1, r1, #2
932    mov   r2, r10
933    blx   lr
934    cmp   r0, #0
935    bxne  r4
936    mov   r0, r7
937    bx    r4
938
939.Lmemcmp16:
940    .word __memcmp16
941
942/* ------------------------------ */
943    .balign 4
944    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
945dvmCompiler_TEMPLATE_STRING_INDEXOF:
946/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
947    /*
948     * String's indexOf.
949     *
950     * Requires r0 to have been previously checked for null.  Will
951     * return index of match of r1 in r0.
952     *
953     * IMPORTANT NOTE:
954     *
955     * This code relies on hard-coded offsets for string objects, and must be
956     * kept in sync wth definitions in UtfString.h  See asm-constants.h
957     *
958     * On entry:
959     *    r0:   string object pointer
960     *    r1:   char to match
961     *    r2:   Starting offset in string data
962     */
963
964    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
965    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
966    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
967
968    /*
969     * At this point, we have:
970     *    r0: object pointer
971     *    r1: char to match
972     *    r2: starting offset
973     *    r7: offset
974     *    r8: string length
975     */
976
977     /* Build pointer to start of string data */
978     add   r0, #16
979     add   r0, r0, r7, lsl #1
980
981     /* Save a copy of starting data in r7 */
982     mov   r7, r0
983
984     /* Clamp start to [0..count] */
985     cmp   r2, #0
986     movlt r2, #0
987     cmp   r2, r8
988     movgt r2, r8
989
990     /* Build pointer to start of data to compare and pre-bias */
991     add   r0, r0, r2, lsl #1
992     sub   r0, #2
993
994     /* Compute iteration count */
995     sub   r8, r2
996
997     /*
998      * At this point we have:
999      *   r0: start of data to test
1000      *   r1: chat to compare
1001      *   r8: iteration count
1002      *   r7: original start of string
1003      *   r3, r4, r9, r10, r11, r12 available for loading string data
1004      */
1005
1006    subs  r8, #4
1007    blt   indexof_remainder
1008
1009indexof_loop4:
1010    ldrh  r3, [r0, #2]!
1011    ldrh  r4, [r0, #2]!
1012    ldrh  r10, [r0, #2]!
1013    ldrh  r11, [r0, #2]!
1014    cmp   r3, r1
1015    beq   match_0
1016    cmp   r4, r1
1017    beq   match_1
1018    cmp   r10, r1
1019    beq   match_2
1020    cmp   r11, r1
1021    beq   match_3
1022    subs  r8, #4
1023    bge   indexof_loop4
1024
1025indexof_remainder:
1026    adds    r8, #4
1027    beq     indexof_nomatch
1028
1029indexof_loop1:
1030    ldrh  r3, [r0, #2]!
1031    cmp   r3, r1
1032    beq   match_3
1033    subs  r8, #1
1034    bne   indexof_loop1
1035
1036indexof_nomatch:
1037    mov   r0, #-1
1038    bx    lr
1039
1040match_0:
1041    sub   r0, #6
1042    sub   r0, r7
1043    asr   r0, r0, #1
1044    bx    lr
1045match_1:
1046    sub   r0, #4
1047    sub   r0, r7
1048    asr   r0, r0, #1
1049    bx    lr
1050match_2:
1051    sub   r0, #2
1052    sub   r0, r7
1053    asr   r0, r0, #1
1054    bx    lr
1055match_3:
1056    sub   r0, r7
1057    asr   r0, r0, #1
1058    bx    lr
1059
1060/* ------------------------------ */
1061    .balign 4
1062    .global dvmCompiler_TEMPLATE_INTERPRET
1063dvmCompiler_TEMPLATE_INTERPRET:
1064/* File: armv5te/TEMPLATE_INTERPRET.S */
1065    /*
1066     * This handler transfers control to the interpeter without performing
1067     * any lookups.  It may be called either as part of a normal chaining
1068     * operation, or from the transition code in header.S.  We distinquish
1069     * the two cases by looking at the link register.  If called from a
1070     * translation chain, it will point to the chaining Dalvik PC -3.
1071     * On entry:
1072     *    lr - if NULL:
1073     *        r1 - the Dalvik PC to begin interpretation.
1074     *    else
1075     *        [lr, #3] contains Dalvik PC to begin interpretation
1076     *    rGLUE - pointer to interpState
1077     *    rFP - Dalvik frame pointer
1078     */
1079    cmp     lr, #0
1080    ldrne   r1,[lr, #3]
1081    ldr     r2, .LinterpPunt
1082    mov     r0, r1                       @ set Dalvik PC
1083    bx      r2
1084    @ doesn't return
1085
1086.LinterpPunt:
1087    .word   dvmJitToInterpPunt
1088
1089/* ------------------------------ */
1090    .balign 4
1091    .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1092dvmCompiler_TEMPLATE_MONITOR_ENTER:
1093/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1094    /*
1095     * Call out to the runtime to lock an object.  Because this thread
1096     * may have been suspended in THREAD_MONITOR state and the Jit's
1097     * translation cache subsequently cleared, we cannot return directly.
1098     * Instead, unconditionally transition to the interpreter to resume.
1099     *
1100     * On entry:
1101     *    r0 - self pointer
1102     *    r1 - the object (which has already been null-checked by the caller
1103     *    r4 - the Dalvik PC of the following instruction.
1104     */
1105    ldr     r2, .LdvmLockObject
1106    mov     r3, #0                       @ Record that we're not returning
1107    str     r3, [r0, #offThread_inJitCodeCache]
1108    blx     r2                           @ dvmLockObject(self, obj)
1109    @ refresh Jit's on/off status
1110    ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1111    ldr     r0, [r0]
1112    ldr     r2, .LdvmJitToInterpNoChain
1113    str     r0, [rGLUE, #offGlue_pJitProfTable]
1114    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1115#if defined(WITH_JIT_TUNING)
1116    mov     r0, #kHeavyweightMonitor
1117#endif
1118    bx      r2
1119
1120/* ------------------------------ */
1121    .balign 4
1122    .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1123dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1124/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1125    /*
1126     * To support deadlock prediction, this version of MONITOR_ENTER
1127     * will always call the heavyweight dvmLockObject, check for an
1128     * exception and then bail out to the interpreter.
1129     *
1130     * On entry:
1131     *    r0 - self pointer
1132     *    r1 - the object (which has already been null-checked by the caller
1133     *    r4 - the Dalvik PC of the following instruction.
1134     *
1135     */
1136    ldr     r2, .LdvmLockObject
1137    mov     r3, #0                       @ Record that we're not returning
1138    str     r3, [r0, #offThread_inJitCodeCache]
1139    blx     r2             @ dvmLockObject(self, obj)
1140    @ refresh Jit's on/off status & test for exception
1141    ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1142    ldr     r1, [rGLUE, #offGlue_self]
1143    ldr     r0, [r0]
1144    ldr     r1, [r1, #offThread_exception]
1145    str     r0, [rGLUE, #offGlue_pJitProfTable]
1146    cmp     r1, #0
1147    beq     1f
1148    ldr     r2, .LhandleException
1149    sub     r0, r4, #2     @ roll dPC back to this monitor instruction
1150    bx      r2
11511:
1152    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1153#if defined(WITH_JIT_TUNING)
1154    mov     r0, #kHeavyweightMonitor
1155#endif
1156    ldr     pc, .LdvmJitToInterpNoChain
1157
1158    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1159/* File: armv5te/footer.S */
1160/*
1161 * ===========================================================================
1162 *  Common subroutines and data
1163 * ===========================================================================
1164 */
1165
1166    .text
1167    .align  2
1168.LinvokeNative:
1169    @ Prep for the native call
1170    @ r1 = newFP, r0 = methodToCall
1171    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1172    mov     r2, #0
1173    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1174    str     r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache
1175    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1176    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1177                                        @ newFp->localRefCookie=top
1178    mov     r9, r3                      @ r9<- glue->self (preserve)
1179    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1180
1181    mov     r2, r0                      @ r2<- methodToCall
1182    mov     r0, r1                      @ r0<- newFP
1183    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1184
1185    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1186
1187    @ Refresh Jit's on/off status
1188    ldr     r3, [rGLUE, #offGlue_ppJitProfTable]
1189
1190    @ native return; r9=self, r10=newSaveArea
1191    @ equivalent to dvmPopJniLocals
1192    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1193    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1194    ldr     r1, [r9, #offThread_exception] @ check for exception
1195    ldr     r3, [r3]    @ r1 <- pointer to Jit profile table
1196    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1197    cmp     r1, #0                      @ null?
1198    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1199    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1200    str     r3, [rGLUE, #offGlue_pJitProfTable]  @ cache current JitProfTable
1201
1202    @ r0 = dalvikCallsitePC
1203    bne     .LhandleException           @ no, handle exception
1204
1205    str     r2, [r9, #offThread_inJitCodeCache] @ set the new mode
1206    cmp     r2, #0                      @ return chaining cell still exists?
1207    bxne    r2                          @ yes - go ahead
1208
1209    @ continue executing the next instruction through the interpreter
1210    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1211    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
1212#if defined(WITH_JIT_TUNING)
1213    mov     r0, #kCallsiteInterpreted
1214#endif
1215    mov     pc, r1
1216
1217/*
1218 * On entry:
1219 * r0  Faulting Dalvik PC
1220 */
1221.LhandleException:
1222#if defined(WITH_SELF_VERIFICATION)
1223    ldr     pc, .LdeadFood @ should not see this under self-verification mode
1224.LdeadFood:
1225    .word   0xdeadf00d
1226#endif
1227    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
1228    mov     r2, #0
1229    str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
1230    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1231    ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1232    mov     rPC, r0                 @ reload the faulting Dalvik address
1233    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1234
1235    .align  2
1236.LdvmAsmInstructionStart:
1237    .word   dvmAsmInstructionStart
1238.LdvmJitToInterpNoChainNoProfile:
1239    .word   dvmJitToInterpNoChainNoProfile
1240.LdvmJitToInterpTraceSelectNoChain:
1241    .word   dvmJitToInterpTraceSelectNoChain
1242.LdvmJitToInterpNoChain:
1243    .word   dvmJitToInterpNoChain
1244.LdvmMterpStdBail:
1245    .word   dvmMterpStdBail
1246.LdvmMterpCommonExceptionThrown:
1247    .word   dvmMterpCommonExceptionThrown
1248.LdvmLockObject:
1249    .word   dvmLockObject
1250#if defined(WITH_JIT_TUNING)
1251.LdvmICHitCount:
1252    .word   gDvmICHitCount
1253#endif
1254#if defined(WITH_SELF_VERIFICATION)
1255.LdvmSelfVerificationMemOpDecode:
1256    .word   dvmSelfVerificationMemOpDecode
1257#endif
1258.L__aeabi_cdcmple:
1259    .word   __aeabi_cdcmple
1260.L__aeabi_cfcmple:
1261    .word   __aeabi_cfcmple
1262
1263    .global dmvCompilerTemplateEnd
1264dmvCompilerTemplateEnd:
1265
1266#endif /* WITH_JIT */
1267
1268