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