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