OSDN Git Service

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