CompilerTemplateAsm-armv5te-vfp.S revision 9a8c75adb2abf551d06dbf757bff558c1feded08
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    bne     .LhandleException             @ no, handle exception
444    bx      r2
445
446
447/* ------------------------------ */
448    .balign 4
449    .global dvmCompiler_TEMPLATE_MUL_LONG
450dvmCompiler_TEMPLATE_MUL_LONG:
451/* File: armv5te/TEMPLATE_MUL_LONG.S */
452    /*
453     * Signed 64-bit integer multiply.
454     *
455     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
456     *
457     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
458     *        WX
459     *      x YZ
460     *  --------
461     *     ZW ZX
462     *  YW YX
463     *
464     * The low word of the result holds ZX, the high word holds
465     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
466     * it doesn't fit in the low 64 bits.
467     *
468     * Unlike most ARM math operations, multiply instructions have
469     * restrictions on using the same register more than once (Rd and Rm
470     * cannot be the same).
471     */
472    /* mul-long vAA, vBB, vCC */
473    mul     ip, r2, r1                  @  ip<- ZxW
474    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
475    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
476    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
477    mov     r0,r9
478    mov     r1,r10
479    bx      lr
480
481/* ------------------------------ */
482    .balign 4
483    .global dvmCompiler_TEMPLATE_SHL_LONG
484dvmCompiler_TEMPLATE_SHL_LONG:
485/* File: armv5te/TEMPLATE_SHL_LONG.S */
486    /*
487     * Long integer shift.  This is different from the generic 32/64-bit
488     * binary operations because vAA/vBB are 64-bit but vCC (the shift
489     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
490     * 6 bits.
491     */
492    /* shl-long vAA, vBB, vCC */
493    and     r2, r2, #63                 @ r2<- r2 & 0x3f
494    mov     r1, r1, asl r2              @  r1<- r1 << r2
495    rsb     r3, r2, #32                 @  r3<- 32 - r2
496    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
497    subs    ip, r2, #32                 @  ip<- r2 - 32
498    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
499    mov     r0, r0, asl r2              @  r0<- r0 << r2
500    bx      lr
501
502/* ------------------------------ */
503    .balign 4
504    .global dvmCompiler_TEMPLATE_SHR_LONG
505dvmCompiler_TEMPLATE_SHR_LONG:
506/* File: armv5te/TEMPLATE_SHR_LONG.S */
507    /*
508     * Long integer shift.  This is different from the generic 32/64-bit
509     * binary operations because vAA/vBB are 64-bit but vCC (the shift
510     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
511     * 6 bits.
512     */
513    /* shr-long vAA, vBB, vCC */
514    and     r2, r2, #63                 @ r0<- r0 & 0x3f
515    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
516    rsb     r3, r2, #32                 @  r3<- 32 - r2
517    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
518    subs    ip, r2, #32                 @  ip<- r2 - 32
519    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
520    mov     r1, r1, asr r2              @  r1<- r1 >> r2
521    bx      lr
522
523
524/* ------------------------------ */
525    .balign 4
526    .global dvmCompiler_TEMPLATE_USHR_LONG
527dvmCompiler_TEMPLATE_USHR_LONG:
528/* File: armv5te/TEMPLATE_USHR_LONG.S */
529    /*
530     * Long integer shift.  This is different from the generic 32/64-bit
531     * binary operations because vAA/vBB are 64-bit but vCC (the shift
532     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
533     * 6 bits.
534     */
535    /* ushr-long vAA, vBB, vCC */
536    and     r2, r2, #63                 @ r0<- r0 & 0x3f
537    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
538    rsb     r3, r2, #32                 @  r3<- 32 - r2
539    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
540    subs    ip, r2, #32                 @  ip<- r2 - 32
541    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
542    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
543    bx      lr
544
545
546/* ------------------------------ */
547    .balign 4
548    .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
549dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
550/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
551/* File: armv5te-vfp/fbinop.S */
552    /*
553     * Generic 32-bit floating point operation.  Provide an "instr" line that
554     * specifies an instruction that performs s2 = s0 op s1.
555     *
556     * On entry:
557     *     r0 = target dalvik register address
558     *     r1 = op1 address
559     *     r2 = op2 address
560     */
561     flds    s0,[r1]
562     flds    s1,[r2]
563     fadds   s2, s0, s1
564     fsts    s2,[r0]
565     bx      lr
566
567
568/* ------------------------------ */
569    .balign 4
570    .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
571dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
572/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
573/* File: armv5te-vfp/fbinop.S */
574    /*
575     * Generic 32-bit floating point operation.  Provide an "instr" line that
576     * specifies an instruction that performs s2 = s0 op s1.
577     *
578     * On entry:
579     *     r0 = target dalvik register address
580     *     r1 = op1 address
581     *     r2 = op2 address
582     */
583     flds    s0,[r1]
584     flds    s1,[r2]
585     fsubs   s2, s0, s1
586     fsts    s2,[r0]
587     bx      lr
588
589
590/* ------------------------------ */
591    .balign 4
592    .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
593dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
594/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
595/* File: armv5te-vfp/fbinop.S */
596    /*
597     * Generic 32-bit floating point operation.  Provide an "instr" line that
598     * specifies an instruction that performs s2 = s0 op s1.
599     *
600     * On entry:
601     *     r0 = target dalvik register address
602     *     r1 = op1 address
603     *     r2 = op2 address
604     */
605     flds    s0,[r1]
606     flds    s1,[r2]
607     fmuls   s2, s0, s1
608     fsts    s2,[r0]
609     bx      lr
610
611
612/* ------------------------------ */
613    .balign 4
614    .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
615dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
616/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
617/* File: armv5te-vfp/fbinop.S */
618    /*
619     * Generic 32-bit floating point operation.  Provide an "instr" line that
620     * specifies an instruction that performs s2 = s0 op s1.
621     *
622     * On entry:
623     *     r0 = target dalvik register address
624     *     r1 = op1 address
625     *     r2 = op2 address
626     */
627     flds    s0,[r1]
628     flds    s1,[r2]
629     fdivs   s2, s0, s1
630     fsts    s2,[r0]
631     bx      lr
632
633
634/* ------------------------------ */
635    .balign 4
636    .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
637dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
638/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
639/* File: armv5te-vfp/fbinopWide.S */
640    /*
641     * Generic 64-bit floating point operation.  Provide an "instr" line that
642     * specifies an instruction that performs s2 = s0 op s1.
643     *
644     * On entry:
645     *     r0 = target dalvik register address
646     *     r1 = op1 address
647     *     r2 = op2 address
648     */
649     fldd    d0,[r1]
650     fldd    d1,[r2]
651     faddd   d2, d0, d1
652     fstd    d2,[r0]
653     bx      lr
654
655
656/* ------------------------------ */
657    .balign 4
658    .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
659dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
660/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
661/* File: armv5te-vfp/fbinopWide.S */
662    /*
663     * Generic 64-bit floating point operation.  Provide an "instr" line that
664     * specifies an instruction that performs s2 = s0 op s1.
665     *
666     * On entry:
667     *     r0 = target dalvik register address
668     *     r1 = op1 address
669     *     r2 = op2 address
670     */
671     fldd    d0,[r1]
672     fldd    d1,[r2]
673     fsubd   d2, d0, d1
674     fstd    d2,[r0]
675     bx      lr
676
677
678/* ------------------------------ */
679    .balign 4
680    .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
681dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
682/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
683/* File: armv5te-vfp/fbinopWide.S */
684    /*
685     * Generic 64-bit floating point operation.  Provide an "instr" line that
686     * specifies an instruction that performs s2 = s0 op s1.
687     *
688     * On entry:
689     *     r0 = target dalvik register address
690     *     r1 = op1 address
691     *     r2 = op2 address
692     */
693     fldd    d0,[r1]
694     fldd    d1,[r2]
695     fmuld   d2, d0, d1
696     fstd    d2,[r0]
697     bx      lr
698
699
700/* ------------------------------ */
701    .balign 4
702    .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
703dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
704/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
705/* File: armv5te-vfp/fbinopWide.S */
706    /*
707     * Generic 64-bit floating point operation.  Provide an "instr" line that
708     * specifies an instruction that performs s2 = s0 op s1.
709     *
710     * On entry:
711     *     r0 = target dalvik register address
712     *     r1 = op1 address
713     *     r2 = op2 address
714     */
715     fldd    d0,[r1]
716     fldd    d1,[r2]
717     fdivd   d2, d0, d1
718     fstd    d2,[r0]
719     bx      lr
720
721
722/* ------------------------------ */
723    .balign 4
724    .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
725dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
726/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
727/* File: armv5te-vfp/funopNarrower.S */
728    /*
729     * Generic 64bit-to-32bit floating point unary operation.  Provide an
730     * "instr" line that specifies an instruction that performs "s0 = op d0".
731     *
732     * For: double-to-int, double-to-float
733     *
734     * On entry:
735     *     r0 = target dalvik register address
736     *     r1 = src dalvik register address
737     */
738    /* unop vA, vB */
739    fldd    d0, [r1]                    @ d0<- vB
740    fcvtsd  s0, d0                              @ s0<- op d0
741    fsts    s0, [r0]                    @ vA<- s0
742    bx      lr
743
744
745/* ------------------------------ */
746    .balign 4
747    .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
748dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
749/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
750/* File: armv5te-vfp/funopNarrower.S */
751    /*
752     * Generic 64bit-to-32bit floating point unary operation.  Provide an
753     * "instr" line that specifies an instruction that performs "s0 = op d0".
754     *
755     * For: double-to-int, double-to-float
756     *
757     * On entry:
758     *     r0 = target dalvik register address
759     *     r1 = src dalvik register address
760     */
761    /* unop vA, vB */
762    fldd    d0, [r1]                    @ d0<- vB
763    ftosizd  s0, d0                              @ s0<- op d0
764    fsts    s0, [r0]                    @ vA<- s0
765    bx      lr
766
767
768/* ------------------------------ */
769    .balign 4
770    .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
771dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
772/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
773/* File: armv5te-vfp/funopWider.S */
774    /*
775     * Generic 32bit-to-64bit floating point unary operation.  Provide an
776     * "instr" line that specifies an instruction that performs "d0 = op s0".
777     *
778     * For: int-to-double, float-to-double
779     *
780     * On entry:
781     *     r0 = target dalvik register address
782     *     r1 = src dalvik register address
783     */
784    /* unop vA, vB */
785    flds    s0, [r1]                    @ s0<- vB
786    fcvtds  d0, s0                              @ d0<- op s0
787    fstd    d0, [r0]                    @ vA<- d0
788    bx      lr
789
790
791/* ------------------------------ */
792    .balign 4
793    .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
794dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
795/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
796/* File: armv5te-vfp/funop.S */
797    /*
798     * Generic 32bit-to-32bit floating point unary operation.  Provide an
799     * "instr" line that specifies an instruction that performs "s1 = op s0".
800     *
801     * For: float-to-int, int-to-float
802     *
803     * On entry:
804     *     r0 = target dalvik register address
805     *     r1 = src dalvik register address
806     */
807    /* unop vA, vB */
808    flds    s0, [r1]                    @ s0<- vB
809    ftosizs s1, s0                              @ s1<- op s0
810    fsts    s1, [r0]                    @ vA<- s1
811    bx      lr
812
813
814/* ------------------------------ */
815    .balign 4
816    .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
817dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
818/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
819/* File: armv5te-vfp/funopWider.S */
820    /*
821     * Generic 32bit-to-64bit floating point unary operation.  Provide an
822     * "instr" line that specifies an instruction that performs "d0 = op s0".
823     *
824     * For: int-to-double, float-to-double
825     *
826     * On entry:
827     *     r0 = target dalvik register address
828     *     r1 = src dalvik register address
829     */
830    /* unop vA, vB */
831    flds    s0, [r1]                    @ s0<- vB
832    fsitod  d0, s0                              @ d0<- op s0
833    fstd    d0, [r0]                    @ vA<- d0
834    bx      lr
835
836
837/* ------------------------------ */
838    .balign 4
839    .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
840dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
841/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
842/* File: armv5te-vfp/funop.S */
843    /*
844     * Generic 32bit-to-32bit floating point unary operation.  Provide an
845     * "instr" line that specifies an instruction that performs "s1 = op s0".
846     *
847     * For: float-to-int, int-to-float
848     *
849     * On entry:
850     *     r0 = target dalvik register address
851     *     r1 = src dalvik register address
852     */
853    /* unop vA, vB */
854    flds    s0, [r1]                    @ s0<- vB
855    fsitos  s1, s0                              @ s1<- op s0
856    fsts    s1, [r0]                    @ vA<- s1
857    bx      lr
858
859
860/* ------------------------------ */
861    .balign 4
862    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
863dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
864/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
865    /*
866     * Compare two floating-point values.  Puts 0, 1, or -1 into the
867     * destination register based on the results of the comparison.
868     *
869     * int compare(x, y) {
870     *     if (x == y) {
871     *         return 0;
872     *     } else if (x < y) {
873     *         return -1;
874     *     } else if (x > y) {
875     *         return 1;
876     *     } else {
877     *         return 1;
878     *     }
879     * }
880     *
881     * On entry:
882     *    r0 = &op1 [vBB]
883     *    r1 = &op2 [vCC]
884     */
885    /* op vAA, vBB, vCC */
886    fldd    d0, [r0]                    @ d0<- vBB
887    fldd    d1, [r1]                    @ d1<- vCC
888    fcmpd  d0, d1                       @ compare (vBB, vCC)
889    mov     r0, #1                      @ r0<- 1 (default)
890    fmstat                              @ export status flags
891    mvnmi   r0, #0                      @ (less than) r0<- -1
892    moveq   r0, #0                      @ (equal) r0<- 0
893    bx      lr
894
895
896/* ------------------------------ */
897    .balign 4
898    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
899dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
900/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
901    /*
902     * Compare two floating-point values.  Puts 0, 1, or -1 into the
903     * destination register based on the results of the comparison.
904     *
905     * int compare(x, y) {
906     *     if (x == y) {
907     *         return 0;
908     *     } else if (x > y) {
909     *         return 1;
910     *     } else if (x < y) {
911     *         return -1;
912     *     } else {
913     *         return -1;
914     *     }
915     * }
916     * On entry:
917     *    r0 = &op1 [vBB]
918     *    r1 = &op2 [vCC]
919     */
920    /* op vAA, vBB, vCC */
921    fldd    d0, [r0]                    @ d0<- vBB
922    fldd    d1, [r1]                    @ d1<- vCC
923    fcmped  d0, d1                      @ compare (vBB, vCC)
924    mvn     r0, #0                      @ r0<- -1 (default)
925    fmstat                              @ export status flags
926    movgt   r0, #1                      @ (greater than) r0<- 1
927    moveq   r0, #0                      @ (equal) r0<- 0
928    bx      lr
929
930/* ------------------------------ */
931    .balign 4
932    .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
933dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
934/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
935    /*
936     * Compare two floating-point values.  Puts 0, 1, or -1 into the
937     * destination register based on the results of the comparison.
938     *
939     * int compare(x, y) {
940     *     if (x == y) {
941     *         return 0;
942     *     } else if (x < y) {
943     *         return -1;
944     *     } else if (x > y) {
945     *         return 1;
946     *     } else {
947     *         return 1;
948     *     }
949     * }
950     * On entry:
951     *    r0 = &op1 [vBB]
952     *    r1 = &op2 [vCC]
953     */
954    /* op vAA, vBB, vCC */
955    flds    s0, [r0]                    @ d0<- vBB
956    flds    s1, [r1]                    @ d1<- vCC
957    fcmps  s0, s1                      @ compare (vBB, vCC)
958    mov     r0, #1                      @ r0<- 1 (default)
959    fmstat                              @ export status flags
960    mvnmi   r0, #0                      @ (less than) r0<- -1
961    moveq   r0, #0                      @ (equal) r0<- 0
962    bx      lr
963
964/* ------------------------------ */
965    .balign 4
966    .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
967dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
968/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
969    /*
970     * Compare two floating-point values.  Puts 0, 1, or -1 into the
971     * destination register based on the results of the comparison.
972     *
973     * int compare(x, y) {
974     *     if (x == y) {
975     *         return 0;
976     *     } else if (x > y) {
977     *         return 1;
978     *     } else if (x < y) {
979     *         return -1;
980     *     } else {
981     *         return -1;
982     *     }
983     * }
984     * On entry:
985     *    r0 = &op1 [vBB]
986     *    r1 = &op2 [vCC]
987     */
988    /* op vAA, vBB, vCC */
989    flds    s0, [r0]                    @ d0<- vBB
990    flds    s1, [r1]                    @ d1<- vCC
991    fcmps  s0, s1                      @ compare (vBB, vCC)
992    mvn     r0, #0                      @ r0<- -1 (default)
993    fmstat                              @ export status flags
994    movgt   r0, #1                      @ (greater than) r0<- 1
995    moveq   r0, #0                      @ (equal) r0<- 0
996    bx      lr
997
998/* ------------------------------ */
999    .balign 4
1000    .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
1001dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
1002/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
1003    /*
1004     * 64-bit floating point vfp sqrt operation.
1005     * If the result is a NaN, bail out to library code to do
1006     * the right thing.
1007     *
1008     * On entry:
1009     *     r2 src addr of op1
1010     * On exit:
1011     *     r0,r1 = res
1012     */
1013    fldd    d0, [r2]
1014    fsqrtd  d1, d0
1015    fcmpd   d1, d1
1016    fmstat
1017    fmrrd   r0, r1, d1
1018    bxeq    lr   @ Result OK - return
1019    ldr     r2, .Lsqrt
1020    fmrrd   r0, r1, d0   @ reload orig operand
1021    bx      r2   @ tail call to sqrt library routine
1022
1023.Lsqrt:
1024    .word   sqrt
1025
1026/* ------------------------------ */
1027    .balign 4
1028    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
1029dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
1030/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
1031    /*
1032     * Throw an exception from JIT'ed code.
1033     * On entry:
1034     *    r0    Dalvik PC that raises the exception
1035     */
1036    b       .LhandleException
1037
1038/* ------------------------------ */
1039    .balign 4
1040    .global dvmCompiler_TEMPLATE_SAVE_STATE
1041dvmCompiler_TEMPLATE_SAVE_STATE:
1042/* File: armv5te-vfp/TEMPLATE_SAVE_STATE.S */
1043    /*
1044     * This handler performs a register save for selfVerification mode.
1045     * On entry:
1046     *    Top of stack + 4: r7 value to save
1047     *    Top of stack + 0: r0 value to save
1048     *    r0 - offset from rGLUE to the beginning of the heapArgSpace record
1049     *    r7 - the value of regMap
1050     *
1051     * The handler must save regMap, r0-r12 and then return with r0-r12
1052     * with their original values (note that this means r0 and r7 must take
1053     * the values on the stack - not the ones in those registers on entry.
1054     * Finally, the two registers previously pushed must be popped.
1055     */
1056    add     r0, r0, rGLUE               @ pointer to heapArgSpace
1057    stmia   r0!, {r7}                   @ save regMap
1058    ldr     r7, [r13, #0]               @ recover r0 value
1059    stmia   r0!, {r7}                   @ save r0
1060    ldr     r7, [r13, #4]               @ recover r7 value
1061    stmia   r0!, {r1-r12}
1062    add     r0, #12                     @ move to start of FP save regio
1063    vstmia  r0, {d0-d15}
1064    pop     {r0, r7}                    @ recover r0, r7
1065    bx      lr
1066
1067/* ------------------------------ */
1068    .balign 4
1069    .global dvmCompiler_TEMPLATE_RESTORE_STATE
1070dvmCompiler_TEMPLATE_RESTORE_STATE:
1071/* File: armv5te-vfp/TEMPLATE_RESTORE_STATE.S */
1072    /*
1073     * This handler restores state following a selfVerification memory access.
1074     * On entry:
1075     *    r0 - offset from rGLUE to the 1st element of the coreRegs save array.
1076     */
1077    add     r0, r0, rGLUE               @ pointer to heapArgSpace.coreRegs[0]
1078    add     r0, #64                     @ pointer to heapArgSpace.fpRegs[0]
1079    vldmia  r0, {d0-d15}
1080    sub     r0, #64                     @ pointer to heapArgSpace.coreRegs[0]
1081    ldmia   r0, {r0-r12}
1082    bx      lr
1083
1084/* ------------------------------ */
1085    .balign 4
1086    .global dvmCompiler_TEMPLATE_STRING_COMPARETO
1087dvmCompiler_TEMPLATE_STRING_COMPARETO:
1088/* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
1089    /*
1090     * String's compareTo.
1091     *
1092     * Requires r0/r1 to have been previously checked for null.  Will
1093     * return negative if this's string is < comp, 0 if they are the
1094     * same and positive if >.
1095     *
1096     * IMPORTANT NOTE:
1097     *
1098     * This code relies on hard-coded offsets for string objects, and must be
1099     * kept in sync with definitions in UtfString.h.  See asm-constants.h
1100     *
1101     * On entry:
1102     *    r0:   this object pointer
1103     *    r1:   comp object pointer
1104     *
1105     */
1106
1107    mov    r2, r0         @ this to r2, opening up r0 for return value
1108    subs   r0, r2, r1     @ Same?
1109    bxeq   lr
1110
1111    ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
1112    ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
1113    ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
1114    ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
1115    ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
1116    ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
1117
1118    /*
1119     * At this point, we have:
1120     *    value:  r2/r1
1121     *    offset: r4/r9
1122     *    count:  r7/r10
1123     * We're going to compute
1124     *    r11 <- countDiff
1125     *    r10 <- minCount
1126     */
1127     subs  r11, r7, r10
1128     movls r10, r7
1129
1130     /* Now, build pointers to the string data */
1131     add   r2, r2, r4, lsl #1
1132     add   r1, r1, r9, lsl #1
1133     /*
1134      * Note: data pointers point to previous element so we can use pre-index
1135      * mode with base writeback.
1136      */
1137     add   r2, #16-2   @ offset to contents[-1]
1138     add   r1, #16-2   @ offset to contents[-1]
1139
1140     /*
1141      * At this point we have:
1142      *   r2: *this string data
1143      *   r1: *comp string data
1144      *   r10: iteration count for comparison
1145      *   r11: value to return if the first part of the string is equal
1146      *   r0: reserved for result
1147      *   r3, r4, r7, r8, r9, r12 available for loading string data
1148      */
1149
1150    cmp   r10, #3
1151    blt   do_remainder
1152loopback_triple:
1153    ldrh  r3, [r2, #2]!
1154    ldrh  r4, [r1, #2]!
1155    ldrh  r7, [r2, #2]!
1156    ldrh  r8, [r1, #2]!
1157    ldrh  r9, [r2, #2]!
1158    ldrh  r12,[r1, #2]!
1159    subs  r0, r3, r4
1160    subeqs  r0, r7, r8
1161    subeqs  r0, r9, r12
1162    bxne  lr
1163    subs  r10, #3
1164    bgt   loopback_triple
1165
1166do_remainder:
1167    cmp   r10, #0
1168    beq   returnDiff
1169
1170loopback_single:
1171    ldrh  r3, [r2, #2]!
1172    ldrh  r4, [r1, #2]!
1173    subs  r0, r3, r4
1174    bxne  lr
1175    subs  r10, #1
1176    bne     loopback_single
1177
1178returnDiff:
1179    mov   r0, r11
1180    bx    lr
1181
1182
1183/* ------------------------------ */
1184    .balign 4
1185    .global dvmCompiler_TEMPLATE_STRING_INDEXOF
1186dvmCompiler_TEMPLATE_STRING_INDEXOF:
1187/* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
1188    /*
1189     * String's indexOf.
1190     *
1191     * Requires r0 to have been previously checked for null.  Will
1192     * return index of match of r1 in r0.
1193     *
1194     * IMPORTANT NOTE:
1195     *
1196     * This code relies on hard-coded offsets for string objects, and must be
1197     * kept in sync wth definitions in UtfString.h  See asm-constants.h
1198     *
1199     * On entry:
1200     *    r0:   string object pointer
1201     *    r1:   char to match
1202     *    r2:   Starting offset in string data
1203     */
1204
1205    ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
1206    ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
1207    ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
1208
1209    /*
1210     * At this point, we have:
1211     *    r0: object pointer
1212     *    r1: char to match
1213     *    r2: starting offset
1214     *    r7: offset
1215     *    r8: string length
1216     */
1217
1218     /* Build pointer to start of string data */
1219     add   r0, #16
1220     add   r0, r0, r7, lsl #1
1221
1222     /* Save a copy of starting data in r7 */
1223     mov   r7, r0
1224
1225     /* Clamp start to [0..count] */
1226     cmp   r2, #0
1227     movlt r2, #0
1228     cmp   r2, r8
1229     movgt r2, r8
1230
1231     /* Build pointer to start of data to compare and pre-bias */
1232     add   r0, r0, r2, lsl #1
1233     sub   r0, #2
1234
1235     /* Compute iteration count */
1236     sub   r8, r2
1237
1238     /*
1239      * At this point we have:
1240      *   r0: start of data to test
1241      *   r1: chat to compare
1242      *   r8: iteration count
1243      *   r7: original start of string
1244      *   r3, r4, r9, r10, r11, r12 available for loading string data
1245      */
1246
1247    sub   r8, #4
1248    blt   indexof_remainder
1249
1250indexof_loop4:
1251    ldrh  r3, [r0, #2]!
1252    ldrh  r4, [r0, #2]!
1253    ldrh  r10, [r0, #2]!
1254    ldrh  r11, [r0, #2]!
1255    cmp   r3, r1
1256    beq   match_0
1257    cmp   r4, r1
1258    beq   match_1
1259    cmp   r10, r1
1260    beq   match_2
1261    cmp   r11, r1
1262    beq   match_3
1263    subs  r8, #4
1264    bge   indexof_loop4
1265
1266indexof_remainder:
1267    adds    r8, #4
1268    beq     indexof_nomatch
1269
1270indexof_loop1:
1271    ldrh  r3, [r0, #2]!
1272    cmp   r3, r1
1273    beq   match_3
1274    subs  r8, #1
1275    bne   indexof_loop1
1276
1277indexof_nomatch:
1278    mov   r0, #-1
1279    bx    lr
1280
1281match_0:
1282    sub   r0, #6
1283    sub   r0, r7
1284    asr   r0, r0, #1
1285    bx    lr
1286match_1:
1287    sub   r0, #4
1288    sub   r0, r7
1289    asr   r0, r0, #1
1290    bx    lr
1291match_2:
1292    sub   r0, #2
1293    sub   r0, r7
1294    asr   r0, r0, #1
1295    bx    lr
1296match_3:
1297    sub   r0, r7
1298    asr   r0, r0, #1
1299    bx    lr
1300
1301
1302/* ------------------------------ */
1303    .balign 4
1304    .global dvmCompiler_TEMPLATE_INTERPRET
1305dvmCompiler_TEMPLATE_INTERPRET:
1306/* File: armv5te/TEMPLATE_INTERPRET.S */
1307    /*
1308     * This handler transfers control to the interpeter without performing
1309     * any lookups.  It may be called either as part of a normal chaining
1310     * operation, or from the transition code in header.S.  We distinquish
1311     * the two cases by looking at the link register.  If called from a
1312     * translation chain, it will point to the chaining Dalvik PC + 1.
1313     * On entry:
1314     *    lr - if NULL:
1315     *        r1 - the Dalvik PC to begin interpretation.
1316     *    else
1317     *        [lr, #-1] contains Dalvik PC to begin interpretation
1318     *    rGLUE - pointer to interpState
1319     *    rFP - Dalvik frame pointer
1320     */
1321    cmp     lr, #0
1322    ldrne   r1,[lr, #-1]
1323    ldr     r2, .LinterpPunt
1324    mov     r0, r1                       @ set Dalvik PC
1325    bx      r2
1326    @ doesn't return
1327
1328.LinterpPunt:
1329    .word   dvmJitToInterpPunt
1330
1331    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1332/* File: armv5te/footer.S */
1333/*
1334 * ===========================================================================
1335 *  Common subroutines and data
1336 * ===========================================================================
1337 */
1338
1339    .text
1340    .align  2
1341.LinvokeNative:
1342    @ Prep for the native call
1343    @ r1 = newFP, r0 = methodToCall
1344    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1345    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1346    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1347    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1348                                        @ newFp->localRefCookie=top
1349    mov     r9, r3                      @ r9<- glue->self (preserve)
1350    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1351
1352    mov     r2, r0                      @ r2<- methodToCall
1353    mov     r0, r1                      @ r0<- newFP
1354    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1355
1356    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1357
1358    @ native return; r9=self, r10=newSaveArea
1359    @ equivalent to dvmPopJniLocals
1360    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1361    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1362    ldr     r1, [r9, #offThread_exception] @ check for exception
1363    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1364    cmp     r1, #0                      @ null?
1365    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1366    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1367    bne     .LhandleException             @ no, handle exception
1368    bx      r2
1369
1370/*
1371 * On entry:
1372 * r0  Faulting Dalvik PC
1373 */
1374.LhandleException:
1375    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1376    ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1377    mov     rPC, r0                 @ reload the faulting Dalvik address
1378    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1379
1380    .align  2
1381.LdvmAsmInstructionStart:
1382    .word   dvmAsmInstructionStart
1383.LdvmJitToInterpNoChain:
1384    .word   dvmJitToInterpNoChain
1385.LdvmMterpStdBail:
1386    .word   dvmMterpStdBail
1387.LdvmMterpCommonExceptionThrown:
1388    .word   dvmMterpCommonExceptionThrown
1389.L__aeabi_cdcmple:
1390    .word   __aeabi_cdcmple
1391.L__aeabi_cfcmple:
1392    .word   __aeabi_cfcmple
1393
1394    .global dmvCompilerTemplateEnd
1395dmvCompilerTemplateEnd:
1396
1397#endif /* WITH_JIT */
1398
1399