CompilerTemplateAsm-armv5te-vfp.S revision 342806dae77556290dfe0760e6fe3117d812c7ba
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
105/* File: armv5te-vfp/platform.S */
106/*
107 * ===========================================================================
108 *  CPU-version-specific defines and utility
109 * ===========================================================================
110 */
111
112/*
113 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
114 * Jump to subroutine.
115 *
116 * May modify IP and LR.
117 */
118.macro  LDR_PC_LR source
119    mov     lr, pc
120    ldr     pc, \source
121.endm
122
123/*
124 * Save & restore for callee-save FP registers.
125 * On entry:
126 *    r0 : pointer to save area of JIT_CALLEE_SAVE_WORD_SIZE
127 */
128    .text
129    .align 2
130    .global dvmJitCalleeSave
131    .type dvmJitCalleeSave, %function
132dvmJitCalleeSave:
133    vstmia r0, {d8-d15}
134    bx     lr
135
136    .global dvmJitCalleeRestore
137    .type dvmJitCalleeRestore, %function
138dvmJitCalleeRestore:
139    vldmia r0, {d8-d15}
140    bx     lr
141
142
143
144    .global dvmCompilerTemplateStart
145    .type   dvmCompilerTemplateStart, %function
146    .text
147
148dvmCompilerTemplateStart:
149
150/* ------------------------------ */
151    .balign 4
152    .global dvmCompiler_TEMPLATE_CMP_LONG
153dvmCompiler_TEMPLATE_CMP_LONG:
154/* File: armv5te/TEMPLATE_CMP_LONG.S */
155    /*
156     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
157     * register based on the results of the comparison.
158     *
159     * We load the full values with LDM, but in practice many values could
160     * be resolved by only looking at the high word.  This could be made
161     * faster or slower by splitting the LDM into a pair of LDRs.
162     *
163     * If we just wanted to set condition flags, we could do this:
164     *  subs    ip, r0, r2
165     *  sbcs    ip, r1, r3
166     *  subeqs  ip, r0, r2
167     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
168     * integer value, which we can do with 2 conditional mov/mvn instructions
169     * (set 1, set -1; if they're equal we already have 0 in ip), giving
170     * us a constant 5-cycle path plus a branch at the end to the
171     * instruction epilogue code.  The multi-compare approach below needs
172     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
173     * in the worst case (the 64-bit values are equal).
174     */
175    /* cmp-long vAA, vBB, vCC */
176    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
177    blt     .LTEMPLATE_CMP_LONG_less            @ signed compare on high part
178    bgt     .LTEMPLATE_CMP_LONG_greater
179    subs    r0, r0, r2                  @ r0<- r0 - r2
180    bxeq     lr
181    bhi     .LTEMPLATE_CMP_LONG_greater         @ unsigned compare on low part
182.LTEMPLATE_CMP_LONG_less:
183    mvn     r0, #0                      @ r0<- -1
184    bx      lr
185.LTEMPLATE_CMP_LONG_greater:
186    mov     r0, #1                      @ r0<- 1
187    bx      lr
188
189
190/* ------------------------------ */
191    .balign 4
192    .global dvmCompiler_TEMPLATE_RETURN
193dvmCompiler_TEMPLATE_RETURN:
194/* File: armv5te/TEMPLATE_RETURN.S */
195    /*
196     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
197     * If the stored value in returnAddr
198     * is non-zero, the caller is compiled by the JIT thus return to the
199     * address in the code cache following the invoke instruction. Otherwise
200     * return to the special dvmJitToInterpNoChain entry point.
201     */
202    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
203    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
204    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
205    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
206#if !defined(WITH_SELF_VERIFICATION)
207    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
208#else
209    mov     r9, #0                      @ disable chaining
210#endif
211    ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
212                                        @ r2<- method we're returning to
213    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
214    cmp     r2, #0                      @ break frame?
215#if !defined(WITH_SELF_VERIFICATION)
216    beq     1f                          @ bail to interpreter
217#else
218    blxeq   lr                          @ punt to interpreter and compare state
219#endif
220    ldr     r1, .LdvmJitToInterpNoChain @ defined in footer.S
221    mov     rFP, r10                    @ publish new FP
222    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
223    ldr     r8, [r8]                    @ r8<- suspendCount
224
225    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
226    ldr     r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
227    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
228    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
229    str     r0, [rGLUE, #offGlue_methodClassDex]
230    cmp     r8, #0                      @ check the suspendCount
231    movne   r9, #0                      @ clear the chaining cell address
232    cmp     r9, #0                      @ chaining cell exists?
233    blxne   r9                          @ jump to the chaining cell
234#if defined(EXIT_STATS)
235    mov     r0, #kCallsiteInterpreted
236#endif
237    mov     pc, r1                      @ callsite is interpreted
2381:
239    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
240    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
241    mov     r1, #0                      @ changeInterp = false
242    mov     r0, rGLUE                   @ Expecting rGLUE in r0
243    blx     r2                          @ exit the interpreter
244
245/* ------------------------------ */
246    .balign 4
247    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
248dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
249/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
250    /*
251     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
252     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
253     * runtime-resolved callee.
254     */
255    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
256    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
257    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
258    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
259    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
260    add     r3, r1, #1  @ Thumb addr is odd
261    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
262    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
263    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
264    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
265    ldr     r8, [r8]                    @ r3<- suspendCount (int)
266    cmp     r10, r9                     @ bottom < interpStackEnd?
267    bxlt    lr                          @ return to raise stack overflow excep.
268    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
269    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
270    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
271    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
272    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
273    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
274
275
276    @ set up newSaveArea
277    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
278    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
279    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
280    cmp     r8, #0                      @ suspendCount != 0
281    bxne    lr                          @ bail to the interpreter
282    tst     r10, #ACC_NATIVE
283#if !defined(WITH_SELF_VERIFICATION)
284    bne     .LinvokeNative
285#else
286    bxne    lr                          @ bail to the interpreter
287#endif
288
289    ldr     r10, .LdvmJitToInterpNoChain
290    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
291    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
292
293    @ Update "glue" values for the new method
294    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
295    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
296    mov     rFP, r1                         @ fp = newFp
297    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
298
299    @ Start executing the callee
300#if defined(EXIT_STATS)
301    mov     r0, #kInlineCacheMiss
302#endif
303    mov     pc, r10                         @ dvmJitToInterpNoChain
304
305/* ------------------------------ */
306    .balign 4
307    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
308dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
309/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
310    /*
311     * For monomorphic callsite, setup the Dalvik frame and return to the
312     * Thumb code through the link register to transfer control to the callee
313     * method through a dedicated chaining cell.
314     */
315    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
316    @ methodToCall is guaranteed to be non-native
317.LinvokeChain:
318    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
319    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
320    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
321    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
322    add     r3, r1, #1  @ Thumb addr is odd
323    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
324    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
325    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
326    add     r12, lr, #2                 @ setup the punt-to-interp address
327    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
328    ldr     r8, [r8]                    @ r3<- suspendCount (int)
329    cmp     r10, r9                     @ bottom < interpStackEnd?
330    bxlt    r12                         @ return to raise stack overflow excep.
331    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
332    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
333    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
334    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
335    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
336
337
338    @ set up newSaveArea
339    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
340    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
341    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
342    cmp     r8, #0                      @ suspendCount != 0
343    bxne    r12                         @ bail to the interpreter
344
345    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
346    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
347
348    @ Update "glue" values for the new method
349    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
350    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
351    mov     rFP, r1                         @ fp = newFp
352    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
353
354    bx      lr                              @ return to the callee-chaining cell
355
356
357
358/* ------------------------------ */
359    .balign 4
360    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
361dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
362/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
363    /*
364     * For polymorphic callsite, check whether the cached class pointer matches
365     * the current one. If so setup the Dalvik frame and return to the
366     * Thumb code through the link register to transfer control to the callee
367     * method through a dedicated chaining cell.
368     *
369     * The predicted chaining cell is declared in ArmLIR.h with the
370     * following layout:
371     *
372     *  typedef struct PredictedChainingCell {
373     *      u4 branch;
374     *      const ClassObject *clazz;
375     *      const Method *method;
376     *      u4 counter;
377     *  } PredictedChainingCell;
378     *
379     * Upon returning to the callsite:
380     *    - lr  : to branch to the chaining cell
381     *    - lr+2: to punt to the interpreter
382     *    - lr+4: to fully resolve the callee and may rechain.
383     *            r3 <- class
384     *            r9 <- counter
385     */
386    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
387    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
388    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
389    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
390    ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
391    cmp     r3, r8          @ predicted class == actual class?
392    beq     .LinvokeChain   @ predicted chain is valid
393    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
394    sub     r1, r9, #1      @ count--
395    str     r1, [r2, #12]   @ write back to PredictedChainingCell->counter
396    add     lr, lr, #4      @ return to fully-resolve landing pad
397    /*
398     * r1 <- count
399     * r2 <- &predictedChainCell
400     * r3 <- this->class
401     * r4 <- dPC
402     * r7 <- this->class->vtable
403     */
404    bx      lr
405
406/* ------------------------------ */
407    .balign 4
408    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
409dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
410/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
411    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
412    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
413    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
414    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
415    add     r3, r1, #1  @ Thumb addr is odd
416    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
417    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
418    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
419    ldr     r8, [r8]                    @ r3<- suspendCount (int)
420    cmp     r10, r9                     @ bottom < interpStackEnd?
421    bxlt    lr                          @ return to raise stack overflow excep.
422    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
423    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
424    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
425    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
426
427
428    @ set up newSaveArea
429    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
430    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
431    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
432    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
433    cmp     r8, #0                      @ suspendCount != 0
434    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
435#if !defined(WITH_SELF_VERIFICATION)
436    bxne    lr                          @ bail to the interpreter
437#else
438    bx      lr                          @ bail to interpreter unconditionally
439#endif
440
441    @ go ahead and transfer control to the native code
442    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
443    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
444    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
445                                        @ newFp->localRefCookie=top
446    mov     r9, r3                      @ r9<- glue->self (preserve)
447    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
448
449    mov     r2, r0                      @ r2<- methodToCall
450    mov     r0, r1                      @ r0<- newFP
451    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
452
453    blx     r8                          @ off to the native code
454
455    @ native return; r9=self, r10=newSaveArea
456    @ equivalent to dvmPopJniLocals
457    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
458    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
459    ldr     r1, [r9, #offThread_exception] @ check for exception
460    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
461    cmp     r1, #0                      @ null?
462    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
463    ldr     r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
464    bne     .LhandleException             @ no, handle exception
465    bx      r2
466
467
468/* ------------------------------ */
469    .balign 4
470    .global dvmCompiler_TEMPLATE_MUL_LONG
471dvmCompiler_TEMPLATE_MUL_LONG:
472/* File: armv5te/TEMPLATE_MUL_LONG.S */
473    /*
474     * Signed 64-bit integer multiply.
475     *
476     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
477     *
478     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
479     *        WX
480     *      x YZ
481     *  --------
482     *     ZW ZX
483     *  YW YX
484     *
485     * The low word of the result holds ZX, the high word holds
486     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
487     * it doesn't fit in the low 64 bits.
488     *
489     * Unlike most ARM math operations, multiply instructions have
490     * restrictions on using the same register more than once (Rd and Rm
491     * cannot be the same).
492     */
493    /* mul-long vAA, vBB, vCC */
494    mul     ip, r2, r1                  @  ip<- ZxW
495    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
496    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
497    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
498    mov     r0,r9
499    mov     r1,r10
500    bx      lr
501
502/* ------------------------------ */
503    .balign 4
504    .global dvmCompiler_TEMPLATE_SHL_LONG
505dvmCompiler_TEMPLATE_SHL_LONG:
506/* File: armv5te/TEMPLATE_SHL_LONG.S */
507    /*
508     * Long integer shift.  This is different from the generic 32/64-bit
509     * binary operations because vAA/vBB are 64-bit but vCC (the shift
510     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
511     * 6 bits.
512     */
513    /* shl-long vAA, vBB, vCC */
514    and     r2, r2, #63                 @ r2<- r2 & 0x3f
515    mov     r1, r1, asl r2              @  r1<- r1 << r2
516    rsb     r3, r2, #32                 @  r3<- 32 - r2
517    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
518    subs    ip, r2, #32                 @  ip<- r2 - 32
519    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
520    mov     r0, r0, asl r2              @  r0<- r0 << r2
521    bx      lr
522
523/* ------------------------------ */
524    .balign 4
525    .global dvmCompiler_TEMPLATE_SHR_LONG
526dvmCompiler_TEMPLATE_SHR_LONG:
527/* File: armv5te/TEMPLATE_SHR_LONG.S */
528    /*
529     * Long integer shift.  This is different from the generic 32/64-bit
530     * binary operations because vAA/vBB are 64-bit but vCC (the shift
531     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
532     * 6 bits.
533     */
534    /* shr-long vAA, vBB, vCC */
535    and     r2, r2, #63                 @ r0<- r0 & 0x3f
536    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
537    rsb     r3, r2, #32                 @  r3<- 32 - r2
538    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
539    subs    ip, r2, #32                 @  ip<- r2 - 32
540    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
541    mov     r1, r1, asr r2              @  r1<- r1 >> r2
542    bx      lr
543
544
545/* ------------------------------ */
546    .balign 4
547    .global dvmCompiler_TEMPLATE_USHR_LONG
548dvmCompiler_TEMPLATE_USHR_LONG:
549/* File: armv5te/TEMPLATE_USHR_LONG.S */
550    /*
551     * Long integer shift.  This is different from the generic 32/64-bit
552     * binary operations because vAA/vBB are 64-bit but vCC (the shift
553     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
554     * 6 bits.
555     */
556    /* ushr-long vAA, vBB, vCC */
557    and     r2, r2, #63                 @ r0<- r0 & 0x3f
558    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
559    rsb     r3, r2, #32                 @  r3<- 32 - r2
560    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
561    subs    ip, r2, #32                 @  ip<- r2 - 32
562    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
563    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
564    bx      lr
565
566
567/* ------------------------------ */
568    .balign 4
569    .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
570dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
571/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
572/* File: armv5te-vfp/fbinop.S */
573    /*
574     * Generic 32-bit floating point operation.  Provide an "instr" line that
575     * specifies an instruction that performs s2 = s0 op s1.
576     *
577     * On entry:
578     *     r0 = target dalvik register address
579     *     r1 = op1 address
580     *     r2 = op2 address
581     */
582     flds    s0,[r1]
583     flds    s1,[r2]
584     fadds   s2, s0, s1
585     fsts    s2,[r0]
586     bx      lr
587
588
589/* ------------------------------ */
590    .balign 4
591    .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
592dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
593/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
594/* File: armv5te-vfp/fbinop.S */
595    /*
596     * Generic 32-bit floating point operation.  Provide an "instr" line that
597     * specifies an instruction that performs s2 = s0 op s1.
598     *
599     * On entry:
600     *     r0 = target dalvik register address
601     *     r1 = op1 address
602     *     r2 = op2 address
603     */
604     flds    s0,[r1]
605     flds    s1,[r2]
606     fsubs   s2, s0, s1
607     fsts    s2,[r0]
608     bx      lr
609
610
611/* ------------------------------ */
612    .balign 4
613    .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
614dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
615/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
616/* File: armv5te-vfp/fbinop.S */
617    /*
618     * Generic 32-bit floating point operation.  Provide an "instr" line that
619     * specifies an instruction that performs s2 = s0 op s1.
620     *
621     * On entry:
622     *     r0 = target dalvik register address
623     *     r1 = op1 address
624     *     r2 = op2 address
625     */
626     flds    s0,[r1]
627     flds    s1,[r2]
628     fmuls   s2, s0, s1
629     fsts    s2,[r0]
630     bx      lr
631
632
633/* ------------------------------ */
634    .balign 4
635    .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
636dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
637/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
638/* File: armv5te-vfp/fbinop.S */
639    /*
640     * Generic 32-bit floating point operation.  Provide an "instr" line that
641     * specifies an instruction that performs s2 = s0 op s1.
642     *
643     * On entry:
644     *     r0 = target dalvik register address
645     *     r1 = op1 address
646     *     r2 = op2 address
647     */
648     flds    s0,[r1]
649     flds    s1,[r2]
650     fdivs   s2, s0, s1
651     fsts    s2,[r0]
652     bx      lr
653
654
655/* ------------------------------ */
656    .balign 4
657    .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
658dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
659/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
660/* File: armv5te-vfp/fbinopWide.S */
661    /*
662     * Generic 64-bit floating point operation.  Provide an "instr" line that
663     * specifies an instruction that performs s2 = s0 op s1.
664     *
665     * On entry:
666     *     r0 = target dalvik register address
667     *     r1 = op1 address
668     *     r2 = op2 address
669     */
670     fldd    d0,[r1]
671     fldd    d1,[r2]
672     faddd   d2, d0, d1
673     fstd    d2,[r0]
674     bx      lr
675
676
677/* ------------------------------ */
678    .balign 4
679    .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
680dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
681/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
682/* File: armv5te-vfp/fbinopWide.S */
683    /*
684     * Generic 64-bit floating point operation.  Provide an "instr" line that
685     * specifies an instruction that performs s2 = s0 op s1.
686     *
687     * On entry:
688     *     r0 = target dalvik register address
689     *     r1 = op1 address
690     *     r2 = op2 address
691     */
692     fldd    d0,[r1]
693     fldd    d1,[r2]
694     fsubd   d2, d0, d1
695     fstd    d2,[r0]
696     bx      lr
697
698
699/* ------------------------------ */
700    .balign 4
701    .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
702dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
703/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
704/* File: armv5te-vfp/fbinopWide.S */
705    /*
706     * Generic 64-bit floating point operation.  Provide an "instr" line that
707     * specifies an instruction that performs s2 = s0 op s1.
708     *
709     * On entry:
710     *     r0 = target dalvik register address
711     *     r1 = op1 address
712     *     r2 = op2 address
713     */
714     fldd    d0,[r1]
715     fldd    d1,[r2]
716     fmuld   d2, d0, d1
717     fstd    d2,[r0]
718     bx      lr
719
720
721/* ------------------------------ */
722    .balign 4
723    .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
724dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
725/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
726/* File: armv5te-vfp/fbinopWide.S */
727    /*
728     * Generic 64-bit floating point operation.  Provide an "instr" line that
729     * specifies an instruction that performs s2 = s0 op s1.
730     *
731     * On entry:
732     *     r0 = target dalvik register address
733     *     r1 = op1 address
734     *     r2 = op2 address
735     */
736     fldd    d0,[r1]
737     fldd    d1,[r2]
738     fdivd   d2, d0, d1
739     fstd    d2,[r0]
740     bx      lr
741
742
743/* ------------------------------ */
744    .balign 4
745    .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
746dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
747/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
748/* File: armv5te-vfp/funopNarrower.S */
749    /*
750     * Generic 64bit-to-32bit floating point unary operation.  Provide an
751     * "instr" line that specifies an instruction that performs "s0 = op d0".
752     *
753     * For: double-to-int, double-to-float
754     *
755     * On entry:
756     *     r0 = target dalvik register address
757     *     r1 = src dalvik register address
758     */
759    /* unop vA, vB */
760    fldd    d0, [r1]                    @ d0<- vB
761    fcvtsd  s0, d0                              @ s0<- op d0
762    fsts    s0, [r0]                    @ vA<- s0
763    bx      lr
764
765
766/* ------------------------------ */
767    .balign 4
768    .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
769dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
770/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
771/* File: armv5te-vfp/funopNarrower.S */
772    /*
773     * Generic 64bit-to-32bit floating point unary operation.  Provide an
774     * "instr" line that specifies an instruction that performs "s0 = op d0".
775     *
776     * For: double-to-int, double-to-float
777     *
778     * On entry:
779     *     r0 = target dalvik register address
780     *     r1 = src dalvik register address
781     */
782    /* unop vA, vB */
783    fldd    d0, [r1]                    @ d0<- vB
784    ftosizd  s0, d0                              @ s0<- op d0
785    fsts    s0, [r0]                    @ vA<- s0
786    bx      lr
787
788
789/* ------------------------------ */
790    .balign 4
791    .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
792dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
793/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
794/* File: armv5te-vfp/funopWider.S */
795    /*
796     * Generic 32bit-to-64bit floating point unary operation.  Provide an
797     * "instr" line that specifies an instruction that performs "d0 = op s0".
798     *
799     * For: int-to-double, float-to-double
800     *
801     * On entry:
802     *     r0 = target dalvik register address
803     *     r1 = src dalvik register address
804     */
805    /* unop vA, vB */
806    flds    s0, [r1]                    @ s0<- vB
807    fcvtds  d0, s0                              @ d0<- op s0
808    fstd    d0, [r0]                    @ vA<- d0
809    bx      lr
810
811
812/* ------------------------------ */
813    .balign 4
814    .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
815dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
816/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
817/* File: armv5te-vfp/funop.S */
818    /*
819     * Generic 32bit-to-32bit floating point unary operation.  Provide an
820     * "instr" line that specifies an instruction that performs "s1 = op s0".
821     *
822     * For: float-to-int, int-to-float
823     *
824     * On entry:
825     *     r0 = target dalvik register address
826     *     r1 = src dalvik register address
827     */
828    /* unop vA, vB */
829    flds    s0, [r1]                    @ s0<- vB
830    ftosizs s1, s0                              @ s1<- op s0
831    fsts    s1, [r0]                    @ vA<- s1
832    bx      lr
833
834
835/* ------------------------------ */
836    .balign 4
837    .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
838dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
839/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
840/* File: armv5te-vfp/funopWider.S */
841    /*
842     * Generic 32bit-to-64bit floating point unary operation.  Provide an
843     * "instr" line that specifies an instruction that performs "d0 = op s0".
844     *
845     * For: int-to-double, float-to-double
846     *
847     * On entry:
848     *     r0 = target dalvik register address
849     *     r1 = src dalvik register address
850     */
851    /* unop vA, vB */
852    flds    s0, [r1]                    @ s0<- vB
853    fsitod  d0, s0                              @ d0<- op s0
854    fstd    d0, [r0]                    @ vA<- d0
855    bx      lr
856
857
858/* ------------------------------ */
859    .balign 4
860    .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
861dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
862/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
863/* File: armv5te-vfp/funop.S */
864    /*
865     * Generic 32bit-to-32bit floating point unary operation.  Provide an
866     * "instr" line that specifies an instruction that performs "s1 = op s0".
867     *
868     * For: float-to-int, int-to-float
869     *
870     * On entry:
871     *     r0 = target dalvik register address
872     *     r1 = src dalvik register address
873     */
874    /* unop vA, vB */
875    flds    s0, [r1]                    @ s0<- vB
876    fsitos  s1, s0                              @ s1<- op s0
877    fsts    s1, [r0]                    @ vA<- s1
878    bx      lr
879
880
881/* ------------------------------ */
882    .balign 4
883    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
884dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
885/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
886    /*
887     * Compare two floating-point values.  Puts 0, 1, or -1 into the
888     * destination register based on the results of the comparison.
889     *
890     * int compare(x, y) {
891     *     if (x == y) {
892     *         return 0;
893     *     } else if (x < y) {
894     *         return -1;
895     *     } else if (x > y) {
896     *         return 1;
897     *     } else {
898     *         return 1;
899     *     }
900     * }
901     *
902     * On entry:
903     *    r0 = &op1 [vBB]
904     *    r1 = &op2 [vCC]
905     */
906    /* op vAA, vBB, vCC */
907    fldd    d0, [r0]                    @ d0<- vBB
908    fldd    d1, [r1]                    @ d1<- vCC
909    fcmpd  d0, d1                       @ compare (vBB, vCC)
910    mov     r0, #1                      @ r0<- 1 (default)
911    fmstat                              @ export status flags
912    mvnmi   r0, #0                      @ (less than) r0<- -1
913    moveq   r0, #0                      @ (equal) r0<- 0
914    bx      lr
915
916
917/* ------------------------------ */
918    .balign 4
919    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
920dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
921/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
922    /*
923     * Compare two floating-point values.  Puts 0, 1, or -1 into the
924     * destination register based on the results of the comparison.
925     *
926     * int compare(x, y) {
927     *     if (x == y) {
928     *         return 0;
929     *     } else if (x > y) {
930     *         return 1;
931     *     } else if (x < y) {
932     *         return -1;
933     *     } else {
934     *         return -1;
935     *     }
936     * }
937     * On entry:
938     *    r0 = &op1 [vBB]
939     *    r1 = &op2 [vCC]
940     */
941    /* op vAA, vBB, vCC */
942    fldd    d0, [r0]                    @ d0<- vBB
943    fldd    d1, [r1]                    @ d1<- vCC
944    fcmped  d0, d1                      @ compare (vBB, vCC)
945    mvn     r0, #0                      @ r0<- -1 (default)
946    fmstat                              @ export status flags
947    movgt   r0, #1                      @ (greater than) r0<- 1
948    moveq   r0, #0                      @ (equal) r0<- 0
949    bx      lr
950
951/* ------------------------------ */
952    .balign 4
953    .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
954dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
955/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
956    /*
957     * Compare two floating-point values.  Puts 0, 1, or -1 into the
958     * destination register based on the results of the comparison.
959     *
960     * int compare(x, y) {
961     *     if (x == y) {
962     *         return 0;
963     *     } else if (x < y) {
964     *         return -1;
965     *     } else if (x > y) {
966     *         return 1;
967     *     } else {
968     *         return 1;
969     *     }
970     * }
971     * On entry:
972     *    r0 = &op1 [vBB]
973     *    r1 = &op2 [vCC]
974     */
975    /* op vAA, vBB, vCC */
976    flds    s0, [r0]                    @ d0<- vBB
977    flds    s1, [r1]                    @ d1<- vCC
978    fcmps  s0, s1                      @ compare (vBB, vCC)
979    mov     r0, #1                      @ r0<- 1 (default)
980    fmstat                              @ export status flags
981    mvnmi   r0, #0                      @ (less than) r0<- -1
982    moveq   r0, #0                      @ (equal) r0<- 0
983    bx      lr
984
985/* ------------------------------ */
986    .balign 4
987    .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
988dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
989/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
990    /*
991     * Compare two floating-point values.  Puts 0, 1, or -1 into the
992     * destination register based on the results of the comparison.
993     *
994     * int compare(x, y) {
995     *     if (x == y) {
996     *         return 0;
997     *     } else if (x > y) {
998     *         return 1;
999     *     } else if (x < y) {
1000     *         return -1;
1001     *     } else {
1002     *         return -1;
1003     *     }
1004     * }
1005     * On entry:
1006     *    r0 = &op1 [vBB]
1007     *    r1 = &op2 [vCC]
1008     */
1009    /* op vAA, vBB, vCC */
1010    flds    s0, [r0]                    @ d0<- vBB
1011    flds    s1, [r1]                    @ d1<- vCC
1012    fcmps  s0, s1                      @ compare (vBB, vCC)
1013    mvn     r0, #0                      @ r0<- -1 (default)
1014    fmstat                              @ export status flags
1015    movgt   r0, #1                      @ (greater than) r0<- 1
1016    moveq   r0, #0                      @ (equal) r0<- 0
1017    bx      lr
1018
1019/* ------------------------------ */
1020    .balign 4
1021    .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
1022dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
1023/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
1024    /*
1025     * 64-bit floating point vfp sqrt operation.
1026     * If the result is a NaN, bail out to library code to do
1027     * the right thing.
1028     *
1029     * On entry:
1030     *     r2 src addr of op1
1031     * On exit:
1032     *     r0,r1 = res
1033     */
1034    fldd    d0, [r2]
1035    fsqrtd  d1, d0
1036    fcmpd   d1, d1
1037    fmstat
1038    fmrrd   r0, r1, d1
1039    bxeq    lr   @ Result OK - return
1040    ldr     r2, .Lsqrt
1041    fmrrd   r0, r1, d0   @ reload orig operand
1042    bx      r2   @ tail call to sqrt library routine
1043
1044.Lsqrt:
1045    .word   sqrt
1046
1047/* ------------------------------ */
1048    .balign 4
1049    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
1050dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
1051/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
1052    /*
1053     * Throw an exception from JIT'ed code.
1054     * On entry:
1055     *    r0    Dalvik PC that raises the exception
1056     */
1057    b       .LhandleException
1058
1059/* ------------------------------ */
1060    .balign 4
1061    .global dvmCompiler_TEMPLATE_SAVE_STATE
1062dvmCompiler_TEMPLATE_SAVE_STATE:
1063/* File: armv5te-vfp/TEMPLATE_SAVE_STATE.S */
1064    /*
1065     * This handler performs a register save for selfVerification mode.
1066     * On entry:
1067     *    Top of stack + 4: r7 value to save
1068     *    Top of stack + 0: r0 value to save
1069     *    r0 - offset from rGLUE to the beginning of the heapArgSpace record
1070     *    r7 - the value of regMap
1071     *
1072     * The handler must save regMap, r0-r12 and then return with r0-r12
1073     * with their original values (note that this means r0 and r7 must take
1074     * the values on the stack - not the ones in those registers on entry.
1075     * Finally, the two registers previously pushed must be popped.
1076     */
1077    add     r0, r0, rGLUE               @ pointer to heapArgSpace
1078    stmia   r0!, {r7}                   @ save regMap
1079    ldr     r7, [r13, #0]               @ recover r0 value
1080    stmia   r0!, {r7}                   @ save r0
1081    ldr     r7, [r13, #4]               @ recover r7 value
1082    stmia   r0!, {r1-r12}
1083    add     r0, #12                     @ move to start of FP save regio
1084    vstmia  r0, {d0-d15}
1085    pop     {r0, r7}                    @ recover r0, r7
1086    bx      lr
1087
1088/* ------------------------------ */
1089    .balign 4
1090    .global dvmCompiler_TEMPLATE_RESTORE_STATE
1091dvmCompiler_TEMPLATE_RESTORE_STATE:
1092/* File: armv5te-vfp/TEMPLATE_RESTORE_STATE.S */
1093    /*
1094     * This handler restores state following a selfVerification memory access.
1095     * On entry:
1096     *    r0 - offset from rGLUE to the 1st element of the coreRegs save array.
1097     */
1098    add     r0, r0, rGLUE               @ pointer to heapArgSpace.coreRegs[0]
1099    add     r0, #64                     @ pointer to heapArgSpace.fpRegs[0]
1100    vldmia  r0, {d0-d15}
1101    sub     r0, #64                     @ pointer to heapArgSpace.coreRegs[0]
1102    ldmia   r0, {r0-r12}
1103    bx      lr
1104
1105/* ------------------------------ */
1106    .balign 4
1107    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
1108dvmCompiler_TEMPLATE_STRING_COMPARETO:
1109/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
1110    /*
1111     * String's compareTo.
1112     *
1113     * Requires r0/r1 to have been previously checked for null.  Will
1114     * return negative if this's string is < comp, 0 if they are the
1115     * same and positive if >.
1116     *
1117     * IMPORTANT NOTE:
1118     *
1119     * This code relies on hard-coded offsets for string objects, and must be
1120     * kept in sync with definitions in UtfString.h.  See asm-constants.h
1121     *
1122     * On entry:
1123     *    r0:   this object pointer
1124     *    r1:   comp object pointer
1125     *
1126     */
1127
1128    mov    r2, r0         @ this to r2, opening up r0 for return value
1129    subs   r0, r2, r1     @ Same?
1130    bxeq   lr
1131
1132    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
1133    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
1134    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
1135    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
1136    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
1137    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
1138
1139    /*
1140     * At this point, we have:
1141     *    value:  r2/r1
1142     *    offset: r4/r9
1143     *    count:  r7/r10
1144     * We're going to compute
1145     *    r11 <- countDiff
1146     *    r10 <- minCount
1147     */
1148     subs  r11, r7, r10
1149     movls r10, r7
1150
1151     /* Now, build pointers to the string data */
1152     add   r2, r2, r4, lsl #1
1153     add   r1, r1, r9, lsl #1
1154     /*
1155      * Note: data pointers point to previous element so we can use pre-index
1156      * mode with base writeback.
1157      */
1158     add   r2, #16-2   @ offset to contents[-1]
1159     add   r1, #16-2   @ offset to contents[-1]
1160
1161     /*
1162      * At this point we have:
1163      *   r2: *this string data
1164      *   r1: *comp string data
1165      *   r10: iteration count for comparison
1166      *   r11: value to return if the first part of the string is equal
1167      *   r0: reserved for result
1168      *   r3, r4, r7, r8, r9, r12 available for loading string data
1169      */
1170
1171    subs  r10, #2
1172    blt   do_remainder2
1173
1174      /*
1175       * Unroll the first two checks so we can quickly catch early mismatch
1176       * on long strings (but preserve incoming alignment)
1177       */
1178
1179    ldrh  r3, [r2, #2]!
1180    ldrh  r4, [r1, #2]!
1181    ldrh  r7, [r2, #2]!
1182    ldrh  r8, [r1, #2]!
1183    subs  r0, r3, r4
1184    subeqs  r0, r7, r8
1185    bxne  lr
1186    cmp   r10, #28
1187    bgt   do_memcmp16
1188    subs  r10, #3
1189    blt   do_remainder
1190
1191loopback_triple:
1192    ldrh  r3, [r2, #2]!
1193    ldrh  r4, [r1, #2]!
1194    ldrh  r7, [r2, #2]!
1195    ldrh  r8, [r1, #2]!
1196    ldrh  r9, [r2, #2]!
1197    ldrh  r12,[r1, #2]!
1198    subs  r0, r3, r4
1199    subeqs  r0, r7, r8
1200    subeqs  r0, r9, r12
1201    bxne  lr
1202    subs  r10, #3
1203    bge   loopback_triple
1204
1205do_remainder:
1206    adds  r10, #3
1207    beq   returnDiff
1208
1209loopback_single:
1210    ldrh  r3, [r2, #2]!
1211    ldrh  r4, [r1, #2]!
1212    subs  r0, r3, r4
1213    bxne  lr
1214    subs  r10, #1
1215    bne     loopback_single
1216
1217returnDiff:
1218    mov   r0, r11
1219    bx    lr
1220
1221do_remainder2:
1222    adds  r10, #2
1223    bne   loopback_single
1224    mov   r0, r11
1225    bx    lr
1226
1227    /* Long string case */
1228do_memcmp16:
1229    mov   r4, lr
1230    ldr   lr, .Lmemcmp16
1231    mov   r7, r11
1232    add   r0, r2, #2
1233    add   r1, r1, #2
1234    mov   r2, r10
1235    blx   lr
1236    cmp   r0, #0
1237    bxne  r4
1238    mov   r0, r7
1239    bx    r4
1240
1241.Lmemcmp16:
1242    .word __memcmp16
1243
1244
1245/* ------------------------------ */
1246    .balign 4
1247    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
1248dvmCompiler_TEMPLATE_STRING_INDEXOF:
1249/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
1250    /*
1251     * String's indexOf.
1252     *
1253     * Requires r0 to have been previously checked for null.  Will
1254     * return index of match of r1 in r0.
1255     *
1256     * IMPORTANT NOTE:
1257     *
1258     * This code relies on hard-coded offsets for string objects, and must be
1259     * kept in sync wth definitions in UtfString.h  See asm-constants.h
1260     *
1261     * On entry:
1262     *    r0:   string object pointer
1263     *    r1:   char to match
1264     *    r2:   Starting offset in string data
1265     */
1266
1267    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
1268    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
1269    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
1270
1271    /*
1272     * At this point, we have:
1273     *    r0: object pointer
1274     *    r1: char to match
1275     *    r2: starting offset
1276     *    r7: offset
1277     *    r8: string length
1278     */
1279
1280     /* Build pointer to start of string data */
1281     add   r0, #16
1282     add   r0, r0, r7, lsl #1
1283
1284     /* Save a copy of starting data in r7 */
1285     mov   r7, r0
1286
1287     /* Clamp start to [0..count] */
1288     cmp   r2, #0
1289     movlt r2, #0
1290     cmp   r2, r8
1291     movgt r2, r8
1292
1293     /* Build pointer to start of data to compare and pre-bias */
1294     add   r0, r0, r2, lsl #1
1295     sub   r0, #2
1296
1297     /* Compute iteration count */
1298     sub   r8, r2
1299
1300     /*
1301      * At this point we have:
1302      *   r0: start of data to test
1303      *   r1: chat to compare
1304      *   r8: iteration count
1305      *   r7: original start of string
1306      *   r3, r4, r9, r10, r11, r12 available for loading string data
1307      */
1308
1309    subs  r8, #4
1310    blt   indexof_remainder
1311
1312indexof_loop4:
1313    ldrh  r3, [r0, #2]!
1314    ldrh  r4, [r0, #2]!
1315    ldrh  r10, [r0, #2]!
1316    ldrh  r11, [r0, #2]!
1317    cmp   r3, r1
1318    beq   match_0
1319    cmp   r4, r1
1320    beq   match_1
1321    cmp   r10, r1
1322    beq   match_2
1323    cmp   r11, r1
1324    beq   match_3
1325    subs  r8, #4
1326    bge   indexof_loop4
1327
1328indexof_remainder:
1329    adds    r8, #4
1330    beq     indexof_nomatch
1331
1332indexof_loop1:
1333    ldrh  r3, [r0, #2]!
1334    cmp   r3, r1
1335    beq   match_3
1336    subs  r8, #1
1337    bne   indexof_loop1
1338
1339indexof_nomatch:
1340    mov   r0, #-1
1341    bx    lr
1342
1343match_0:
1344    sub   r0, #6
1345    sub   r0, r7
1346    asr   r0, r0, #1
1347    bx    lr
1348match_1:
1349    sub   r0, #4
1350    sub   r0, r7
1351    asr   r0, r0, #1
1352    bx    lr
1353match_2:
1354    sub   r0, #2
1355    sub   r0, r7
1356    asr   r0, r0, #1
1357    bx    lr
1358match_3:
1359    sub   r0, r7
1360    asr   r0, r0, #1
1361    bx    lr
1362
1363
1364/* ------------------------------ */
1365    .balign 4
1366    .global dvmCompiler_TEMPLATE_INTERPRET
1367dvmCompiler_TEMPLATE_INTERPRET:
1368/* File: armv5te/TEMPLATE_INTERPRET.S */
1369    /*
1370     * This handler transfers control to the interpeter without performing
1371     * any lookups.  It may be called either as part of a normal chaining
1372     * operation, or from the transition code in header.S.  We distinquish
1373     * the two cases by looking at the link register.  If called from a
1374     * translation chain, it will point to the chaining Dalvik PC + 1.
1375     * On entry:
1376     *    lr - if NULL:
1377     *        r1 - the Dalvik PC to begin interpretation.
1378     *    else
1379     *        [lr, #-1] contains Dalvik PC to begin interpretation
1380     *    rGLUE - pointer to interpState
1381     *    rFP - Dalvik frame pointer
1382     */
1383    cmp     lr, #0
1384    ldrne   r1,[lr, #-1]
1385    ldr     r2, .LinterpPunt
1386    mov     r0, r1                       @ set Dalvik PC
1387    bx      r2
1388    @ doesn't return
1389
1390.LinterpPunt:
1391    .word   dvmJitToInterpPunt
1392
1393    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1394/* File: armv5te/footer.S */
1395/*
1396 * ===========================================================================
1397 *  Common subroutines and data
1398 * ===========================================================================
1399 */
1400
1401    .text
1402    .align  2
1403.LinvokeNative:
1404    @ Prep for the native call
1405    @ r1 = newFP, r0 = methodToCall
1406    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1407    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1408    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1409    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1410                                        @ newFp->localRefCookie=top
1411    mov     r9, r3                      @ r9<- glue->self (preserve)
1412    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1413
1414    mov     r2, r0                      @ r2<- methodToCall
1415    mov     r0, r1                      @ r0<- newFP
1416    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1417
1418    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1419
1420    @ native return; r9=self, r10=newSaveArea
1421    @ equivalent to dvmPopJniLocals
1422    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1423    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1424    ldr     r1, [r9, #offThread_exception] @ check for exception
1425    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1426    cmp     r1, #0                      @ null?
1427    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1428    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1429    bne     .LhandleException             @ no, handle exception
1430    bx      r2
1431
1432/*
1433 * On entry:
1434 * r0  Faulting Dalvik PC
1435 */
1436.LhandleException:
1437    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1438    ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1439    mov     rPC, r0                 @ reload the faulting Dalvik address
1440    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1441
1442    .align  2
1443.LdvmAsmInstructionStart:
1444    .word   dvmAsmInstructionStart
1445.LdvmJitToInterpNoChain:
1446    .word   dvmJitToInterpNoChain
1447.LdvmMterpStdBail:
1448    .word   dvmMterpStdBail
1449.LdvmMterpCommonExceptionThrown:
1450    .word   dvmMterpCommonExceptionThrown
1451.L__aeabi_cdcmple:
1452    .word   __aeabi_cdcmple
1453.L__aeabi_cfcmple:
1454    .word   __aeabi_cfcmple
1455
1456    .global dmvCompilerTemplateEnd
1457dmvCompilerTemplateEnd:
1458
1459#endif /* WITH_JIT */
1460
1461