• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/*
96 * This is a #include, not a %include, because we want the C pre-processor
97 * to expand the macros into assembler assignment statements.
98 */
99#include "../../../mterp/common/asm-constants.h"
100
101
102/* File: armv5te/platform.S */
103/*
104 * ===========================================================================
105 *  CPU-version-specific defines
106 * ===========================================================================
107 */
108
109/*
110 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
111 * Jump to subroutine.
112 *
113 * May modify IP and LR.
114 */
115.macro  LDR_PC_LR source
116    mov     lr, pc
117    ldr     pc, \source
118.endm
119
120
121    .global dvmCompilerTemplateStart
122    .type   dvmCompilerTemplateStart, %function
123    .text
124
125dvmCompilerTemplateStart:
126
127/* ------------------------------ */
128    .balign 4
129    .global dvmCompiler_TEMPLATE_CMP_LONG
130dvmCompiler_TEMPLATE_CMP_LONG:
131/* File: armv5te/TEMPLATE_CMP_LONG.S */
132    /*
133     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
134     * register based on the results of the comparison.
135     *
136     * We load the full values with LDM, but in practice many values could
137     * be resolved by only looking at the high word.  This could be made
138     * faster or slower by splitting the LDM into a pair of LDRs.
139     *
140     * If we just wanted to set condition flags, we could do this:
141     *  subs    ip, r0, r2
142     *  sbcs    ip, r1, r3
143     *  subeqs  ip, r0, r2
144     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
145     * integer value, which we can do with 2 conditional mov/mvn instructions
146     * (set 1, set -1; if they're equal we already have 0 in ip), giving
147     * us a constant 5-cycle path plus a branch at the end to the
148     * instruction epilogue code.  The multi-compare approach below needs
149     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
150     * in the worst case (the 64-bit values are equal).
151     */
152    /* cmp-long vAA, vBB, vCC */
153    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
154    blt     .LTEMPLATE_CMP_LONG_less            @ signed compare on high part
155    bgt     .LTEMPLATE_CMP_LONG_greater
156    subs    r0, r0, r2                  @ r0<- r0 - r2
157    bxeq     lr
158    bhi     .LTEMPLATE_CMP_LONG_greater         @ unsigned compare on low part
159.LTEMPLATE_CMP_LONG_less:
160    mvn     r0, #0                      @ r0<- -1
161    bx      lr
162.LTEMPLATE_CMP_LONG_greater:
163    mov     r0, #1                      @ r0<- 1
164    bx      lr
165
166
167/* ------------------------------ */
168    .balign 4
169    .global dvmCompiler_TEMPLATE_RETURN
170dvmCompiler_TEMPLATE_RETURN:
171/* File: armv5te/TEMPLATE_RETURN.S */
172    /*
173     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
174     * If the stored value in returnAddr
175     * is non-zero, the caller is compiled by the JIT thus return to the
176     * address in the code cache following the invoke instruction. Otherwise
177     * return to the special dvmJitToInterpNoChain entry point.
178     */
179    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
180    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
181    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
182    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
183    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
184    ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
185                                        @ r2<- method we're returning to
186    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
187    cmp     r2, #0                      @ break frame?
188    beq     1f                          @ bail to interpreter
189    ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
190    mov     rFP, r10                    @ publish new FP
191    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
192    ldr     r8, [r8]                    @ r8<- suspendCount
193
194    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
195    ldr     r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
196    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
197    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
198    str     r1, [rGLUE, #offGlue_methodClassDex]
199    cmp     r8, #0                      @ check the suspendCount
200    movne   r9, #0                      @ clear the chaining cell address
201    cmp     r9, #0                      @ chaining cell exists?
202    blxne   r9                          @ jump to the chaining cell
203    mov     pc, r0                      @ callsite is interpreted
2041:
205    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
206    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
207    mov     r1, #0                      @ changeInterp = false
208    mov     r0, rGLUE                   @ Expecting rGLUE in r0
209    blx     r2                          @ exit the interpreter
210
211/* ------------------------------ */
212    .balign 4
213    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
214dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
215/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
216    /*
217     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
218     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
219     * runtime-resolved callee.
220     */
221    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
222    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
223    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
224    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
225    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
226    add     r3, r1, #1  @ Thumb addr is odd
227    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
228    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
229    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
230    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
231    ldr     r8, [r8]                    @ r3<- suspendCount (int)
232    cmp     r10, r9                     @ bottom < interpStackEnd?
233    bxlt    lr                          @ return to raise stack overflow excep.
234    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
235    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
236    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
237    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
238    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
239    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
240
241
242    @ set up newSaveArea
243    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
244    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
245    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
246    cmp     r8, #0                      @ suspendCount != 0
247    bxne    lr                          @ bail to the interpreter
248    tst     r10, #ACC_NATIVE
249    bne     .LinvokeNative
250
251    ldr     r10, .LdvmJitToInterpNoChain
252    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
253    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
254
255    @ Update "glue" values for the new method
256    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
257    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
258    mov     rFP, r1                         @ fp = newFp
259    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
260
261    @ Start executing the callee
262    mov     pc, r10                         @ dvmJitToInterpNoChain
263
264/* ------------------------------ */
265    .balign 4
266    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
267dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
268/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
269    /*
270     * For monomorphic callsite, setup the Dalvik frame and return to the
271     * Thumb code through the link register to transfer control to the callee
272     * method through a dedicated chaining cell.
273     */
274    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
275    @ methodToCall is guaranteed to be non-native
276.LinvokeChain:
277    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
278    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
279    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
280    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
281    add     r3, r1, #1  @ Thumb addr is odd
282    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
283    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
284    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
285    add     r12, lr, #2                 @ setup the punt-to-interp address
286    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
287    ldr     r8, [r8]                    @ r3<- suspendCount (int)
288    cmp     r10, r9                     @ bottom < interpStackEnd?
289    bxlt    r12                         @ return to raise stack overflow excep.
290    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
291    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
292    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
293    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
294    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
295
296
297    @ set up newSaveArea
298    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
299    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
300    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
301    cmp     r8, #0                      @ suspendCount != 0
302    bxne    r12                         @ bail to the interpreter
303
304    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
305    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
306
307    @ Update "glue" values for the new method
308    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
309    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
310    mov     rFP, r1                         @ fp = newFp
311    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
312
313    bx      lr                              @ return to the callee-chaining cell
314
315
316
317/* ------------------------------ */
318    .balign 4
319    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
320dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
321/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
322    /*
323     * For polymorphic callsite, check whether the cached class pointer matches
324     * the current one. If so setup the Dalvik frame and return to the
325     * Thumb code through the link register to transfer control to the callee
326     * method through a dedicated chaining cell.
327     *
328     * The predicted chaining cell is declared in ArmLIR.h with the
329     * following layout:
330     *
331     *  typedef struct PredictedChainingCell {
332     *      u4 branch;
333     *      const ClassObject *clazz;
334     *      const Method *method;
335     *      u4 counter;
336     *  } PredictedChainingCell;
337     *
338     * Upon returning to the callsite:
339     *    - lr  : to branch to the chaining cell
340     *    - lr+2: to punt to the interpreter
341     *    - lr+4: to fully resolve the callee and may rechain.
342     *            r3 <- class
343     *            r9 <- counter
344     */
345    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
346    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
347    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
348    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
349    ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
350    cmp     r3, r8          @ predicted class == actual class?
351    beq     .LinvokeChain   @ predicted chain is valid
352    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
353    sub     r1, r9, #1      @ count--
354    str     r1, [r2, #12]   @ write back to PredictedChainingCell->counter
355    add     lr, lr, #4      @ return to fully-resolve landing pad
356    /*
357     * r1 <- count
358     * r2 <- &predictedChainCell
359     * r3 <- this->class
360     * r4 <- dPC
361     * r7 <- this->class->vtable
362     */
363    bx      lr
364
365/* ------------------------------ */
366    .balign 4
367    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
368dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
369/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
370    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
371    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
372    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
373    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
374    add     r3, r1, #1  @ Thumb addr is odd
375    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
376    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
377    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
378    ldr     r8, [r8]                    @ r3<- suspendCount (int)
379    cmp     r10, r9                     @ bottom < interpStackEnd?
380    bxlt    lr                          @ return to raise stack overflow excep.
381    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
382    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
383    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
384    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
385
386
387    @ set up newSaveArea
388    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
389    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
390    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
391    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
392    cmp     r8, #0                      @ suspendCount != 0
393    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
394    bxne    lr                          @ bail to the interpreter
395
396    @ go ahead and transfer control to the native code
397    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
398    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
399    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
400                                        @ newFp->localRefCookie=top
401    mov     r9, r3                      @ r9<- glue->self (preserve)
402    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
403
404    mov     r2, r0                      @ r2<- methodToCall
405    mov     r0, r1                      @ r0<- newFP
406    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
407
408    blx     r8                          @ off to the native code
409
410    @ native return; r9=self, r10=newSaveArea
411    @ equivalent to dvmPopJniLocals
412    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
413    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
414    ldr     r1, [r9, #offThread_exception] @ check for exception
415    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
416    cmp     r1, #0                      @ null?
417    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
418    bne     .LhandleException             @ no, handle exception
419    bx      r2
420
421
422/* ------------------------------ */
423    .balign 4
424    .global dvmCompiler_TEMPLATE_MUL_LONG
425dvmCompiler_TEMPLATE_MUL_LONG:
426/* File: armv5te/TEMPLATE_MUL_LONG.S */
427    /*
428     * Signed 64-bit integer multiply.
429     *
430     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
431     *
432     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
433     *        WX
434     *      x YZ
435     *  --------
436     *     ZW ZX
437     *  YW YX
438     *
439     * The low word of the result holds ZX, the high word holds
440     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
441     * it doesn't fit in the low 64 bits.
442     *
443     * Unlike most ARM math operations, multiply instructions have
444     * restrictions on using the same register more than once (Rd and Rm
445     * cannot be the same).
446     */
447    /* mul-long vAA, vBB, vCC */
448    mul     ip, r2, r1                  @  ip<- ZxW
449    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
450    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
451    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
452    mov     r0,r9
453    mov     r1,r10
454    bx      lr
455
456/* ------------------------------ */
457    .balign 4
458    .global dvmCompiler_TEMPLATE_SHL_LONG
459dvmCompiler_TEMPLATE_SHL_LONG:
460/* File: armv5te/TEMPLATE_SHL_LONG.S */
461    /*
462     * Long integer shift.  This is different from the generic 32/64-bit
463     * binary operations because vAA/vBB are 64-bit but vCC (the shift
464     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
465     * 6 bits.
466     */
467    /* shl-long vAA, vBB, vCC */
468    and     r2, r2, #63                 @ r2<- r2 & 0x3f
469    mov     r1, r1, asl r2              @  r1<- r1 << r2
470    rsb     r3, r2, #32                 @  r3<- 32 - r2
471    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
472    subs    ip, r2, #32                 @  ip<- r2 - 32
473    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
474    mov     r0, r0, asl r2              @  r0<- r0 << r2
475    bx      lr
476
477/* ------------------------------ */
478    .balign 4
479    .global dvmCompiler_TEMPLATE_SHR_LONG
480dvmCompiler_TEMPLATE_SHR_LONG:
481/* File: armv5te/TEMPLATE_SHR_LONG.S */
482    /*
483     * Long integer shift.  This is different from the generic 32/64-bit
484     * binary operations because vAA/vBB are 64-bit but vCC (the shift
485     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
486     * 6 bits.
487     */
488    /* shr-long vAA, vBB, vCC */
489    and     r2, r2, #63                 @ r0<- r0 & 0x3f
490    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
491    rsb     r3, r2, #32                 @  r3<- 32 - r2
492    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
493    subs    ip, r2, #32                 @  ip<- r2 - 32
494    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
495    mov     r1, r1, asr r2              @  r1<- r1 >> r2
496    bx      lr
497
498
499/* ------------------------------ */
500    .balign 4
501    .global dvmCompiler_TEMPLATE_USHR_LONG
502dvmCompiler_TEMPLATE_USHR_LONG:
503/* File: armv5te/TEMPLATE_USHR_LONG.S */
504    /*
505     * Long integer shift.  This is different from the generic 32/64-bit
506     * binary operations because vAA/vBB are 64-bit but vCC (the shift
507     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
508     * 6 bits.
509     */
510    /* ushr-long vAA, vBB, vCC */
511    and     r2, r2, #63                 @ r0<- r0 & 0x3f
512    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
513    rsb     r3, r2, #32                 @  r3<- 32 - r2
514    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
515    subs    ip, r2, #32                 @  ip<- r2 - 32
516    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
517    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
518    bx      lr
519
520
521/* ------------------------------ */
522    .balign 4
523    .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
524dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
525/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
526/* File: armv5te-vfp/fbinop.S */
527    /*
528     * Generic 32-bit floating point operation.  Provide an "instr" line that
529     * specifies an instruction that performs s2 = s0 op s1.
530     *
531     * On entry:
532     *     r0 = target dalvik register address
533     *     r1 = op1 address
534     *     r2 = op2 address
535     */
536     flds    s0,[r1]
537     flds    s1,[r2]
538     fadds   s2, s0, s1
539     fsts    s2,[r0]
540     bx      lr
541
542
543/* ------------------------------ */
544    .balign 4
545    .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
546dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
547/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
548/* File: armv5te-vfp/fbinop.S */
549    /*
550     * Generic 32-bit floating point operation.  Provide an "instr" line that
551     * specifies an instruction that performs s2 = s0 op s1.
552     *
553     * On entry:
554     *     r0 = target dalvik register address
555     *     r1 = op1 address
556     *     r2 = op2 address
557     */
558     flds    s0,[r1]
559     flds    s1,[r2]
560     fsubs   s2, s0, s1
561     fsts    s2,[r0]
562     bx      lr
563
564
565/* ------------------------------ */
566    .balign 4
567    .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
568dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
569/* File: armv5te-vfp/TEMPLATE_MUL_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     fmuls   s2, s0, s1
583     fsts    s2,[r0]
584     bx      lr
585
586
587/* ------------------------------ */
588    .balign 4
589    .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
590dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
591/* File: armv5te-vfp/TEMPLATE_DIV_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     fdivs   s2, s0, s1
605     fsts    s2,[r0]
606     bx      lr
607
608
609/* ------------------------------ */
610    .balign 4
611    .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
612dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
613/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
614/* File: armv5te-vfp/fbinopWide.S */
615    /*
616     * Generic 64-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     fldd    d0,[r1]
625     fldd    d1,[r2]
626     faddd   d2, d0, d1
627     fstd    d2,[r0]
628     bx      lr
629
630
631/* ------------------------------ */
632    .balign 4
633    .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
634dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
635/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
636/* File: armv5te-vfp/fbinopWide.S */
637    /*
638     * Generic 64-bit floating point operation.  Provide an "instr" line that
639     * specifies an instruction that performs s2 = s0 op s1.
640     *
641     * On entry:
642     *     r0 = target dalvik register address
643     *     r1 = op1 address
644     *     r2 = op2 address
645     */
646     fldd    d0,[r1]
647     fldd    d1,[r2]
648     fsubd   d2, d0, d1
649     fstd    d2,[r0]
650     bx      lr
651
652
653/* ------------------------------ */
654    .balign 4
655    .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
656dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
657/* File: armv5te-vfp/TEMPLATE_MUL_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     fmuld   d2, d0, d1
671     fstd    d2,[r0]
672     bx      lr
673
674
675/* ------------------------------ */
676    .balign 4
677    .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
678dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
679/* File: armv5te-vfp/TEMPLATE_DIV_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     fdivd   d2, d0, d1
693     fstd    d2,[r0]
694     bx      lr
695
696
697/* ------------------------------ */
698    .balign 4
699    .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
700dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
701/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
702/* File: armv5te-vfp/funopNarrower.S */
703    /*
704     * Generic 64bit-to-32bit floating point unary operation.  Provide an
705     * "instr" line that specifies an instruction that performs "s0 = op d0".
706     *
707     * For: double-to-int, double-to-float
708     *
709     * On entry:
710     *     r0 = target dalvik register address
711     *     r1 = src dalvik register address
712     */
713    /* unop vA, vB */
714    fldd    d0, [r1]                    @ d0<- vB
715    fcvtsd  s0, d0                              @ s0<- op d0
716    fsts    s0, [r0]                    @ vA<- s0
717    bx      lr
718
719
720/* ------------------------------ */
721    .balign 4
722    .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
723dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
724/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
725/* File: armv5te-vfp/funopNarrower.S */
726    /*
727     * Generic 64bit-to-32bit floating point unary operation.  Provide an
728     * "instr" line that specifies an instruction that performs "s0 = op d0".
729     *
730     * For: double-to-int, double-to-float
731     *
732     * On entry:
733     *     r0 = target dalvik register address
734     *     r1 = src dalvik register address
735     */
736    /* unop vA, vB */
737    fldd    d0, [r1]                    @ d0<- vB
738    ftosizd  s0, d0                              @ s0<- op d0
739    fsts    s0, [r0]                    @ vA<- s0
740    bx      lr
741
742
743/* ------------------------------ */
744    .balign 4
745    .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
746dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
747/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
748/* File: armv5te-vfp/funopWider.S */
749    /*
750     * Generic 32bit-to-64bit floating point unary operation.  Provide an
751     * "instr" line that specifies an instruction that performs "d0 = op s0".
752     *
753     * For: int-to-double, float-to-double
754     *
755     * On entry:
756     *     r0 = target dalvik register address
757     *     r1 = src dalvik register address
758     */
759    /* unop vA, vB */
760    flds    s0, [r1]                    @ s0<- vB
761    fcvtds  d0, s0                              @ d0<- op s0
762    fstd    d0, [r0]                    @ vA<- d0
763    bx      lr
764
765
766/* ------------------------------ */
767    .balign 4
768    .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
769dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
770/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
771/* File: armv5te-vfp/funop.S */
772    /*
773     * Generic 32bit-to-32bit floating point unary operation.  Provide an
774     * "instr" line that specifies an instruction that performs "s1 = op s0".
775     *
776     * For: float-to-int, int-to-float
777     *
778     * On entry:
779     *     r0 = target dalvik register address
780     *     r1 = src dalvik register address
781     */
782    /* unop vA, vB */
783    flds    s0, [r1]                    @ s0<- vB
784    ftosizs s1, s0                              @ s1<- op s0
785    fsts    s1, [r0]                    @ vA<- s1
786    bx      lr
787
788
789/* ------------------------------ */
790    .balign 4
791    .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
792dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
793/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
794/* File: armv5te-vfp/funopWider.S */
795    /*
796     * Generic 32bit-to-64bit floating point unary operation.  Provide an
797     * "instr" line that specifies an instruction that performs "d0 = op s0".
798     *
799     * For: int-to-double, float-to-double
800     *
801     * On entry:
802     *     r0 = target dalvik register address
803     *     r1 = src dalvik register address
804     */
805    /* unop vA, vB */
806    flds    s0, [r1]                    @ s0<- vB
807    fsitod  d0, s0                              @ d0<- op s0
808    fstd    d0, [r0]                    @ vA<- d0
809    bx      lr
810
811
812/* ------------------------------ */
813    .balign 4
814    .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
815dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
816/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
817/* File: armv5te-vfp/funop.S */
818    /*
819     * Generic 32bit-to-32bit floating point unary operation.  Provide an
820     * "instr" line that specifies an instruction that performs "s1 = op s0".
821     *
822     * For: float-to-int, int-to-float
823     *
824     * On entry:
825     *     r0 = target dalvik register address
826     *     r1 = src dalvik register address
827     */
828    /* unop vA, vB */
829    flds    s0, [r1]                    @ s0<- vB
830    fsitos  s1, s0                              @ s1<- op s0
831    fsts    s1, [r0]                    @ vA<- s1
832    bx      lr
833
834
835/* ------------------------------ */
836    .balign 4
837    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
838dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
839/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
840    /*
841     * Compare two floating-point values.  Puts 0, 1, or -1 into the
842     * destination register based on the results of the comparison.
843     *
844     * int compare(x, y) {
845     *     if (x == y) {
846     *         return 0;
847     *     } else if (x < y) {
848     *         return -1;
849     *     } else if (x > y) {
850     *         return 1;
851     *     } else {
852     *         return 1;
853     *     }
854     * }
855     *
856     * On entry:
857     *    r0 = &op1 [vBB]
858     *    r1 = &op2 [vCC]
859     */
860    /* op vAA, vBB, vCC */
861    fldd    d0, [r0]                    @ d0<- vBB
862    fldd    d1, [r1]                    @ d1<- vCC
863    fcmped  d0, d1                      @ compare (vBB, vCC)
864    mov     r0, #1                      @ r0<- 1 (default)
865    fmstat                              @ export status flags
866    mvnmi   r0, #0                      @ (less than) r0<- -1
867    moveq   r0, #0                      @ (equal) r0<- 0
868    bx      lr
869
870
871/* ------------------------------ */
872    .balign 4
873    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
874dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
875/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
876    /*
877     * Compare two floating-point values.  Puts 0, 1, or -1 into the
878     * destination register based on the results of the comparison.
879     *
880     * int compare(x, y) {
881     *     if (x == y) {
882     *         return 0;
883     *     } else if (x > y) {
884     *         return 1;
885     *     } else if (x < y) {
886     *         return -1;
887     *     } else {
888     *         return -1;
889     *     }
890     * }
891     * On entry:
892     *    r0 = &op1 [vBB]
893     *    r1 = &op2 [vCC]
894     */
895    /* op vAA, vBB, vCC */
896    fldd    d0, [r0]                    @ d0<- vBB
897    fldd    d1, [r1]                    @ d1<- vCC
898    fcmped  d0, d1                      @ compare (vBB, vCC)
899    mvn     r0, #0                      @ r0<- -1 (default)
900    fmstat                              @ export status flags
901    movgt   r0, #1                      @ (greater than) r0<- 1
902    moveq   r0, #0                      @ (equal) r0<- 0
903    bx      lr
904
905/* ------------------------------ */
906    .balign 4
907    .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
908dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
909/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
910    /*
911     * Compare two floating-point values.  Puts 0, 1, or -1 into the
912     * destination register based on the results of the comparison.
913     *
914     * int compare(x, y) {
915     *     if (x == y) {
916     *         return 0;
917     *     } else if (x < y) {
918     *         return -1;
919     *     } else if (x > y) {
920     *         return 1;
921     *     } else {
922     *         return 1;
923     *     }
924     * }
925     * On entry:
926     *    r0 = &op1 [vBB]
927     *    r1 = &op2 [vCC]
928     */
929    /* op vAA, vBB, vCC */
930    flds    s0, [r0]                    @ d0<- vBB
931    flds    s1, [r1]                    @ d1<- vCC
932    fcmpes  s0, s1                      @ compare (vBB, vCC)
933    mov     r0, #1                      @ r0<- 1 (default)
934    fmstat                              @ export status flags
935    mvnmi   r0, #0                      @ (less than) r0<- -1
936    moveq   r0, #0                      @ (equal) r0<- 0
937    bx      lr
938
939/* ------------------------------ */
940    .balign 4
941    .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
942dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
943/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
944    /*
945     * Compare two floating-point values.  Puts 0, 1, or -1 into the
946     * destination register based on the results of the comparison.
947     *
948     * int compare(x, y) {
949     *     if (x == y) {
950     *         return 0;
951     *     } else if (x > y) {
952     *         return 1;
953     *     } else if (x < y) {
954     *         return -1;
955     *     } else {
956     *         return -1;
957     *     }
958     * }
959     * On entry:
960     *    r0 = &op1 [vBB]
961     *    r1 = &op2 [vCC]
962     */
963    /* op vAA, vBB, vCC */
964    flds    s0, [r0]                    @ d0<- vBB
965    flds    s1, [r1]                    @ d1<- vCC
966    fcmpes  s0, s1                      @ compare (vBB, vCC)
967    mvn     r0, #0                      @ r0<- -1 (default)
968    fmstat                              @ export status flags
969    movgt   r0, #1                      @ (greater than) r0<- 1
970    moveq   r0, #0                      @ (equal) r0<- 0
971    bx      lr
972
973/* ------------------------------ */
974    .balign 4
975    .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
976dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
977/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
978    /*
979     * 64-bit floating point vfp sqrt operation.
980     * If the result is a NaN, bail out to library code to do
981     * the right thing.
982     *
983     * On entry:
984     *     r2 src addr of op1
985     * On exit:
986     *     r0,r1 = res
987     */
988    fldd    d0, [r2]
989    fsqrtd  d1, d0
990    fcmpd   d1, d1
991    fmstat
992    fmrrd   r0, r1, d1
993    bxeq    lr   @ Result OK - return
994    ldr     r2, .Lsqrt
995    fmrrd   r0, r1, d0   @ reload orig operand
996    bx      r2   @ tail call to sqrt library routine
997
998.Lsqrt:
999    .word   sqrt
1000
1001    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1002/* File: armv5te/footer.S */
1003/*
1004 * ===========================================================================
1005 *  Common subroutines and data
1006 * ===========================================================================
1007 */
1008
1009    .text
1010    .align  2
1011.LinvokeNative:
1012    @ Prep for the native call
1013    @ r1 = newFP, r0 = methodToCall
1014    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1015    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1016    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1017    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1018                                        @ newFp->localRefCookie=top
1019    mov     r9, r3                      @ r9<- glue->self (preserve)
1020    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1021
1022    mov     r2, r0                      @ r2<- methodToCall
1023    mov     r0, r1                      @ r0<- newFP
1024    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1025
1026    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1027
1028    @ native return; r9=self, r10=newSaveArea
1029    @ equivalent to dvmPopJniLocals
1030    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1031    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1032    ldr     r1, [r9, #offThread_exception] @ check for exception
1033    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1034    cmp     r1, #0                      @ null?
1035    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1036    bne     .LhandleException             @ no, handle exception
1037    bx      r2
1038
1039/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
1040.LhandleException:
1041    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1042    ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1043    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
1044    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
1045
1046    .align  2
1047.LdvmAsmInstructionStart:
1048    .word   dvmAsmInstructionStart
1049.LdvmJitToInterpNoChain:
1050    .word   dvmJitToInterpNoChain
1051.LdvmMterpStdBail:
1052    .word   dvmMterpStdBail
1053.LdvmMterpCommonExceptionThrown:
1054    .word   dvmMterpCommonExceptionThrown
1055.L__aeabi_cdcmple:
1056    .word   __aeabi_cdcmple
1057.L__aeabi_cfcmple:
1058    .word   __aeabi_cfcmple
1059
1060    .global dmvCompilerTemplateEnd
1061dmvCompilerTemplateEnd:
1062
1063#endif /* WITH_JIT */
1064
1065