OSDN Git Service

Made Self Verification mode's memory interface less intrusive.
[android-x86/dalvik.git] / vm / compiler / template / out / CompilerTemplateAsm-armv5te-vfp.S
1 /*
2  * This file was generated automatically by gen-template.py for 'armv5te-vfp'.
3  *
4  * --> DO NOT EDIT <--
5  */
6
7 /* File: armv5te/header.S */
8 /*
9  * Copyright (C) 2008 The Android Open Source Project
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23
24 #if defined(WITH_JIT)
25
26 /*
27  * ARMv5 definitions and declarations.
28  */
29
30 /*
31 ARM EABI general notes:
32
33 r0-r3 hold first 4 args to a method; they are not preserved across method calls
34 r4-r8 are available for general use
35 r9 is given special treatment in some situations, but not for us
36 r10 (sl) seems to be generally available
37 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
38 r12 (ip) is scratch -- not preserved across method calls
39 r13 (sp) should be managed carefully in case a signal arrives
40 r14 (lr) must be preserved
41 r15 (pc) can be tinkered with directly
42
43 r0 holds returns of <= 4 bytes
44 r0-r1 hold returns of 8 bytes, low word in r0
45
46 Callee must save/restore r4+ (except r12) if it modifies them.
47
48 Stack is "full descending".  Only the arguments that don't fit in the first 4
49 registers are placed on the stack.  "sp" points at the first stacked argument
50 (i.e. the 5th arg).
51
52 VFP: single-precision results in s0, double-precision results in d0.
53
54 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
55 64-bit quantities (long long, double) must be 64-bit aligned.
56 */
57
58 /*
59 JIT and ARM notes:
60
61 The 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
67 The following registers have fixed assignments in mterp but are scratch
68 registers 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
75 Macros are provided for common operations.  Each macro MUST emit only
76 one instruction to make instruction-counting easier.  They MUST NOT alter
77 unspecified 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
128 dvmCompilerTemplateStart:
129
130 /* ------------------------------ */
131     .balign 4
132     .global dvmCompiler_TEMPLATE_CMP_LONG
133 dvmCompiler_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
173 dvmCompiler_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
219 1:
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
229 dvmCompiler_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
289 dvmCompiler_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
342 dvmCompiler_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
390 dvmCompiler_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
469 dvmCompiler_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
503 dvmCompiler_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
524 dvmCompiler_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
546 dvmCompiler_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
568 dvmCompiler_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
590 dvmCompiler_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
612 dvmCompiler_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
634 dvmCompiler_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
656 dvmCompiler_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
678 dvmCompiler_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
700 dvmCompiler_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
722 dvmCompiler_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
744 dvmCompiler_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
767 dvmCompiler_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
790 dvmCompiler_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
813 dvmCompiler_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
836 dvmCompiler_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
859 dvmCompiler_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
882 dvmCompiler_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
918 dvmCompiler_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
952 dvmCompiler_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
986 dvmCompiler_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
1020 dvmCompiler_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
1048 dvmCompiler_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_MEM_OP_DECODE
1060 dvmCompiler_TEMPLATE_MEM_OP_DECODE:
1061 /* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */
1062 #if defined(WITH_SELF_VERIFICATION)
1063     /*
1064      * This handler encapsulates heap memory ops for selfVerification mode.
1065      *
1066      * The call to the handler is inserted prior to a heap memory operation.
1067      * This handler then calls a function to decode the memory op, and process
1068      * it accordingly. Afterwards, the handler changes the return address to
1069      * skip the memory op so it never gets executed.
1070      */
1071     vpush   {d0-d15}                    @ save out all fp registers
1072     push    {r0-r12,lr}                 @ save out all registers
1073     mov     r0, lr                      @ arg0 <- link register
1074     mov     r1, sp                      @ arg1 <- stack pointer
1075     ldr     r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
1076     blx     r2                          @ decode and handle the mem op
1077     pop     {r0-r12,lr}                 @ restore all registers
1078     vpop    {d0-d15}                    @ restore all fp registers
1079     bx      lr                          @ return to compiled code
1080 #endif
1081
1082 /* ------------------------------ */
1083     .balign 4
1084     .global dvmCompiler_TEMPLATE_STRING_COMPARETO
1085 dvmCompiler_TEMPLATE_STRING_COMPARETO:
1086 /* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
1087     /*
1088      * String's compareTo.
1089      *
1090      * Requires r0/r1 to have been previously checked for null.  Will
1091      * return negative if this's string is < comp, 0 if they are the
1092      * same and positive if >.
1093      *
1094      * IMPORTANT NOTE:
1095      *
1096      * This code relies on hard-coded offsets for string objects, and must be
1097      * kept in sync with definitions in UtfString.h.  See asm-constants.h
1098      *
1099      * On entry:
1100      *    r0:   this object pointer
1101      *    r1:   comp object pointer
1102      *
1103      */
1104
1105     mov    r2, r0         @ this to r2, opening up r0 for return value
1106     subs   r0, r2, r1     @ Same?
1107     bxeq   lr
1108
1109     ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
1110     ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
1111     ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
1112     ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
1113     ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
1114     ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
1115
1116     /*
1117      * At this point, we have:
1118      *    value:  r2/r1
1119      *    offset: r4/r9
1120      *    count:  r7/r10
1121      * We're going to compute
1122      *    r11 <- countDiff
1123      *    r10 <- minCount
1124      */
1125      subs  r11, r7, r10
1126      movls r10, r7
1127
1128      /* Now, build pointers to the string data */
1129      add   r2, r2, r4, lsl #1
1130      add   r1, r1, r9, lsl #1
1131      /*
1132       * Note: data pointers point to previous element so we can use pre-index
1133       * mode with base writeback.
1134       */
1135      add   r2, #16-2   @ offset to contents[-1]
1136      add   r1, #16-2   @ offset to contents[-1]
1137
1138      /*
1139       * At this point we have:
1140       *   r2: *this string data
1141       *   r1: *comp string data
1142       *   r10: iteration count for comparison
1143       *   r11: value to return if the first part of the string is equal
1144       *   r0: reserved for result
1145       *   r3, r4, r7, r8, r9, r12 available for loading string data
1146       */
1147
1148     subs  r10, #2
1149     blt   do_remainder2
1150
1151       /*
1152        * Unroll the first two checks so we can quickly catch early mismatch
1153        * on long strings (but preserve incoming alignment)
1154        */
1155
1156     ldrh  r3, [r2, #2]!
1157     ldrh  r4, [r1, #2]!
1158     ldrh  r7, [r2, #2]!
1159     ldrh  r8, [r1, #2]!
1160     subs  r0, r3, r4
1161     subeqs  r0, r7, r8
1162     bxne  lr
1163     cmp   r10, #28
1164     bgt   do_memcmp16
1165     subs  r10, #3
1166     blt   do_remainder
1167
1168 loopback_triple:
1169     ldrh  r3, [r2, #2]!
1170     ldrh  r4, [r1, #2]!
1171     ldrh  r7, [r2, #2]!
1172     ldrh  r8, [r1, #2]!
1173     ldrh  r9, [r2, #2]!
1174     ldrh  r12,[r1, #2]!
1175     subs  r0, r3, r4
1176     subeqs  r0, r7, r8
1177     subeqs  r0, r9, r12
1178     bxne  lr
1179     subs  r10, #3
1180     bge   loopback_triple
1181
1182 do_remainder:
1183     adds  r10, #3
1184     beq   returnDiff
1185
1186 loopback_single:
1187     ldrh  r3, [r2, #2]!
1188     ldrh  r4, [r1, #2]!
1189     subs  r0, r3, r4
1190     bxne  lr
1191     subs  r10, #1
1192     bne     loopback_single
1193
1194 returnDiff:
1195     mov   r0, r11
1196     bx    lr
1197
1198 do_remainder2:
1199     adds  r10, #2
1200     bne   loopback_single
1201     mov   r0, r11
1202     bx    lr
1203
1204     /* Long string case */
1205 do_memcmp16:
1206     mov   r4, lr
1207     ldr   lr, .Lmemcmp16
1208     mov   r7, r11
1209     add   r0, r2, #2
1210     add   r1, r1, #2
1211     mov   r2, r10
1212     blx   lr
1213     cmp   r0, #0
1214     bxne  r4
1215     mov   r0, r7
1216     bx    r4
1217
1218 .Lmemcmp16:
1219     .word __memcmp16
1220
1221
1222 /* ------------------------------ */
1223     .balign 4
1224     .global dvmCompiler_TEMPLATE_STRING_INDEXOF
1225 dvmCompiler_TEMPLATE_STRING_INDEXOF:
1226 /* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
1227     /*
1228      * String's indexOf.
1229      *
1230      * Requires r0 to have been previously checked for null.  Will
1231      * return index of match of r1 in r0.
1232      *
1233      * IMPORTANT NOTE:
1234      *
1235      * This code relies on hard-coded offsets for string objects, and must be
1236      * kept in sync wth definitions in UtfString.h  See asm-constants.h
1237      *
1238      * On entry:
1239      *    r0:   string object pointer
1240      *    r1:   char to match
1241      *    r2:   Starting offset in string data
1242      */
1243
1244     ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
1245     ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
1246     ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
1247
1248     /*
1249      * At this point, we have:
1250      *    r0: object pointer
1251      *    r1: char to match
1252      *    r2: starting offset
1253      *    r7: offset
1254      *    r8: string length
1255      */
1256
1257      /* Build pointer to start of string data */
1258      add   r0, #16
1259      add   r0, r0, r7, lsl #1
1260
1261      /* Save a copy of starting data in r7 */
1262      mov   r7, r0
1263
1264      /* Clamp start to [0..count] */
1265      cmp   r2, #0
1266      movlt r2, #0
1267      cmp   r2, r8
1268      movgt r2, r8
1269
1270      /* Build pointer to start of data to compare and pre-bias */
1271      add   r0, r0, r2, lsl #1
1272      sub   r0, #2
1273
1274      /* Compute iteration count */
1275      sub   r8, r2
1276
1277      /*
1278       * At this point we have:
1279       *   r0: start of data to test
1280       *   r1: chat to compare
1281       *   r8: iteration count
1282       *   r7: original start of string
1283       *   r3, r4, r9, r10, r11, r12 available for loading string data
1284       */
1285
1286     subs  r8, #4
1287     blt   indexof_remainder
1288
1289 indexof_loop4:
1290     ldrh  r3, [r0, #2]!
1291     ldrh  r4, [r0, #2]!
1292     ldrh  r10, [r0, #2]!
1293     ldrh  r11, [r0, #2]!
1294     cmp   r3, r1
1295     beq   match_0
1296     cmp   r4, r1
1297     beq   match_1
1298     cmp   r10, r1
1299     beq   match_2
1300     cmp   r11, r1
1301     beq   match_3
1302     subs  r8, #4
1303     bge   indexof_loop4
1304
1305 indexof_remainder:
1306     adds    r8, #4
1307     beq     indexof_nomatch
1308
1309 indexof_loop1:
1310     ldrh  r3, [r0, #2]!
1311     cmp   r3, r1
1312     beq   match_3
1313     subs  r8, #1
1314     bne   indexof_loop1
1315
1316 indexof_nomatch:
1317     mov   r0, #-1
1318     bx    lr
1319
1320 match_0:
1321     sub   r0, #6
1322     sub   r0, r7
1323     asr   r0, r0, #1
1324     bx    lr
1325 match_1:
1326     sub   r0, #4
1327     sub   r0, r7
1328     asr   r0, r0, #1
1329     bx    lr
1330 match_2:
1331     sub   r0, #2
1332     sub   r0, r7
1333     asr   r0, r0, #1
1334     bx    lr
1335 match_3:
1336     sub   r0, r7
1337     asr   r0, r0, #1
1338     bx    lr
1339
1340
1341 /* ------------------------------ */
1342     .balign 4
1343     .global dvmCompiler_TEMPLATE_INTERPRET
1344 dvmCompiler_TEMPLATE_INTERPRET:
1345 /* File: armv5te/TEMPLATE_INTERPRET.S */
1346     /*
1347      * This handler transfers control to the interpeter without performing
1348      * any lookups.  It may be called either as part of a normal chaining
1349      * operation, or from the transition code in header.S.  We distinquish
1350      * the two cases by looking at the link register.  If called from a
1351      * translation chain, it will point to the chaining Dalvik PC + 1.
1352      * On entry:
1353      *    lr - if NULL:
1354      *        r1 - the Dalvik PC to begin interpretation.
1355      *    else
1356      *        [lr, #-1] contains Dalvik PC to begin interpretation
1357      *    rGLUE - pointer to interpState
1358      *    rFP - Dalvik frame pointer
1359      */
1360     cmp     lr, #0
1361     ldrne   r1,[lr, #-1]
1362     ldr     r2, .LinterpPunt
1363     mov     r0, r1                       @ set Dalvik PC
1364     bx      r2
1365     @ doesn't return
1366
1367 .LinterpPunt:
1368     .word   dvmJitToInterpPunt
1369
1370 /* ------------------------------ */
1371     .balign 4
1372     .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1373 dvmCompiler_TEMPLATE_MONITOR_ENTER:
1374 /* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1375     /*
1376      * Call out to the runtime to lock an object.  Because this thread
1377      * may have been suspended in THREAD_MONITOR state and the Jit's
1378      * translation cache subsequently cleared, we cannot return directly.
1379      * Instead, unconditionally transition to the interpreter to resume.
1380      *
1381      * On entry:
1382      *    r0 - self pointer
1383      *    r1 - the object (which has already been null-checked by the caller
1384      *    r4 - the Dalvik PC of the following instruction.
1385      *
1386     ldr     r2, .LdvmLockObject
1387     mov     r3, #0                       @ Record that we're not returning
1388     str     r3, [r0, #offThread_inJitCodeCache]
1389     blx     r2                           @ dvmLockObject(self, obj)
1390     @ refresh Jit's on/off status
1391     ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1392     ldr     r0, [r0]
1393     ldr     r2, .LdvmJitToInterpNoChain
1394     str     r0, [rGLUE, #offGlue_pJitProfTable]
1395     @ Bail to interpreter - no chain [note - r4 still contains rPC]
1396     bx      r2
1397
1398
1399 /* ------------------------------ */
1400     .balign 4
1401     .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1402 dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1403 /* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1404     /*
1405      * To support deadlock prediction, this version of MONITOR_ENTER
1406      * will always call the heavyweight dvmLockObject, check for an
1407      * exception and then bail out to the interpreter.
1408      *
1409      * On entry:
1410      *    r0 - self pointer
1411      *    r1 - the object (which has already been null-checked by the caller
1412      *    r4 - the Dalvik PC of the following instruction.
1413      *
1414      */
1415     ldr     r2, .LdvmLockObject
1416     mov     r3, #0                       @ Record that we're not returning
1417     str     r3, [r0, #offThread_inJitCodeCache]
1418     blx     r2             @ dvmLockObject(self, obj)
1419     @ refresh Jit's on/off status & test for exception
1420     ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1421     ldr     r1, [rGLUE, #offGlue_self]
1422     ldr     r0, [r0]
1423     ldr     r1, [r1, #offThread_exception]
1424     str     r0, [rGLUE, #offGlue_pJitProfTable]
1425     cmp     r1, #0
1426     beq     1f
1427     ldr     r2, .LhandleException
1428     sub     r0, r4, #2     @ roll dPC back to this monitor instruction
1429     bx      r2
1430 1:
1431     @ Bail to interpreter - no chain [note - r4 still contains rPC]
1432     ldr     pc, .LdvmJitToInterpNoChain
1433
1434     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1435 /* File: armv5te/footer.S */
1436 /*
1437  * ===========================================================================
1438  *  Common subroutines and data
1439  * ===========================================================================
1440  */
1441
1442     .text
1443     .align  2
1444 .LinvokeNative:
1445     @ Prep for the native call
1446     @ r1 = newFP, r0 = methodToCall
1447     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1448     mov     r2, #0
1449     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1450     str     r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache
1451     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1452     str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1453                                         @ newFp->localRefCookie=top
1454     mov     r9, r3                      @ r9<- glue->self (preserve)
1455     SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1456
1457     mov     r2, r0                      @ r2<- methodToCall
1458     mov     r0, r1                      @ r0<- newFP
1459     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1460
1461     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1462
1463     @ Refresh Jit's on/off status
1464     ldr     r3, [rGLUE, #offGlue_ppJitProfTable]
1465
1466     @ native return; r9=self, r10=newSaveArea
1467     @ equivalent to dvmPopJniLocals
1468     ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1469     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1470     ldr     r1, [r9, #offThread_exception] @ check for exception
1471     ldr     r3, [r3]    @ r1 <- pointer to Jit profile table
1472     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1473     cmp     r1, #0                      @ null?
1474     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1475     ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1476     str     r3, [rGLUE, #offGlue_pJitProfTable]  @ cache current JitProfTable
1477
1478     @ r0 = dalvikCallsitePC
1479     bne     .LhandleException           @ no, handle exception
1480
1481     str     r2, [r9, #offThread_inJitCodeCache] @ set the new mode
1482     cmp     r2, #0                      @ return chaining cell still exists?
1483     bxne    r2                          @ yes - go ahead
1484
1485     @ continue executing the next instruction through the interpreter
1486     ldr     r1, .LdvmJitToInterpNoChain @ defined in footer.S
1487     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
1488 #if defined(EXIT_STATS)
1489     mov     r0, #kCallsiteInterpreted
1490 #endif
1491     mov     pc, r1
1492
1493 /*
1494  * On entry:
1495  * r0  Faulting Dalvik PC
1496  */
1497 .LhandleException:
1498     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
1499     mov     r2, #0
1500     str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
1501     ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1502     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1503     mov     rPC, r0                 @ reload the faulting Dalvik address
1504     mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1505
1506     .align  2
1507 .LdvmAsmInstructionStart:
1508     .word   dvmAsmInstructionStart
1509 .LdvmJitToInterpNoChain:
1510     .word   dvmJitToInterpNoChain
1511 .LdvmMterpStdBail:
1512     .word   dvmMterpStdBail
1513 .LdvmMterpCommonExceptionThrown:
1514     .word   dvmMterpCommonExceptionThrown
1515 .LdvmLockObject:
1516     .word   dvmLockObject
1517 #if defined(WITH_SELF_VERIFICATION)
1518 .LdvmSelfVerificationMemOpDecode:
1519     .word   dvmSelfVerificationMemOpDecode
1520 #endif
1521 .L__aeabi_cdcmple:
1522     .word   __aeabi_cdcmple
1523 .L__aeabi_cfcmple:
1524     .word   __aeabi_cfcmple
1525
1526     .global dmvCompilerTemplateEnd
1527 dmvCompilerTemplateEnd:
1528
1529 #endif /* WITH_JIT */
1530