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