OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / dalvik / vm / compiler / template / out / CompilerTemplateAsm-armv5te.S
1 /*
2  * This file was generated automatically by gen-template.py for 'armv5te'.
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 /* File: armv5te/platform.S */
105 /*
106  * ===========================================================================
107  *  CPU-version-specific defines and utility
108  * ===========================================================================
109  */
110
111 /*
112  * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
113  * Jump to subroutine.
114  *
115  * May modify IP and LR.
116  */
117 .macro  LDR_PC_LR source
118     mov     lr, pc
119     ldr     pc, \source
120 .endm
121
122
123     .global dvmCompilerTemplateStart
124     .type   dvmCompilerTemplateStart, %function
125     .text
126
127 dvmCompilerTemplateStart:
128
129 /* ------------------------------ */
130     .balign 4
131     .global dvmCompiler_TEMPLATE_CMP_LONG
132 dvmCompiler_TEMPLATE_CMP_LONG:
133 /* File: armv5te/TEMPLATE_CMP_LONG.S */
134     /*
135      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
136      * register based on the results of the comparison.
137      *
138      * We load the full values with LDM, but in practice many values could
139      * be resolved by only looking at the high word.  This could be made
140      * faster or slower by splitting the LDM into a pair of LDRs.
141      *
142      * If we just wanted to set condition flags, we could do this:
143      *  subs    ip, r0, r2
144      *  sbcs    ip, r1, r3
145      *  subeqs  ip, r0, r2
146      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
147      * integer value, which we can do with 2 conditional mov/mvn instructions
148      * (set 1, set -1; if they're equal we already have 0 in ip), giving
149      * us a constant 5-cycle path plus a branch at the end to the
150      * instruction epilogue code.  The multi-compare approach below needs
151      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
152      * in the worst case (the 64-bit values are equal).
153      */
154     /* cmp-long vAA, vBB, vCC */
155     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
156     blt     .LTEMPLATE_CMP_LONG_less            @ signed compare on high part
157     bgt     .LTEMPLATE_CMP_LONG_greater
158     subs    r0, r0, r2                  @ r0<- r0 - r2
159     bxeq     lr
160     bhi     .LTEMPLATE_CMP_LONG_greater         @ unsigned compare on low part
161 .LTEMPLATE_CMP_LONG_less:
162     mvn     r0, #0                      @ r0<- -1
163     bx      lr
164 .LTEMPLATE_CMP_LONG_greater:
165     mov     r0, #1                      @ r0<- 1
166     bx      lr
167
168 /* ------------------------------ */
169     .balign 4
170     .global dvmCompiler_TEMPLATE_RETURN
171 dvmCompiler_TEMPLATE_RETURN:
172 /* File: armv5te/TEMPLATE_RETURN.S */
173     /*
174      * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
175      * If the stored value in returnAddr
176      * is non-zero, the caller is compiled by the JIT thus return to the
177      * address in the code cache following the invoke instruction. Otherwise
178      * return to the special dvmJitToInterpNoChain entry point.
179      */
180     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
181     ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
182     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
183     ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
184 #if !defined(WITH_SELF_VERIFICATION)
185     ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
186 #else
187     mov     r9, #0                      @ disable chaining
188 #endif
189     ldr     r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
190                                         @ r2<- method we're returning to
191     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
192     cmp     r2, #0                      @ break frame?
193 #if !defined(WITH_SELF_VERIFICATION)
194     beq     1f                          @ bail to interpreter
195 #else
196     blxeq   lr                          @ punt to interpreter and compare state
197 #endif
198     ldr     r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
199     mov     rFP, r10                    @ publish new FP
200     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
201     ldr     r8, [r8]                    @ r8<- suspendCount
202
203     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
204     ldr     r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
205     str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
206     add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
207     str     r0, [rGLUE, #offGlue_methodClassDex]
208     cmp     r8, #0                      @ check the suspendCount
209     movne   r9, #0                      @ clear the chaining cell address
210     str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
211     cmp     r9, #0                      @ chaining cell exists?
212     blxne   r9                          @ jump to the chaining cell
213 #if defined(WITH_JIT_TUNING)
214     mov     r0, #kCallsiteInterpreted
215 #endif
216     mov     pc, r1                      @ callsite is interpreted
217 1:
218     stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
219     ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
220     mov     r1, #0                      @ changeInterp = false
221     mov     r0, rGLUE                   @ Expecting rGLUE in r0
222     blx     r2                          @ exit the interpreter
223
224 /* ------------------------------ */
225     .balign 4
226     .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
227 dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
228 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
229     /*
230      * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
231      * into rPC then jump to dvmJitToInterpNoChain to dispatch the
232      * runtime-resolved callee.
233      */
234     @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
235     ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
236     ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
237     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
238     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
239     add     r3, r1, #1  @ Thumb addr is odd
240     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
241     sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
242     SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
243     sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
244     ldr     r8, [r8]                    @ r8<- suspendCount (int)
245     cmp     r10, r9                     @ bottom < interpStackEnd?
246     bxlo    lr                          @ return to raise stack overflow excep.
247     @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
248     ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
249     ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
250     str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
251     str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
252     ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
253
254
255     @ set up newSaveArea
256     str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
257     str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
258     str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
259     cmp     r8, #0                      @ suspendCount != 0
260     bxne    lr                          @ bail to the interpreter
261     tst     r10, #ACC_NATIVE
262 #if !defined(WITH_SELF_VERIFICATION)
263     bne     .LinvokeNative
264 #else
265     bxne    lr                          @ bail to the interpreter
266 #endif
267
268     ldr     r10, .LdvmJitToInterpTraceSelectNoChain
269     ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
270     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
271
272     @ Update "glue" values for the new method
273     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
274     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
275     mov     rFP, r1                         @ fp = newFp
276     str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
277
278     @ Start executing the callee
279 #if defined(WITH_JIT_TUNING)
280     mov     r0, #kInlineCacheMiss
281 #endif
282     mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
283
284 /* ------------------------------ */
285     .balign 4
286     .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
287 dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
288 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
289     /*
290      * For monomorphic callsite, setup the Dalvik frame and return to the
291      * Thumb code through the link register to transfer control to the callee
292      * method through a dedicated chaining cell.
293      */
294     @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
295     @ methodToCall is guaranteed to be non-native
296 .LinvokeChain:
297     ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
298     ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
299     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
300     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
301     add     r3, r1, #1  @ Thumb addr is odd
302     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
303     sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
304     SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
305     add     r12, lr, #2                 @ setup the punt-to-interp address
306     sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
307     ldr     r8, [r8]                    @ r8<- suspendCount (int)
308     cmp     r10, r9                     @ bottom < interpStackEnd?
309     bxlo    r12                         @ return to raise stack overflow excep.
310     @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
311     ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
312     str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
313     str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
314     ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
315
316
317     @ set up newSaveArea
318     str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
319     str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
320     str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
321     cmp     r8, #0                      @ suspendCount != 0
322     bxne    r12                         @ bail to the interpreter
323
324     ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
325     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
326
327     @ Update "glue" values for the new method
328     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
329     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
330     mov     rFP, r1                         @ fp = newFp
331     str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
332
333     bx      lr                              @ return to the callee-chaining cell
334
335 /* ------------------------------ */
336     .balign 4
337     .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
338 dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
339 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
340     /*
341      * For polymorphic callsite, check whether the cached class pointer matches
342      * the current one. If so setup the Dalvik frame and return to the
343      * Thumb code through the link register to transfer control to the callee
344      * method through a dedicated chaining cell.
345      *
346      * The predicted chaining cell is declared in ArmLIR.h with the
347      * following layout:
348      *
349      *  typedef struct PredictedChainingCell {
350      *      u4 branch;
351      *      const ClassObject *clazz;
352      *      const Method *method;
353      *      u4 counter;
354      *  } PredictedChainingCell;
355      *
356      * Upon returning to the callsite:
357      *    - lr  : to branch to the chaining cell
358      *    - lr+2: to punt to the interpreter
359      *    - lr+4: to fully resolve the callee and may rechain.
360      *            r3 <- class
361      *            r9 <- counter
362      */
363     @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
364     ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
365     ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
366     ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
367     ldr     r9, [rGLUE, #offGlue_icRechainCount]   @ r1 <- shared rechainCount
368     cmp     r3, r8          @ predicted class == actual class?
369 #if defined(WITH_JIT_TUNING)
370     ldr     r7, .LdvmICHitCount
371     ldreq   r10, [r7, #0]
372     add     r10, r10, #1
373     streq   r10, [r7, #0]
374 #endif
375     beq     .LinvokeChain   @ predicted chain is valid
376     ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
377     cmp     r8, #0          @ initialized class or not
378     moveq   r1, #0
379     subne   r1, r9, #1      @ count--
380     strne   r1, [rGLUE, #offGlue_icRechainCount]   @ write back to InterpState
381     add     lr, lr, #4      @ return to fully-resolve landing pad
382     /*
383      * r1 <- count
384      * r2 <- &predictedChainCell
385      * r3 <- this->class
386      * r4 <- dPC
387      * r7 <- this->class->vtable
388      */
389     bx      lr
390
391 /* ------------------------------ */
392     .balign 4
393     .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
394 dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
395 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
396     @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
397     ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
398     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
399     ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
400     add     r3, r1, #1  @ Thumb addr is odd
401     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
402     sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
403     SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
404     ldr     r8, [r8]                    @ r3<- suspendCount (int)
405     cmp     r10, r9                     @ bottom < interpStackEnd?
406     bxlo    lr                          @ return to raise stack overflow excep.
407     @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
408     str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
409     str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
410     ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
411
412
413     @ set up newSaveArea
414     str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
415     str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
416     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
417     str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
418     cmp     r8, #0                      @ suspendCount != 0
419     ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
420 #if !defined(WITH_SELF_VERIFICATION)
421     bxne    lr                          @ bail to the interpreter
422 #else
423     bx      lr                          @ bail to interpreter unconditionally
424 #endif
425
426     @ go ahead and transfer control to the native code
427     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
428     mov     r2, #0
429     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
430     str     r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
431     str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
432                                         @ newFp->localRefCookie=top
433     mov     r9, r3                      @ r9<- glue->self (preserve)
434     SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
435
436     mov     r2, r0                      @ r2<- methodToCall
437     mov     r0, r1                      @ r0<- newFP
438     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
439
440     blx     r8                          @ off to the native code
441
442     @ native return; r9=self, r10=newSaveArea
443     @ equivalent to dvmPopJniLocals
444     ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
445     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
446     ldr     r1, [r9, #offThread_exception] @ check for exception
447     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
448     cmp     r1, #0                      @ null?
449     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
450     ldr     r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
451
452     @ r0 = dalvikCallsitePC
453     bne     .LhandleException           @ no, handle exception
454
455     str     r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
456     cmp     r2, #0                      @ return chaining cell still exists?
457     bxne    r2                          @ yes - go ahead
458
459     @ continue executing the next instruction through the interpreter
460     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
461     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
462 #if defined(WITH_JIT_TUNING)
463     mov     r0, #kCallsiteInterpreted
464 #endif
465     mov     pc, r1
466
467 /* ------------------------------ */
468     .balign 4
469     .global dvmCompiler_TEMPLATE_CMPG_DOUBLE
470 dvmCompiler_TEMPLATE_CMPG_DOUBLE:
471 /* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */
472 /* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
473     /*
474      * For the JIT: incoming arguments in r0-r1, r2-r3
475      *              result in r0
476      *
477      * Compare two floating-point values.  Puts 0, 1, or -1 into the
478      * destination register based on the results of the comparison.
479      *
480      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
481      * on what value we'd like to return when one of the operands is NaN.
482      *
483      * See OP_CMPL_FLOAT for an explanation.
484      *
485      * For: cmpl-double, cmpg-double
486      */
487     /* op vAA, vBB, vCC */
488     push    {r0-r3}                     @ save operands
489     mov     r11, lr                     @ save return address
490     LDR_PC_LR ".L__aeabi_cdcmple"       @ PIC way of "bl __aeabi_cdcmple"
491     bhi     .LTEMPLATE_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
492     mvncc   r0, #0                      @ (less than) r1<- -1
493     moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
494     add     sp, #16                     @ drop unused operands
495     bx      r11
496
497     @ Test for NaN with a second comparison.  EABI forbids testing bit
498     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
499     @ make the library call.
500 .LTEMPLATE_CMPG_DOUBLE_gt_or_nan:
501     pop     {r2-r3}                     @ restore operands in reverse order
502     pop     {r0-r1}                     @ restore operands in reverse order
503     LDR_PC_LR ".L__aeabi_cdcmple"       @ r0<- Z set if eq, C clear if <
504     movcc   r0, #1                      @ (greater than) r1<- 1
505     bxcc    r11
506     mov     r0, #1                            @ r1<- 1 or -1 for NaN
507     bx      r11
508
509
510 /* ------------------------------ */
511     .balign 4
512     .global dvmCompiler_TEMPLATE_CMPL_DOUBLE
513 dvmCompiler_TEMPLATE_CMPL_DOUBLE:
514 /* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
515     /*
516      * For the JIT: incoming arguments in r0-r1, r2-r3
517      *              result in r0
518      *
519      * Compare two floating-point values.  Puts 0, 1, or -1 into the
520      * destination register based on the results of the comparison.
521      *
522      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
523      * on what value we'd like to return when one of the operands is NaN.
524      *
525      * See OP_CMPL_FLOAT for an explanation.
526      *
527      * For: cmpl-double, cmpg-double
528      */
529     /* op vAA, vBB, vCC */
530     push    {r0-r3}                     @ save operands
531     mov     r11, lr                     @ save return address
532     LDR_PC_LR ".L__aeabi_cdcmple"       @ PIC way of "bl __aeabi_cdcmple"
533     bhi     .LTEMPLATE_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
534     mvncc   r0, #0                      @ (less than) r1<- -1
535     moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
536     add     sp, #16                     @ drop unused operands
537     bx      r11
538
539     @ Test for NaN with a second comparison.  EABI forbids testing bit
540     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
541     @ make the library call.
542 .LTEMPLATE_CMPL_DOUBLE_gt_or_nan:
543     pop     {r2-r3}                     @ restore operands in reverse order
544     pop     {r0-r1}                     @ restore operands in reverse order
545     LDR_PC_LR ".L__aeabi_cdcmple"       @ r0<- Z set if eq, C clear if <
546     movcc   r0, #1                      @ (greater than) r1<- 1
547     bxcc    r11
548     mvn     r0, #0                            @ r1<- 1 or -1 for NaN
549     bx      r11
550
551 /* ------------------------------ */
552     .balign 4
553     .global dvmCompiler_TEMPLATE_CMPG_FLOAT
554 dvmCompiler_TEMPLATE_CMPG_FLOAT:
555 /* File: armv5te/TEMPLATE_CMPG_FLOAT.S */
556 /* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
557     /*
558      * For the JIT: incoming arguments in r0-r1, r2-r3
559      *              result in r0
560      *
561      * Compare two floating-point values.  Puts 0, 1, or -1 into the
562      * destination register based on the results of the comparison.
563      *
564      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
565      * on what value we'd like to return when one of the operands is NaN.
566      *
567      * The operation we're implementing is:
568      *   if (x == y)
569      *     return 0;
570      *   else if (x < y)
571      *     return -1;
572      *   else if (x > y)
573      *     return 1;
574      *   else
575      *     return {-1,1};  // one or both operands was NaN
576      *
577      * The straightforward implementation requires 3 calls to functions
578      * that return a result in r0.  We can do it with two calls if our
579      * EABI library supports __aeabi_cfcmple (only one if we want to check
580      * for NaN directly):
581      *   check x <= y
582      *     if <, return -1
583      *     if ==, return 0
584      *   check y <= x
585      *     if <, return 1
586      *   return {-1,1}
587      *
588      * for: cmpl-float, cmpg-float
589      */
590     /* op vAA, vBB, vCC */
591     mov     r9, r0                      @ Save copies - we may need to redo
592     mov     r10, r1
593     mov     r11, lr                     @ save return address
594     LDR_PC_LR ".L__aeabi_cfcmple"       @ cmp <=: C clear if <, Z set if eq
595     bhi     .LTEMPLATE_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
596     mvncc   r0, #0                      @ (less than) r0<- -1
597     moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
598     bx      r11
599     @ Test for NaN with a second comparison.  EABI forbids testing bit
600     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
601     @ make the library call.
602 .LTEMPLATE_CMPG_FLOAT_gt_or_nan:
603     mov     r0, r10                     @ restore in reverse order
604     mov     r1, r9
605     LDR_PC_LR ".L__aeabi_cfcmple"       @ r0<- Z set if eq, C clear if <
606     movcc   r0, #1                      @ (greater than) r1<- 1
607     bxcc    r11
608     mov     r0, #1                            @ r1<- 1 or -1 for NaN
609     bx      r11
610
611
612 /* ------------------------------ */
613     .balign 4
614     .global dvmCompiler_TEMPLATE_CMPL_FLOAT
615 dvmCompiler_TEMPLATE_CMPL_FLOAT:
616 /* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
617     /*
618      * For the JIT: incoming arguments in r0-r1, r2-r3
619      *              result in r0
620      *
621      * Compare two floating-point values.  Puts 0, 1, or -1 into the
622      * destination register based on the results of the comparison.
623      *
624      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
625      * on what value we'd like to return when one of the operands is NaN.
626      *
627      * The operation we're implementing is:
628      *   if (x == y)
629      *     return 0;
630      *   else if (x < y)
631      *     return -1;
632      *   else if (x > y)
633      *     return 1;
634      *   else
635      *     return {-1,1};  // one or both operands was NaN
636      *
637      * The straightforward implementation requires 3 calls to functions
638      * that return a result in r0.  We can do it with two calls if our
639      * EABI library supports __aeabi_cfcmple (only one if we want to check
640      * for NaN directly):
641      *   check x <= y
642      *     if <, return -1
643      *     if ==, return 0
644      *   check y <= x
645      *     if <, return 1
646      *   return {-1,1}
647      *
648      * for: cmpl-float, cmpg-float
649      */
650     /* op vAA, vBB, vCC */
651     mov     r9, r0                      @ Save copies - we may need to redo
652     mov     r10, r1
653     mov     r11, lr                     @ save return address
654     LDR_PC_LR ".L__aeabi_cfcmple"       @ cmp <=: C clear if <, Z set if eq
655     bhi     .LTEMPLATE_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
656     mvncc   r0, #0                      @ (less than) r0<- -1
657     moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
658     bx      r11
659     @ Test for NaN with a second comparison.  EABI forbids testing bit
660     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
661     @ make the library call.
662 .LTEMPLATE_CMPL_FLOAT_gt_or_nan:
663     mov     r0, r10                     @ restore in reverse order
664     mov     r1, r9
665     LDR_PC_LR ".L__aeabi_cfcmple"       @ r0<- Z set if eq, C clear if <
666     movcc   r0, #1                      @ (greater than) r1<- 1
667     bxcc    r11
668     mvn     r0, #0                            @ r1<- 1 or -1 for NaN
669     bx      r11
670
671 /* ------------------------------ */
672     .balign 4
673     .global dvmCompiler_TEMPLATE_MUL_LONG
674 dvmCompiler_TEMPLATE_MUL_LONG:
675 /* File: armv5te/TEMPLATE_MUL_LONG.S */
676     /*
677      * Signed 64-bit integer multiply.
678      *
679      * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
680      *
681      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
682      *        WX
683      *      x YZ
684      *  --------
685      *     ZW ZX
686      *  YW YX
687      *
688      * The low word of the result holds ZX, the high word holds
689      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
690      * it doesn't fit in the low 64 bits.
691      *
692      * Unlike most ARM math operations, multiply instructions have
693      * restrictions on using the same register more than once (Rd and Rm
694      * cannot be the same).
695      */
696     /* mul-long vAA, vBB, vCC */
697     mul     ip, r2, r1                  @  ip<- ZxW
698     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
699     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
700     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
701     mov     r0,r9
702     mov     r1,r10
703     bx      lr
704
705 /* ------------------------------ */
706     .balign 4
707     .global dvmCompiler_TEMPLATE_SHL_LONG
708 dvmCompiler_TEMPLATE_SHL_LONG:
709 /* File: armv5te/TEMPLATE_SHL_LONG.S */
710     /*
711      * Long integer shift.  This is different from the generic 32/64-bit
712      * binary operations because vAA/vBB are 64-bit but vCC (the shift
713      * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
714      * 6 bits.
715      */
716     /* shl-long vAA, vBB, vCC */
717     and     r2, r2, #63                 @ r2<- r2 & 0x3f
718     mov     r1, r1, asl r2              @  r1<- r1 << r2
719     rsb     r3, r2, #32                 @  r3<- 32 - r2
720     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
721     subs    ip, r2, #32                 @  ip<- r2 - 32
722     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
723     mov     r0, r0, asl r2              @  r0<- r0 << r2
724     bx      lr
725
726 /* ------------------------------ */
727     .balign 4
728     .global dvmCompiler_TEMPLATE_SHR_LONG
729 dvmCompiler_TEMPLATE_SHR_LONG:
730 /* File: armv5te/TEMPLATE_SHR_LONG.S */
731     /*
732      * Long integer shift.  This is different from the generic 32/64-bit
733      * binary operations because vAA/vBB are 64-bit but vCC (the shift
734      * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
735      * 6 bits.
736      */
737     /* shr-long vAA, vBB, vCC */
738     and     r2, r2, #63                 @ r0<- r0 & 0x3f
739     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
740     rsb     r3, r2, #32                 @  r3<- 32 - r2
741     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
742     subs    ip, r2, #32                 @  ip<- r2 - 32
743     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
744     mov     r1, r1, asr r2              @  r1<- r1 >> r2
745     bx      lr
746
747 /* ------------------------------ */
748     .balign 4
749     .global dvmCompiler_TEMPLATE_USHR_LONG
750 dvmCompiler_TEMPLATE_USHR_LONG:
751 /* File: armv5te/TEMPLATE_USHR_LONG.S */
752     /*
753      * Long integer shift.  This is different from the generic 32/64-bit
754      * binary operations because vAA/vBB are 64-bit but vCC (the shift
755      * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
756      * 6 bits.
757      */
758     /* ushr-long vAA, vBB, vCC */
759     and     r2, r2, #63                 @ r0<- r0 & 0x3f
760     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
761     rsb     r3, r2, #32                 @  r3<- 32 - r2
762     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
763     subs    ip, r2, #32                 @  ip<- r2 - 32
764     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
765     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
766     bx      lr
767
768 /* ------------------------------ */
769     .balign 4
770     .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
771 dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
772 /* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
773     /*
774      * Throw an exception from JIT'ed code.
775      * On entry:
776      *    r0    Dalvik PC that raises the exception
777      */
778     b       .LhandleException
779
780 /* ------------------------------ */
781     .balign 4
782     .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
783 dvmCompiler_TEMPLATE_MEM_OP_DECODE:
784 /* File: armv5te/TEMPLATE_MEM_OP_DECODE.S */
785 #if defined(WITH_SELF_VERIFICATION)
786     /*
787      * This handler encapsulates heap memory ops for selfVerification mode.
788      *
789      * The call to the handler is inserted prior to a heap memory operation.
790      * This handler then calls a function to decode the memory op, and process
791      * it accordingly. Afterwards, the handler changes the return address to
792      * skip the memory op so it never gets executed.
793      */
794     push    {r0-r12,lr}                 @ save out all registers
795     mov     r0, lr                      @ arg0 <- link register
796     mov     r1, sp                      @ arg1 <- stack pointer
797     ldr     r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
798     blx     r2                          @ decode and handle the mem op
799     pop     {r0-r12,lr}                 @ restore all registers
800     bx      lr                          @ return to compiled code
801 #endif
802
803 /* ------------------------------ */
804     .balign 4
805     .global dvmCompiler_TEMPLATE_STRING_COMPARETO
806 dvmCompiler_TEMPLATE_STRING_COMPARETO:
807 /* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
808     /*
809      * String's compareTo.
810      *
811      * Requires r0/r1 to have been previously checked for null.  Will
812      * return negative if this's string is < comp, 0 if they are the
813      * same and positive if >.
814      *
815      * IMPORTANT NOTE:
816      *
817      * This code relies on hard-coded offsets for string objects, and must be
818      * kept in sync with definitions in UtfString.h.  See asm-constants.h
819      *
820      * On entry:
821      *    r0:   this object pointer
822      *    r1:   comp object pointer
823      *
824      */
825
826     mov    r2, r0         @ this to r2, opening up r0 for return value
827     subs   r0, r2, r1     @ Same?
828     bxeq   lr
829
830     ldr    r4, [r2, #STRING_FIELDOFF_OFFSET]
831     ldr    r9, [r1, #STRING_FIELDOFF_OFFSET]
832     ldr    r7, [r2, #STRING_FIELDOFF_COUNT]
833     ldr    r10, [r1, #STRING_FIELDOFF_COUNT]
834     ldr    r2, [r2, #STRING_FIELDOFF_VALUE]
835     ldr    r1, [r1, #STRING_FIELDOFF_VALUE]
836
837     /*
838      * At this point, we have:
839      *    value:  r2/r1
840      *    offset: r4/r9
841      *    count:  r7/r10
842      * We're going to compute
843      *    r11 <- countDiff
844      *    r10 <- minCount
845      */
846      subs  r11, r7, r10
847      movls r10, r7
848
849      /* Now, build pointers to the string data */
850      add   r2, r2, r4, lsl #1
851      add   r1, r1, r9, lsl #1
852      /*
853       * Note: data pointers point to previous element so we can use pre-index
854       * mode with base writeback.
855       */
856      add   r2, #16-2   @ offset to contents[-1]
857      add   r1, #16-2   @ offset to contents[-1]
858
859      /*
860       * At this point we have:
861       *   r2: *this string data
862       *   r1: *comp string data
863       *   r10: iteration count for comparison
864       *   r11: value to return if the first part of the string is equal
865       *   r0: reserved for result
866       *   r3, r4, r7, r8, r9, r12 available for loading string data
867       */
868
869     subs  r10, #2
870     blt   do_remainder2
871
872       /*
873        * Unroll the first two checks so we can quickly catch early mismatch
874        * on long strings (but preserve incoming alignment)
875        */
876
877     ldrh  r3, [r2, #2]!
878     ldrh  r4, [r1, #2]!
879     ldrh  r7, [r2, #2]!
880     ldrh  r8, [r1, #2]!
881     subs  r0, r3, r4
882     subeqs  r0, r7, r8
883     bxne  lr
884     cmp   r10, #28
885     bgt   do_memcmp16
886     subs  r10, #3
887     blt   do_remainder
888
889 loopback_triple:
890     ldrh  r3, [r2, #2]!
891     ldrh  r4, [r1, #2]!
892     ldrh  r7, [r2, #2]!
893     ldrh  r8, [r1, #2]!
894     ldrh  r9, [r2, #2]!
895     ldrh  r12,[r1, #2]!
896     subs  r0, r3, r4
897     subeqs  r0, r7, r8
898     subeqs  r0, r9, r12
899     bxne  lr
900     subs  r10, #3
901     bge   loopback_triple
902
903 do_remainder:
904     adds  r10, #3
905     beq   returnDiff
906
907 loopback_single:
908     ldrh  r3, [r2, #2]!
909     ldrh  r4, [r1, #2]!
910     subs  r0, r3, r4
911     bxne  lr
912     subs  r10, #1
913     bne     loopback_single
914
915 returnDiff:
916     mov   r0, r11
917     bx    lr
918
919 do_remainder2:
920     adds  r10, #2
921     bne   loopback_single
922     mov   r0, r11
923     bx    lr
924
925     /* Long string case */
926 do_memcmp16:
927     mov   r4, lr
928     ldr   lr, .Lmemcmp16
929     mov   r7, r11
930     add   r0, r2, #2
931     add   r1, r1, #2
932     mov   r2, r10
933     blx   lr
934     cmp   r0, #0
935     bxne  r4
936     mov   r0, r7
937     bx    r4
938
939 .Lmemcmp16:
940     .word __memcmp16
941
942 /* ------------------------------ */
943     .balign 4
944     .global dvmCompiler_TEMPLATE_STRING_INDEXOF
945 dvmCompiler_TEMPLATE_STRING_INDEXOF:
946 /* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
947     /*
948      * String's indexOf.
949      *
950      * Requires r0 to have been previously checked for null.  Will
951      * return index of match of r1 in r0.
952      *
953      * IMPORTANT NOTE:
954      *
955      * This code relies on hard-coded offsets for string objects, and must be
956      * kept in sync wth definitions in UtfString.h  See asm-constants.h
957      *
958      * On entry:
959      *    r0:   string object pointer
960      *    r1:   char to match
961      *    r2:   Starting offset in string data
962      */
963
964     ldr    r7, [r0, #STRING_FIELDOFF_OFFSET]
965     ldr    r8, [r0, #STRING_FIELDOFF_COUNT]
966     ldr    r0, [r0, #STRING_FIELDOFF_VALUE]
967
968     /*
969      * At this point, we have:
970      *    r0: object pointer
971      *    r1: char to match
972      *    r2: starting offset
973      *    r7: offset
974      *    r8: string length
975      */
976
977      /* Build pointer to start of string data */
978      add   r0, #16
979      add   r0, r0, r7, lsl #1
980
981      /* Save a copy of starting data in r7 */
982      mov   r7, r0
983
984      /* Clamp start to [0..count] */
985      cmp   r2, #0
986      movlt r2, #0
987      cmp   r2, r8
988      movgt r2, r8
989
990      /* Build pointer to start of data to compare and pre-bias */
991      add   r0, r0, r2, lsl #1
992      sub   r0, #2
993
994      /* Compute iteration count */
995      sub   r8, r2
996
997      /*
998       * At this point we have:
999       *   r0: start of data to test
1000       *   r1: chat to compare
1001       *   r8: iteration count
1002       *   r7: original start of string
1003       *   r3, r4, r9, r10, r11, r12 available for loading string data
1004       */
1005
1006     subs  r8, #4
1007     blt   indexof_remainder
1008
1009 indexof_loop4:
1010     ldrh  r3, [r0, #2]!
1011     ldrh  r4, [r0, #2]!
1012     ldrh  r10, [r0, #2]!
1013     ldrh  r11, [r0, #2]!
1014     cmp   r3, r1
1015     beq   match_0
1016     cmp   r4, r1
1017     beq   match_1
1018     cmp   r10, r1
1019     beq   match_2
1020     cmp   r11, r1
1021     beq   match_3
1022     subs  r8, #4
1023     bge   indexof_loop4
1024
1025 indexof_remainder:
1026     adds    r8, #4
1027     beq     indexof_nomatch
1028
1029 indexof_loop1:
1030     ldrh  r3, [r0, #2]!
1031     cmp   r3, r1
1032     beq   match_3
1033     subs  r8, #1
1034     bne   indexof_loop1
1035
1036 indexof_nomatch:
1037     mov   r0, #-1
1038     bx    lr
1039
1040 match_0:
1041     sub   r0, #6
1042     sub   r0, r7
1043     asr   r0, r0, #1
1044     bx    lr
1045 match_1:
1046     sub   r0, #4
1047     sub   r0, r7
1048     asr   r0, r0, #1
1049     bx    lr
1050 match_2:
1051     sub   r0, #2
1052     sub   r0, r7
1053     asr   r0, r0, #1
1054     bx    lr
1055 match_3:
1056     sub   r0, r7
1057     asr   r0, r0, #1
1058     bx    lr
1059
1060 /* ------------------------------ */
1061     .balign 4
1062     .global dvmCompiler_TEMPLATE_INTERPRET
1063 dvmCompiler_TEMPLATE_INTERPRET:
1064 /* File: armv5te/TEMPLATE_INTERPRET.S */
1065     /*
1066      * This handler transfers control to the interpeter without performing
1067      * any lookups.  It may be called either as part of a normal chaining
1068      * operation, or from the transition code in header.S.  We distinquish
1069      * the two cases by looking at the link register.  If called from a
1070      * translation chain, it will point to the chaining Dalvik PC -3.
1071      * On entry:
1072      *    lr - if NULL:
1073      *        r1 - the Dalvik PC to begin interpretation.
1074      *    else
1075      *        [lr, #3] contains Dalvik PC to begin interpretation
1076      *    rGLUE - pointer to interpState
1077      *    rFP - Dalvik frame pointer
1078      */
1079     cmp     lr, #0
1080     ldrne   r1,[lr, #3]
1081     ldr     r2, .LinterpPunt
1082     mov     r0, r1                       @ set Dalvik PC
1083     bx      r2
1084     @ doesn't return
1085
1086 .LinterpPunt:
1087     .word   dvmJitToInterpPunt
1088
1089 /* ------------------------------ */
1090     .balign 4
1091     .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1092 dvmCompiler_TEMPLATE_MONITOR_ENTER:
1093 /* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1094     /*
1095      * Call out to the runtime to lock an object.  Because this thread
1096      * may have been suspended in THREAD_MONITOR state and the Jit's
1097      * translation cache subsequently cleared, we cannot return directly.
1098      * Instead, unconditionally transition to the interpreter to resume.
1099      *
1100      * On entry:
1101      *    r0 - self pointer
1102      *    r1 - the object (which has already been null-checked by the caller
1103      *    r4 - the Dalvik PC of the following instruction.
1104      */
1105     ldr     r2, .LdvmLockObject
1106     mov     r3, #0                       @ Record that we're not returning
1107     str     r3, [r0, #offThread_inJitCodeCache]
1108     blx     r2                           @ dvmLockObject(self, obj)
1109     @ refresh Jit's on/off status
1110     ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1111     ldr     r0, [r0]
1112     ldr     r2, .LdvmJitToInterpNoChain
1113     str     r0, [rGLUE, #offGlue_pJitProfTable]
1114     @ Bail to interpreter - no chain [note - r4 still contains rPC]
1115 #if defined(WITH_JIT_TUNING)
1116     mov     r0, #kHeavyweightMonitor
1117 #endif
1118     bx      r2
1119
1120 /* ------------------------------ */
1121     .balign 4
1122     .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1123 dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1124 /* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1125     /*
1126      * To support deadlock prediction, this version of MONITOR_ENTER
1127      * will always call the heavyweight dvmLockObject, check for an
1128      * exception and then bail out to the interpreter.
1129      *
1130      * On entry:
1131      *    r0 - self pointer
1132      *    r1 - the object (which has already been null-checked by the caller
1133      *    r4 - the Dalvik PC of the following instruction.
1134      *
1135      */
1136     ldr     r2, .LdvmLockObject
1137     mov     r3, #0                       @ Record that we're not returning
1138     str     r3, [r0, #offThread_inJitCodeCache]
1139     blx     r2             @ dvmLockObject(self, obj)
1140     @ refresh Jit's on/off status & test for exception
1141     ldr     r0, [rGLUE, #offGlue_ppJitProfTable]
1142     ldr     r1, [rGLUE, #offGlue_self]
1143     ldr     r0, [r0]
1144     ldr     r1, [r1, #offThread_exception]
1145     str     r0, [rGLUE, #offGlue_pJitProfTable]
1146     cmp     r1, #0
1147     beq     1f
1148     ldr     r2, .LhandleException
1149     sub     r0, r4, #2     @ roll dPC back to this monitor instruction
1150     bx      r2
1151 1:
1152     @ Bail to interpreter - no chain [note - r4 still contains rPC]
1153 #if defined(WITH_JIT_TUNING)
1154     mov     r0, #kHeavyweightMonitor
1155 #endif
1156     ldr     pc, .LdvmJitToInterpNoChain
1157
1158     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1159 /* File: armv5te/footer.S */
1160 /*
1161  * ===========================================================================
1162  *  Common subroutines and data
1163  * ===========================================================================
1164  */
1165
1166     .text
1167     .align  2
1168 .LinvokeNative:
1169     @ Prep for the native call
1170     @ r1 = newFP, r0 = methodToCall
1171     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
1172     mov     r2, #0
1173     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1174     str     r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache
1175     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
1176     str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1177                                         @ newFp->localRefCookie=top
1178     mov     r9, r3                      @ r9<- glue->self (preserve)
1179     SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
1180
1181     mov     r2, r0                      @ r2<- methodToCall
1182     mov     r0, r1                      @ r0<- newFP
1183     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
1184
1185     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1186
1187     @ Refresh Jit's on/off status
1188     ldr     r3, [rGLUE, #offGlue_ppJitProfTable]
1189
1190     @ native return; r9=self, r10=newSaveArea
1191     @ equivalent to dvmPopJniLocals
1192     ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1193     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1194     ldr     r1, [r9, #offThread_exception] @ check for exception
1195     ldr     r3, [r3]    @ r1 <- pointer to Jit profile table
1196     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
1197     cmp     r1, #0                      @ null?
1198     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1199     ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1200     str     r3, [rGLUE, #offGlue_pJitProfTable]  @ cache current JitProfTable
1201
1202     @ r0 = dalvikCallsitePC
1203     bne     .LhandleException           @ no, handle exception
1204
1205     str     r2, [r9, #offThread_inJitCodeCache] @ set the new mode
1206     cmp     r2, #0                      @ return chaining cell still exists?
1207     bxne    r2                          @ yes - go ahead
1208
1209     @ continue executing the next instruction through the interpreter
1210     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1211     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
1212 #if defined(WITH_JIT_TUNING)
1213     mov     r0, #kCallsiteInterpreted
1214 #endif
1215     mov     pc, r1
1216
1217 /*
1218  * On entry:
1219  * r0  Faulting Dalvik PC
1220  */
1221 .LhandleException:
1222 #if defined(WITH_SELF_VERIFICATION)
1223     ldr     pc, .LdeadFood @ should not see this under self-verification mode
1224 .LdeadFood:
1225     .word   0xdeadf00d
1226 #endif
1227     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
1228     mov     r2, #0
1229     str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
1230     ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1231     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
1232     mov     rPC, r0                 @ reload the faulting Dalvik address
1233     mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
1234
1235     .align  2
1236 .LdvmAsmInstructionStart:
1237     .word   dvmAsmInstructionStart
1238 .LdvmJitToInterpNoChainNoProfile:
1239     .word   dvmJitToInterpNoChainNoProfile
1240 .LdvmJitToInterpTraceSelectNoChain:
1241     .word   dvmJitToInterpTraceSelectNoChain
1242 .LdvmJitToInterpNoChain:
1243     .word   dvmJitToInterpNoChain
1244 .LdvmMterpStdBail:
1245     .word   dvmMterpStdBail
1246 .LdvmMterpCommonExceptionThrown:
1247     .word   dvmMterpCommonExceptionThrown
1248 .LdvmLockObject:
1249     .word   dvmLockObject
1250 #if defined(WITH_JIT_TUNING)
1251 .LdvmICHitCount:
1252     .word   gDvmICHitCount
1253 #endif
1254 #if defined(WITH_SELF_VERIFICATION)
1255 .LdvmSelfVerificationMemOpDecode:
1256     .word   dvmSelfVerificationMemOpDecode
1257 #endif
1258 .L__aeabi_cdcmple:
1259     .word   __aeabi_cdcmple
1260 .L__aeabi_cfcmple:
1261     .word   __aeabi_cfcmple
1262
1263     .global dmvCompilerTemplateEnd
1264 dmvCompilerTemplateEnd:
1265
1266 #endif /* WITH_JIT */
1267