CompilerTemplateAsm-armv5te-vfp.S revision c8293e7dfe856ca95e27aef1ac2e64d750d60662
1/*
2 * This file was generated automatically by gen-template.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24#if defined(WITH_JIT)
25
26/*
27 * ARMv5 definitions and declarations.
28 */
29
30/*
31ARM EABI general notes:
32
33r0-r3 hold first 4 args to a method; they are not preserved across method calls
34r4-r8 are available for general use
35r9 is given special treatment in some situations, but not for us
36r10 (sl) seems to be generally available
37r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
38r12 (ip) is scratch -- not preserved across method calls
39r13 (sp) should be managed carefully in case a signal arrives
40r14 (lr) must be preserved
41r15 (pc) can be tinkered with directly
42
43r0 holds returns of <= 4 bytes
44r0-r1 hold returns of 8 bytes, low word in r0
45
46Callee must save/restore r4+ (except r12) if it modifies them.
47
48Stack is "full descending".  Only the arguments that don't fit in the first 4
49registers are placed on the stack.  "sp" points at the first stacked argument
50(i.e. the 5th arg).
51
52VFP: single-precision results in s0, double-precision results in d0.
53
54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5564-bit quantities (long long, double) must be 64-bit aligned.
56*/
57
58/*
59JIT and ARM notes:
60
61The following registers have fixed assignments:
62
63  reg nick      purpose
64  r5  rFP       interpreted frame pointer, used for accessing locals and args
65  r6  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-vfp/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_MUL_LONG
503dvmCompiler_TEMPLATE_MUL_LONG:
504/* File: armv5te/TEMPLATE_MUL_LONG.S */
505    /*
506     * Signed 64-bit integer multiply.
507     *
508     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
509     *
510     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
511     *        WX
512     *      x YZ
513     *  --------
514     *     ZW ZX
515     *  YW YX
516     *
517     * The low word of the result holds ZX, the high word holds
518     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
519     * it doesn't fit in the low 64 bits.
520     *
521     * Unlike most ARM math operations, multiply instructions have
522     * restrictions on using the same register more than once (Rd and Rm
523     * cannot be the same).
524     */
525    /* mul-long vAA, vBB, vCC */
526    mul     ip, r2, r1                  @  ip<- ZxW
527    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
528    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
529    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
530    mov     r0,r9
531    mov     r1,r10
532    bx      lr
533
534/* ------------------------------ */
535    .balign 4
536    .global dvmCompiler_TEMPLATE_SHL_LONG
537dvmCompiler_TEMPLATE_SHL_LONG:
538/* File: armv5te/TEMPLATE_SHL_LONG.S */
539    /*
540     * Long integer shift.  This is different from the generic 32/64-bit
541     * binary operations because vAA/vBB are 64-bit but vCC (the shift
542     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
543     * 6 bits.
544     */
545    /* shl-long vAA, vBB, vCC */
546    and     r2, r2, #63                 @ r2<- r2 & 0x3f
547    mov     r1, r1, asl r2              @  r1<- r1 << r2
548    rsb     r3, r2, #32                 @  r3<- 32 - r2
549    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
550    subs    ip, r2, #32                 @  ip<- r2 - 32
551    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
552    mov     r0, r0, asl r2              @  r0<- r0 << r2
553    bx      lr
554
555/* ------------------------------ */
556    .balign 4
557    .global dvmCompiler_TEMPLATE_SHR_LONG
558dvmCompiler_TEMPLATE_SHR_LONG:
559/* File: armv5te/TEMPLATE_SHR_LONG.S */
560    /*
561     * Long integer shift.  This is different from the generic 32/64-bit
562     * binary operations because vAA/vBB are 64-bit but vCC (the shift
563     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
564     * 6 bits.
565     */
566    /* shr-long vAA, vBB, vCC */
567    and     r2, r2, #63                 @ r0<- r0 & 0x3f
568    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
569    rsb     r3, r2, #32                 @  r3<- 32 - r2
570    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
571    subs    ip, r2, #32                 @  ip<- r2 - 32
572    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
573    mov     r1, r1, asr r2              @  r1<- r1 >> r2
574    bx      lr
575
576/* ------------------------------ */
577    .balign 4
578    .global dvmCompiler_TEMPLATE_USHR_LONG
579dvmCompiler_TEMPLATE_USHR_LONG:
580/* File: armv5te/TEMPLATE_USHR_LONG.S */
581    /*
582     * Long integer shift.  This is different from the generic 32/64-bit
583     * binary operations because vAA/vBB are 64-bit but vCC (the shift
584     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
585     * 6 bits.
586     */
587    /* ushr-long vAA, vBB, vCC */
588    and     r2, r2, #63                 @ r0<- r0 & 0x3f
589    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
590    rsb     r3, r2, #32                 @  r3<- 32 - r2
591    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
592    subs    ip, r2, #32                 @  ip<- r2 - 32
593    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
594    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
595    bx      lr
596
597/* ------------------------------ */
598    .balign 4
599    .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
600dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
601/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
602/* File: armv5te-vfp/fbinop.S */
603    /*
604     * Generic 32-bit floating point operation.  Provide an "instr" line that
605     * specifies an instruction that performs s2 = s0 op s1.
606     *
607     * On entry:
608     *     r0 = target dalvik register address
609     *     r1 = op1 address
610     *     r2 = op2 address
611     */
612     flds    s0,[r1]
613     flds    s1,[r2]
614     fadds   s2, s0, s1
615     fsts    s2,[r0]
616     bx      lr
617
618
619/* ------------------------------ */
620    .balign 4
621    .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
622dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
623/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
624/* File: armv5te-vfp/fbinop.S */
625    /*
626     * Generic 32-bit floating point operation.  Provide an "instr" line that
627     * specifies an instruction that performs s2 = s0 op s1.
628     *
629     * On entry:
630     *     r0 = target dalvik register address
631     *     r1 = op1 address
632     *     r2 = op2 address
633     */
634     flds    s0,[r1]
635     flds    s1,[r2]
636     fsubs   s2, s0, s1
637     fsts    s2,[r0]
638     bx      lr
639
640
641/* ------------------------------ */
642    .balign 4
643    .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
644dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
645/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
646/* File: armv5te-vfp/fbinop.S */
647    /*
648     * Generic 32-bit floating point operation.  Provide an "instr" line that
649     * specifies an instruction that performs s2 = s0 op s1.
650     *
651     * On entry:
652     *     r0 = target dalvik register address
653     *     r1 = op1 address
654     *     r2 = op2 address
655     */
656     flds    s0,[r1]
657     flds    s1,[r2]
658     fmuls   s2, s0, s1
659     fsts    s2,[r0]
660     bx      lr
661
662
663/* ------------------------------ */
664    .balign 4
665    .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
666dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
667/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
668/* File: armv5te-vfp/fbinop.S */
669    /*
670     * Generic 32-bit floating point operation.  Provide an "instr" line that
671     * specifies an instruction that performs s2 = s0 op s1.
672     *
673     * On entry:
674     *     r0 = target dalvik register address
675     *     r1 = op1 address
676     *     r2 = op2 address
677     */
678     flds    s0,[r1]
679     flds    s1,[r2]
680     fdivs   s2, s0, s1
681     fsts    s2,[r0]
682     bx      lr
683
684
685/* ------------------------------ */
686    .balign 4
687    .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
688dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
689/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
690/* File: armv5te-vfp/fbinopWide.S */
691    /*
692     * Generic 64-bit floating point operation.  Provide an "instr" line that
693     * specifies an instruction that performs s2 = s0 op s1.
694     *
695     * On entry:
696     *     r0 = target dalvik register address
697     *     r1 = op1 address
698     *     r2 = op2 address
699     */
700     fldd    d0,[r1]
701     fldd    d1,[r2]
702     faddd   d2, d0, d1
703     fstd    d2,[r0]
704     bx      lr
705
706
707/* ------------------------------ */
708    .balign 4
709    .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
710dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
711/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
712/* File: armv5te-vfp/fbinopWide.S */
713    /*
714     * Generic 64-bit floating point operation.  Provide an "instr" line that
715     * specifies an instruction that performs s2 = s0 op s1.
716     *
717     * On entry:
718     *     r0 = target dalvik register address
719     *     r1 = op1 address
720     *     r2 = op2 address
721     */
722     fldd    d0,[r1]
723     fldd    d1,[r2]
724     fsubd   d2, d0, d1
725     fstd    d2,[r0]
726     bx      lr
727
728
729/* ------------------------------ */
730    .balign 4
731    .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
732dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
733/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
734/* File: armv5te-vfp/fbinopWide.S */
735    /*
736     * Generic 64-bit floating point operation.  Provide an "instr" line that
737     * specifies an instruction that performs s2 = s0 op s1.
738     *
739     * On entry:
740     *     r0 = target dalvik register address
741     *     r1 = op1 address
742     *     r2 = op2 address
743     */
744     fldd    d0,[r1]
745     fldd    d1,[r2]
746     fmuld   d2, d0, d1
747     fstd    d2,[r0]
748     bx      lr
749
750
751/* ------------------------------ */
752    .balign 4
753    .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
754dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
755/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
756/* File: armv5te-vfp/fbinopWide.S */
757    /*
758     * Generic 64-bit floating point operation.  Provide an "instr" line that
759     * specifies an instruction that performs s2 = s0 op s1.
760     *
761     * On entry:
762     *     r0 = target dalvik register address
763     *     r1 = op1 address
764     *     r2 = op2 address
765     */
766     fldd    d0,[r1]
767     fldd    d1,[r2]
768     fdivd   d2, d0, d1
769     fstd    d2,[r0]
770     bx      lr
771
772
773/* ------------------------------ */
774    .balign 4
775    .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
776dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
777/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
778/* File: armv5te-vfp/funopNarrower.S */
779    /*
780     * Generic 64bit-to-32bit floating point unary operation.  Provide an
781     * "instr" line that specifies an instruction that performs "s0 = op d0".
782     *
783     * For: double-to-int, double-to-float
784     *
785     * On entry:
786     *     r0 = target dalvik register address
787     *     r1 = src dalvik register address
788     */
789    /* unop vA, vB */
790    fldd    d0, [r1]                    @ d0<- vB
791    fcvtsd  s0, d0                              @ s0<- op d0
792    fsts    s0, [r0]                    @ vA<- s0
793    bx      lr
794
795
796/* ------------------------------ */
797    .balign 4
798    .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
799dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
800/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
801/* File: armv5te-vfp/funopNarrower.S */
802    /*
803     * Generic 64bit-to-32bit floating point unary operation.  Provide an
804     * "instr" line that specifies an instruction that performs "s0 = op d0".
805     *
806     * For: double-to-int, double-to-float
807     *
808     * On entry:
809     *     r0 = target dalvik register address
810     *     r1 = src dalvik register address
811     */
812    /* unop vA, vB */
813    fldd    d0, [r1]                    @ d0<- vB
814    ftosizd  s0, d0                              @ s0<- op d0
815    fsts    s0, [r0]                    @ vA<- s0
816    bx      lr
817
818
819/* ------------------------------ */
820    .balign 4
821    .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
822dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
823/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
824/* File: armv5te-vfp/funopWider.S */
825    /*
826     * Generic 32bit-to-64bit floating point unary operation.  Provide an
827     * "instr" line that specifies an instruction that performs "d0 = op s0".
828     *
829     * For: int-to-double, float-to-double
830     *
831     * On entry:
832     *     r0 = target dalvik register address
833     *     r1 = src dalvik register address
834     */
835    /* unop vA, vB */
836    flds    s0, [r1]                    @ s0<- vB
837    fcvtds  d0, s0                              @ d0<- op s0
838    fstd    d0, [r0]                    @ vA<- d0
839    bx      lr
840
841
842/* ------------------------------ */
843    .balign 4
844    .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
845dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
846/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
847/* File: armv5te-vfp/funop.S */
848    /*
849     * Generic 32bit-to-32bit floating point unary operation.  Provide an
850     * "instr" line that specifies an instruction that performs "s1 = op s0".
851     *
852     * For: float-to-int, int-to-float
853     *
854     * On entry:
855     *     r0 = target dalvik register address
856     *     r1 = src dalvik register address
857     */
858    /* unop vA, vB */
859    flds    s0, [r1]                    @ s0<- vB
860    ftosizs s1, s0                              @ s1<- op s0
861    fsts    s1, [r0]                    @ vA<- s1
862    bx      lr
863
864
865/* ------------------------------ */
866    .balign 4
867    .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
868dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
869/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
870/* File: armv5te-vfp/funopWider.S */
871    /*
872     * Generic 32bit-to-64bit floating point unary operation.  Provide an
873     * "instr" line that specifies an instruction that performs "d0 = op s0".
874     *
875     * For: int-to-double, float-to-double
876     *
877     * On entry:
878     *     r0 = target dalvik register address
879     *     r1 = src dalvik register address
880     */
881    /* unop vA, vB */
882    flds    s0, [r1]                    @ s0<- vB
883    fsitod  d0, s0                              @ d0<- op s0
884    fstd    d0, [r0]                    @ vA<- d0
885    bx      lr
886
887
888/* ------------------------------ */
889    .balign 4
890    .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
891dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
892/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
893/* File: armv5te-vfp/funop.S */
894    /*
895     * Generic 32bit-to-32bit floating point unary operation.  Provide an
896     * "instr" line that specifies an instruction that performs "s1 = op s0".
897     *
898     * For: float-to-int, int-to-float
899     *
900     * On entry:
901     *     r0 = target dalvik register address
902     *     r1 = src dalvik register address
903     */
904    /* unop vA, vB */
905    flds    s0, [r1]                    @ s0<- vB
906    fsitos  s1, s0                              @ s1<- op s0
907    fsts    s1, [r0]                    @ vA<- s1
908    bx      lr
909
910
911/* ------------------------------ */
912    .balign 4
913    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
914dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
915/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
916    /*
917     * Compare two floating-point values.  Puts 0, 1, or -1 into the
918     * destination register based on the results of the comparison.
919     *
920     * int compare(x, y) {
921     *     if (x == y) {
922     *         return 0;
923     *     } else if (x < y) {
924     *         return -1;
925     *     } else if (x > y) {
926     *         return 1;
927     *     } else {
928     *         return 1;
929     *     }
930     * }
931     *
932     * On entry:
933     *    r0 = &op1 [vBB]
934     *    r1 = &op2 [vCC]
935     */
936    /* op vAA, vBB, vCC */
937    fldd    d0, [r0]                    @ d0<- vBB
938    fldd    d1, [r1]                    @ d1<- vCC
939    fcmpd  d0, d1                       @ compare (vBB, vCC)
940    mov     r0, #1                      @ r0<- 1 (default)
941    fmstat                              @ export status flags
942    mvnmi   r0, #0                      @ (less than) r0<- -1
943    moveq   r0, #0                      @ (equal) r0<- 0
944    bx      lr
945
946/* ------------------------------ */
947    .balign 4
948    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
949dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
950/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
951    /*
952     * Compare two floating-point values.  Puts 0, 1, or -1 into the
953     * destination register based on the results of the comparison.
954     *
955     * int compare(x, y) {
956     *     if (x == y) {
957     *         return 0;
958     *     } else if (x > y) {
959     *         return 1;
960     *     } else if (x < y) {
961     *         return -1;
962     *     } else {
963     *         return -1;
964     *     }
965     * }
966     * On entry:
967     *    r0 = &op1 [vBB]
968     *    r1 = &op2 [vCC]
969     */
970    /* op vAA, vBB, vCC */
971    fldd    d0, [r0]                    @ d0<- vBB
972    fldd    d1, [r1]                    @ d1<- vCC
973    fcmped  d0, d1                      @ compare (vBB, vCC)
974    mvn     r0, #0                      @ r0<- -1 (default)
975    fmstat                              @ export status flags
976    movgt   r0, #1                      @ (greater than) r0<- 1
977    moveq   r0, #0                      @ (equal) r0<- 0
978    bx      lr
979
980/* ------------------------------ */
981    .balign 4
982    .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
983dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
984/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
985    /*
986     * Compare two floating-point values.  Puts 0, 1, or -1 into the
987     * destination register based on the results of the comparison.
988     *
989     * int compare(x, y) {
990     *     if (x == y) {
991     *         return 0;
992     *     } else if (x < y) {
993     *         return -1;
994     *     } else if (x > y) {
995     *         return 1;
996     *     } else {
997     *         return 1;
998     *     }
999     * }
1000     * On entry:
1001     *    r0 = &op1 [vBB]
1002     *    r1 = &op2 [vCC]
1003     */
1004    /* op vAA, vBB, vCC */
1005    flds    s0, [r0]                    @ d0<- vBB
1006    flds    s1, [r1]                    @ d1<- vCC
1007    fcmps  s0, s1                      @ compare (vBB, vCC)
1008    mov     r0, #1                      @ r0<- 1 (default)
1009    fmstat                              @ export status flags
1010    mvnmi   r0, #0                      @ (less than) r0<- -1
1011    moveq   r0, #0                      @ (equal) r0<- 0
1012    bx      lr
1013
1014/* ------------------------------ */
1015    .balign 4
1016    .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
1017dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
1018/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
1019    /*
1020     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1021     * destination register based on the results of the comparison.
1022     *
1023     * int compare(x, y) {
1024     *     if (x == y) {
1025     *         return 0;
1026     *     } else if (x > y) {
1027     *         return 1;
1028     *     } else if (x < y) {
1029     *         return -1;
1030     *     } else {
1031     *         return -1;
1032     *     }
1033     * }
1034     * On entry:
1035     *    r0 = &op1 [vBB]
1036     *    r1 = &op2 [vCC]
1037     */
1038    /* op vAA, vBB, vCC */
1039    flds    s0, [r0]                    @ d0<- vBB
1040    flds    s1, [r1]                    @ d1<- vCC
1041    fcmps  s0, s1                      @ compare (vBB, vCC)
1042    mvn     r0, #0                      @ r0<- -1 (default)
1043    fmstat                              @ export status flags
1044    movgt   r0, #1                      @ (greater than) r0<- 1
1045    moveq   r0, #0                      @ (equal) r0<- 0
1046    bx      lr
1047
1048/* ------------------------------ */
1049    .balign 4
1050    .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
1051dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
1052/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
1053    /*
1054     * 64-bit floating point vfp sqrt operation.
1055     * If the result is a NaN, bail out to library code to do
1056     * the right thing.
1057     *
1058     * On entry:
1059     *     r2 src addr of op1
1060     * On exit:
1061     *     r0,r1 = res
1062     */
1063    fldd    d0, [r2]
1064    fsqrtd  d1, d0
1065    fcmpd   d1, d1
1066    fmstat
1067    fmrrd   r0, r1, d1
1068    bxeq    lr   @ Result OK - return
1069    ldr     r2, .Lsqrt
1070    fmrrd   r0, r1, d0   @ reload orig operand
1071    bx      r2   @ tail call to sqrt library routine
1072
1073.Lsqrt:
1074    .word   sqrt
1075
1076/* ------------------------------ */
1077    .balign 4
1078    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
1079dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
1080/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
1081    /*
1082     * Throw an exception from JIT'ed code.
1083     * On entry:
1084     *    r0    Dalvik PC that raises the exception
1085     */
1086    b       .LhandleException
1087
1088/* ------------------------------ */
1089    .balign 4
1090    .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
1091dvmCompiler_TEMPLATE_MEM_OP_DECODE:
1092/* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */
1093#if defined(WITH_SELF_VERIFICATION)
1094    /*
1095     * This handler encapsulates heap memory ops for selfVerification mode.
1096     *
1097     * The call to the handler is inserted prior to a heap memory operation.
1098     * This handler then calls a function to decode the memory op, and process
1099     * it accordingly. Afterwards, the handler changes the return address to
1100     * skip the memory op so it never gets executed.
1101     */
1102    vpush   {d0-d15}                    @ save out all fp registers
1103    push    {r0-r12,lr}                 @ save out all registers
1104    mov     r0, lr                      @ arg0 <- link register
1105    mov     r1, sp                      @ arg1 <- stack pointer
1106    ldr     r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
1107    blx     r2                          @ decode and handle the mem op
1108    pop     {r0-r12,lr}                 @ restore all registers
1109    vpop    {d0-d15}                    @ restore all fp registers
1110    bx      lr                          @ return to compiled code
1111#endif
1112
1113/* ------------------------------ */
1114    .balign 4
1115    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
1116dvmCompiler_TEMPLATE_STRING_COMPARETO:
1117/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
1118    /*
1119     * String's compareTo.
1120     *
1121     * Requires r0/r1 to have been previously checked for null.  Will
1122     * return negative if this's string is < comp, 0 if they are the
1123     * same and positive if >.
1124     *
1125     * IMPORTANT NOTE:
1126     *
1127     * This code relies on hard-coded offsets for string objects, and must be
1128     * kept in sync with definitions in UtfString.h.  See asm-constants.h
1129     *
1130     * On entry:
1131     *    r0:   this object pointer
1132     *    r1:   comp object pointer
1133     *
1134     */
1135
1136    mov    r2, r0         @ this to r2, opening up r0 for return value
1137    subs   r0, r2, r1     @ Same?
1138    bxeq   lr
1139
1140    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
1141    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
1142    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
1143    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
1144    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
1145    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
1146
1147    /*
1148     * At this point, we have:
1149     *    value:  r2/r1
1150     *    offset: r4/r9
1151     *    count:  r7/r10
1152     * We're going to compute
1153     *    r11 <- countDiff
1154     *    r10 <- minCount
1155     */
1156     subs  r11, r7, r10
1157     movls r10, r7
1158
1159     /* Now, build pointers to the string data */
1160     add   r2, r2, r4, lsl #1
1161     add   r1, r1, r9, lsl #1
1162     /*
1163      * Note: data pointers point to previous element so we can use pre-index
1164      * mode with base writeback.
1165      */
1166     add   r2, #16-2   @ offset to contents[-1]
1167     add   r1, #16-2   @ offset to contents[-1]
1168
1169     /*
1170      * At this point we have:
1171      *   r2: *this string data
1172      *   r1: *comp string data
1173      *   r10: iteration count for comparison
1174      *   r11: value to return if the first part of the string is equal
1175      *   r0: reserved for result
1176      *   r3, r4, r7, r8, r9, r12 available for loading string data
1177      */
1178
1179    subs  r10, #2
1180    blt   do_remainder2
1181
1182      /*
1183       * Unroll the first two checks so we can quickly catch early mismatch
1184       * on long strings (but preserve incoming alignment)
1185       */
1186
1187    ldrh  r3, [r2, #2]!
1188    ldrh  r4, [r1, #2]!
1189    ldrh  r7, [r2, #2]!
1190    ldrh  r8, [r1, #2]!
1191    subs  r0, r3, r4
1192    subeqs  r0, r7, r8
1193    bxne  lr
1194    cmp   r10, #28
1195    bgt   do_memcmp16
1196    subs  r10, #3
1197    blt   do_remainder
1198
1199loopback_triple:
1200    ldrh  r3, [r2, #2]!
1201    ldrh  r4, [r1, #2]!
1202    ldrh  r7, [r2, #2]!
1203    ldrh  r8, [r1, #2]!
1204    ldrh  r9, [r2, #2]!
1205    ldrh  r12,[r1, #2]!
1206    subs  r0, r3, r4
1207    subeqs  r0, r7, r8
1208    subeqs  r0, r9, r12
1209    bxne  lr
1210    subs  r10, #3
1211    bge   loopback_triple
1212
1213do_remainder:
1214    adds  r10, #3
1215    beq   returnDiff
1216
1217loopback_single:
1218    ldrh  r3, [r2, #2]!
1219    ldrh  r4, [r1, #2]!
1220    subs  r0, r3, r4
1221    bxne  lr
1222    subs  r10, #1
1223    bne     loopback_single
1224
1225returnDiff:
1226    mov   r0, r11
1227    bx    lr
1228
1229do_remainder2:
1230    adds  r10, #2
1231    bne   loopback_single
1232    mov   r0, r11
1233    bx    lr
1234
1235    /* Long string case */
1236do_memcmp16:
1237    mov   r4, lr
1238    ldr   lr, .Lmemcmp16
1239    mov   r7, r11
1240    add   r0, r2, #2
1241    add   r1, r1, #2
1242    mov   r2, r10
1243    blx   lr
1244    cmp   r0, #0
1245    bxne  r4
1246    mov   r0, r7
1247    bx    r4
1248
1249.Lmemcmp16:
1250    .word __memcmp16
1251
1252/* ------------------------------ */
1253    .balign 4
1254    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
1255dvmCompiler_TEMPLATE_STRING_INDEXOF:
1256/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
1257    /*
1258     * String's indexOf.
1259     *
1260     * Requires r0 to have been previously checked for null.  Will
1261     * return index of match of r1 in r0.
1262     *
1263     * IMPORTANT NOTE:
1264     *
1265     * This code relies on hard-coded offsets for string objects, and must be
1266     * kept in sync wth definitions in UtfString.h  See asm-constants.h
1267     *
1268     * On entry:
1269     *    r0:   string object pointer
1270     *    r1:   char to match
1271     *    r2:   Starting offset in string data
1272     */
1273
1274    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
1275    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
1276    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
1277
1278    /*
1279     * At this point, we have:
1280     *    r0: object pointer
1281     *    r1: char to match
1282     *    r2: starting offset
1283     *    r7: offset
1284     *    r8: string length
1285     */
1286
1287     /* Build pointer to start of string data */
1288     add   r0, #16
1289     add   r0, r0, r7, lsl #1
1290
1291     /* Save a copy of starting data in r7 */
1292     mov   r7, r0
1293
1294     /* Clamp start to [0..count] */
1295     cmp   r2, #0
1296     movlt r2, #0
1297     cmp   r2, r8
1298     movgt r2, r8
1299
1300     /* Build pointer to start of data to compare and pre-bias */
1301     add   r0, r0, r2, lsl #1
1302     sub   r0, #2
1303
1304     /* Compute iteration count */
1305     sub   r8, r2
1306
1307     /*
1308      * At this point we have:
1309      *   r0: start of data to test
1310      *   r1: chat to compare
1311      *   r8: iteration count
1312      *   r7: original start of string
1313      *   r3, r4, r9, r10, r11, r12 available for loading string data
1314      */
1315
1316    subs  r8, #4
1317    blt   indexof_remainder
1318
1319indexof_loop4:
1320    ldrh  r3, [r0, #2]!
1321    ldrh  r4, [r0, #2]!
1322    ldrh  r10, [r0, #2]!
1323    ldrh  r11, [r0, #2]!
1324    cmp   r3, r1
1325    beq   match_0
1326    cmp   r4, r1
1327    beq   match_1
1328    cmp   r10, r1
1329    beq   match_2
1330    cmp   r11, r1
1331    beq   match_3
1332    subs  r8, #4
1333    bge   indexof_loop4
1334
1335indexof_remainder:
1336    adds    r8, #4
1337    beq     indexof_nomatch
1338
1339indexof_loop1:
1340    ldrh  r3, [r0, #2]!
1341    cmp   r3, r1
1342    beq   match_3
1343    subs  r8, #1
1344    bne   indexof_loop1
1345
1346indexof_nomatch:
1347    mov   r0, #-1
1348    bx    lr
1349
1350match_0:
1351    sub   r0, #6
1352    sub   r0, r7
1353    asr   r0, r0, #1
1354    bx    lr
1355match_1:
1356    sub   r0, #4
1357    sub   r0, r7
1358    asr   r0, r0, #1
1359    bx    lr
1360match_2:
1361    sub   r0, #2
1362    sub   r0, r7
1363    asr   r0, r0, #1
1364    bx    lr
1365match_3:
1366    sub   r0, r7
1367    asr   r0, r0, #1
1368    bx    lr
1369
1370/* ------------------------------ */
1371    .balign 4
1372    .global dvmCompiler_TEMPLATE_INTERPRET
1373dvmCompiler_TEMPLATE_INTERPRET:
1374/* File: armv5te/TEMPLATE_INTERPRET.S */
1375    /*
1376     * This handler transfers control to the interpeter without performing
1377     * any lookups.  It may be called either as part of a normal chaining
1378     * operation, or from the transition code in header.S.  We distinquish
1379     * the two cases by looking at the link register.  If called from a
1380     * translation chain, it will point to the chaining Dalvik PC -3.
1381     * On entry:
1382     *    lr - if NULL:
1383     *        r1 - the Dalvik PC to begin interpretation.
1384     *    else
1385     *        [lr, #3] contains Dalvik PC to begin interpretation
1386     *    rGLUE - pointer to interpState
1387     *    rFP - Dalvik frame pointer
1388     */
1389    cmp     lr, #0
1390    ldrne   r1,[lr, #3]
1391    ldr     r2, .LinterpPunt
1392    mov     r0, r1                       @ set Dalvik PC
1393    bx      r2
1394    @ doesn't return
1395
1396.LinterpPunt:
1397    .word   dvmJitToInterpPunt
1398
1399/* ------------------------------ */
1400    .balign 4
1401    .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1402dvmCompiler_TEMPLATE_MONITOR_ENTER:
1403/* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1404    /*
1405     * Call out to the runtime to lock an object.  Because this thread
1406     * may have been suspended in THREAD_MONITOR state and the Jit's
1407     * translation cache subsequently cleared, we cannot return directly.
1408     * Instead, unconditionally transition to the interpreter to resume.
1409     *
1410     * On entry:
1411     *    r0 - self pointer
1412     *    r1 - the object (which has already been null-checked by the caller
1413     *    r4 - the Dalvik PC of the following instruction.
1414     */
1415    ldr     r2, .LdvmLockObject
1416    mov     r3, #0                       @ Record that we're not returning
1417    str     r3, [r0, #offThread_inJitCodeCache]
1418    blx     r2                           @ dvmLockObject(self, obj)
1419    @ refresh Jit's on/off status
1420    ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1421    ldr     r0, [r0]
1422    ldr     r2, .LdvmJitToInterpNoChain
1423    str     r0, [rGLUE, #offGlue_pJitProfTable]
1424    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1425#if defined(WITH_JIT_TUNING)
1426    mov     r0, #kHeavyweightMonitor
1427#endif
1428    bx      r2
1429
1430/* ------------------------------ */
1431    .balign 4
1432    .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1433dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1434/* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1435    /*
1436     * To support deadlock prediction, this version of MONITOR_ENTER
1437     * will always call the heavyweight dvmLockObject, check for an
1438     * exception and then bail out to the interpreter.
1439     *
1440     * On entry:
1441     *    r0 - self pointer
1442     *    r1 - the object (which has already been null-checked by the caller
1443     *    r4 - the Dalvik PC of the following instruction.
1444     *
1445     */
1446    ldr     r2, .LdvmLockObject
1447    mov     r3, #0                       @ Record that we're not returning
1448    str     r3, [r0, #offThread_inJitCodeCache]
1449    blx     r2             @ dvmLockObject(self, obj)
1450    @ refresh Jit's on/off status & test for exception
1451    ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1452    ldr     r1, [rGLUE, #offGlue_self]
1453    ldr     r0, [r0]
1454    ldr     r1, [r1, #offThread_exception]
1455    str     r0, [rGLUE, #offGlue_pJitProfTable]
1456    cmp     r1, #0
1457    beq     1f
1458    ldr     r2, .LhandleException
1459    sub     r0, r4, #2     @ roll dPC back to this monitor instruction
1460    bx      r2
14611:
1462    @ Bail to interpreter - no chain [note - r4 still contains rPC]
1463#if defined(WITH_JIT_TUNING)
1464    mov     r0, #kHeavyweightMonitor
1465#endif
1466    ldr     pc, .LdvmJitToInterpNoChain
1467
1468    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1469/* File: armv5te/footer.S */
1470/*
1471 * ===========================================================================
1472 *  Common subroutines and data
1473 * ===========================================================================
1474 */
1475
1476    .text
1477    .align  2
1478.LinvokeNative:
1479    @ Prep for the native call
1480    @ r1 = newFP, r0 = methodToCall
1481    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1482    mov     r2, #0
1483    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1484    str     r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache
1485    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1486    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1487                                        @ newFp->localRefCookie=top
1488    mov     r9, r3                      @ r9<- glue->self (preserve)
1489    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1490
1491    mov     r2, r0                      @ r2<- methodToCall
1492    mov     r0, r1                      @ r0<- newFP
1493    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1494#if defined(WITH_INLINE_PROFILING)
1495    @ r2: methodToCall, r6: rGLUE
1496    stmfd   sp!, {r2,r6}
1497    stmfd   sp!, {r0-r3}
1498    mov     r0, r2
1499    mov     r1, r6
1500    LDR_PC_LR ".LdvmFastMethodTraceEnter"
1501    ldmfd   sp!, {r0-r3}
1502#endif
1503
1504    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1505
1506#if defined(WITH_INLINE_PROFILING)
1507    ldmfd   sp!, {r0-r1}
1508    LDR_PC_LR ".LdvmFastNativeMethodTraceExit"
1509#endif
1510    @ Refresh Jit's on/off status
1511    ldr     r3, [rGLUE, #offGlue_ppJitProfTable]
1512
1513    @ native return; r9=self, r10=newSaveArea
1514    @ equivalent to dvmPopJniLocals
1515    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1516    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1517    ldr     r1, [r9, #offThread_exception] @ check for exception
1518    ldr     r3, [r3]    @ r1 <- pointer to Jit profile table
1519    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1520    cmp     r1, #0                      @ null?
1521    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1522    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1523    str     r3, [rGLUE, #offGlue_pJitProfTable]  @ cache current JitProfTable
1524
1525    @ r0 = dalvikCallsitePC
1526    bne     .LhandleException           @ no, handle exception
1527
1528    str     r2, [r9, #offThread_inJitCodeCache] @ set the new mode
1529    cmp     r2, #0                      @ return chaining cell still exists?
1530    bxne    r2                          @ yes - go ahead
1531
1532    @ continue executing the next instruction through the interpreter
1533    ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1534    add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
1535#if defined(WITH_JIT_TUNING)
1536    mov     r0, #kCallsiteInterpreted
1537#endif
1538    mov     pc, r1
1539
1540/*
1541 * On entry:
1542 * r0  Faulting Dalvik PC
1543 */
1544.LhandleException:
1545#if defined(WITH_SELF_VERIFICATION)
1546    ldr     pc, .LdeadFood @ should not see this under self-verification mode
1547.LdeadFood:
1548    .word   0xdeadf00d
1549#endif
1550    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
1551    mov     r2, #0
1552    str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
1553    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1554    ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1555    mov     rPC, r0                 @ reload the faulting Dalvik address
1556    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1557
1558    .align  2
1559.LdvmAsmInstructionStart:
1560    .word   dvmAsmInstructionStart
1561.LdvmJitToInterpNoChainNoProfile:
1562    .word   dvmJitToInterpNoChainNoProfile
1563.LdvmJitToInterpTraceSelectNoChain:
1564    .word   dvmJitToInterpTraceSelectNoChain
1565.LdvmJitToInterpNoChain:
1566    .word   dvmJitToInterpNoChain
1567.LdvmMterpStdBail:
1568    .word   dvmMterpStdBail
1569.LdvmMterpCommonExceptionThrown:
1570    .word   dvmMterpCommonExceptionThrown
1571.LdvmLockObject:
1572    .word   dvmLockObject
1573#if defined(WITH_JIT_TUNING)
1574.LdvmICHitCount:
1575    .word   gDvmICHitCount
1576#endif
1577#if defined(WITH_SELF_VERIFICATION)
1578.LdvmSelfVerificationMemOpDecode:
1579    .word   dvmSelfVerificationMemOpDecode
1580#endif
1581#if defined(WITH_INLINE_PROFILING)
1582.LdvmFastMethodTraceEnter:
1583    .word   dvmFastMethodTraceEnter
1584.LdvmFastNativeMethodTraceExit:
1585    .word   dvmFastNativeMethodTraceExit
1586.LdvmFastJavaMethodTraceExit:
1587    .word   dvmFastJavaMethodTraceExit
1588#endif
1589.L__aeabi_cdcmple:
1590    .word   __aeabi_cdcmple
1591.L__aeabi_cfcmple:
1592    .word   __aeabi_cfcmple
1593
1594    .global dmvCompilerTemplateEnd
1595dmvCompilerTemplateEnd:
1596
1597#endif /* WITH_JIT */
1598
1599