2 * This file was generated automatically by gen-template.py for 'armv7-a-neon'.
7 /* File: armv5te/header.S */
9 * Copyright (C) 2008 The Android Open Source Project
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
15 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 * ARMv5 definitions and declarations.
31 ARM EABI general notes:
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
43 r0 holds returns of <= 4 bytes
44 r0-r1 hold returns of 8 bytes, low word in r0
46 Callee must save/restore r4+ (except r12) if it modifies them.
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
52 VFP: single-precision results in s0, double-precision results in d0.
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.
61 The following registers have fixed assignments:
64 r5 rFP interpreted frame pointer, used for accessing locals and args
65 r6 rSELF thread pointer
67 The following registers have fixed assignments in mterp but are scratch
68 registers in compiled code
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
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.
80 /* single-purpose registers, given names for clarity */
88 * Given a frame pointer, find the stack save area.
90 * In C this is "((StackSaveArea*)(_fp) -1)".
92 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
93 sub _reg, _fpreg, #sizeofStackSaveArea
96 str rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
99 * This is a #include, not a %include, because we want the C pre-processor
100 * to expand the macros into assembler assignment statements.
102 #include "../../../mterp/common/asm-constants.h"
104 /* File: armv5te-vfp/platform.S */
106 * ===========================================================================
107 * CPU-version-specific defines and utility
108 * ===========================================================================
112 .global dvmCompilerTemplateStart
113 .type dvmCompilerTemplateStart, %function
114 .section .data.rel.ro
116 dvmCompilerTemplateStart:
118 /* ------------------------------ */
120 .global dvmCompiler_TEMPLATE_CMP_LONG
121 dvmCompiler_TEMPLATE_CMP_LONG:
122 /* File: armv5te/TEMPLATE_CMP_LONG.S */
124 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
125 * register based on the results of the comparison.
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.
131 * If we just wanted to set condition flags, we could do this:
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).
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
149 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part
150 .LTEMPLATE_CMP_LONG_less:
153 .LTEMPLATE_CMP_LONG_greater:
157 /* ------------------------------ */
159 .global dvmCompiler_TEMPLATE_RETURN
160 dvmCompiler_TEMPLATE_RETURN:
161 /* File: armv5te/TEMPLATE_RETURN.S */
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.
169 #if defined(TEMPLATE_INLINE_PROFILING)
170 stmfd sp!, {r0-r2,lr} @ preserve live registers
173 ldr ip, .LdvmFastMethodTraceExit
175 ldmfd sp!, {r0-r2,lr} @ restore live registers
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 #if !defined(WITH_SELF_VERIFICATION)
182 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
184 mov r9, #0 @ disable chaining
186 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
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
192 blxeq lr @ punt to interpreter and compare state
194 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
195 mov rFP, r10 @ publish new FP
196 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz
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
211 mov pc, r1 @ callsite is interpreted
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
220 /* ------------------------------ */
222 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
223 dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
224 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
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.
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
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
257 #if !defined(WITH_SELF_VERIFICATION)
260 bxne lr @ bail to the interpreter
263 ldr r10, .LdvmJitToInterpTraceSelectNoChain
264 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
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
274 @ r0=methodToCall, r1=rSELF
275 ldr ip, .LdvmFastMethodTraceEnter
277 ldmfd sp!, {r0-r3} @ restore r0-r3
280 @ Start executing the callee
281 #if defined(WITH_JIT_TUNING)
282 mov r0, #kInlineCacheMiss
284 bx r10 @ dvmJitToInterpTraceSelectNoChain
286 /* ------------------------------ */
288 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
289 dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
290 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
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.
296 @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
297 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
298 @ methodToCall is guaranteed to be non-native
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)]
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
322 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
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
332 @ r0=methodToCall, r1=rSELF
333 ldr ip, .LdvmFastMethodTraceEnter
335 ldmfd sp!, {r0-r2,lr} @ restore registers
338 bx lr @ return to the callee-chaining cell
340 /* ------------------------------ */
342 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
343 dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
344 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
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.
351 * The predicted chaining cell is declared in ArmLIR.h with the
354 * typedef struct PredictedChainingCell {
356 * const ClassObject *clazz;
357 * const Method *method;
359 * } PredictedChainingCell;
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.
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 */
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
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
398 * r2 <- &predictedChainCell
401 * r7 <- this->class->vtable
405 /* ------------------------------ */
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)]
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
433 bx lr @ bail to interpreter unconditionally
436 @ go ahead and transfer control to the native code
437 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
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
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
455 @ r0=JNIMethod, r1=rSELF
456 ldr ip, .LdvmFastMethodTraceEnter
458 ldmfd sp!, {r0-r3} @ restore r0-r3
461 blx r8 @ off to the native code
463 #if defined(TEMPLATE_INLINE_PROFILING)
464 ldmfd sp!, {r0-r1} @ restore r2 and r6
465 @ r0=JNIMethod, r1=rSELF
466 ldr ip, .LdvmFastNativeMethodTraceExit
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
476 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
477 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
479 @ r0 = dalvikCallsitePC
480 bne .LhandleException @ no, handle exception
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
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
494 /* ------------------------------ */
496 .global dvmCompiler_TEMPLATE_MUL_LONG
497 dvmCompiler_TEMPLATE_MUL_LONG:
498 /* File: armv5te/TEMPLATE_MUL_LONG.S */
500 * Signed 64-bit integer multiply.
502 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
504 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
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.
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).
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 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
528 /* ------------------------------ */
530 .global dvmCompiler_TEMPLATE_SHL_LONG
531 dvmCompiler_TEMPLATE_SHL_LONG:
532 /* File: armv5te/TEMPLATE_SHL_LONG.S */
534 * Long integer shift. This is different from the generic 32/64-bit
535 * binary operations because vAA/vBB are 64-bit but vCC (the shift
536 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
539 /* shl-long vAA, vBB, vCC */
540 and r2, r2, #63 @ r2<- r2 & 0x3f
541 mov r1, r1, asl r2 @ r1<- r1 << r2
542 rsb r3, r2, #32 @ r3<- 32 - r2
543 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
544 subs ip, r2, #32 @ ip<- r2 - 32
545 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
546 mov r0, r0, asl r2 @ r0<- r0 << r2
549 /* ------------------------------ */
551 .global dvmCompiler_TEMPLATE_SHR_LONG
552 dvmCompiler_TEMPLATE_SHR_LONG:
553 /* File: armv5te/TEMPLATE_SHR_LONG.S */
555 * Long integer shift. This is different from the generic 32/64-bit
556 * binary operations because vAA/vBB are 64-bit but vCC (the shift
557 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
560 /* shr-long vAA, vBB, vCC */
561 and r2, r2, #63 @ r0<- r0 & 0x3f
562 mov r0, r0, lsr r2 @ r0<- r2 >> r2
563 rsb r3, r2, #32 @ r3<- 32 - r2
564 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
565 subs ip, r2, #32 @ ip<- r2 - 32
566 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
567 mov r1, r1, asr r2 @ r1<- r1 >> r2
570 /* ------------------------------ */
572 .global dvmCompiler_TEMPLATE_USHR_LONG
573 dvmCompiler_TEMPLATE_USHR_LONG:
574 /* File: armv5te/TEMPLATE_USHR_LONG.S */
576 * Long integer shift. This is different from the generic 32/64-bit
577 * binary operations because vAA/vBB are 64-bit but vCC (the shift
578 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
581 /* ushr-long vAA, vBB, vCC */
582 and r2, r2, #63 @ r0<- r0 & 0x3f
583 mov r0, r0, lsr r2 @ r0<- r2 >> r2
584 rsb r3, r2, #32 @ r3<- 32 - r2
585 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
586 subs ip, r2, #32 @ ip<- r2 - 32
587 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
588 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
591 /* ------------------------------ */
593 .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
594 dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
595 /* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
596 /* File: armv5te-vfp/fbinop.S */
598 * Generic 32-bit floating point operation. Provide an "instr" line that
599 * specifies an instruction that performs s2 = s0 op s1.
602 * r0 = target dalvik register address
613 /* ------------------------------ */
615 .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
616 dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
617 /* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
618 /* File: armv5te-vfp/fbinop.S */
620 * Generic 32-bit floating point operation. Provide an "instr" line that
621 * specifies an instruction that performs s2 = s0 op s1.
624 * r0 = target dalvik register address
635 /* ------------------------------ */
637 .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
638 dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
639 /* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
640 /* File: armv5te-vfp/fbinop.S */
642 * Generic 32-bit floating point operation. Provide an "instr" line that
643 * specifies an instruction that performs s2 = s0 op s1.
646 * r0 = target dalvik register address
657 /* ------------------------------ */
659 .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
660 dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
661 /* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
662 /* File: armv5te-vfp/fbinop.S */
664 * Generic 32-bit floating point operation. Provide an "instr" line that
665 * specifies an instruction that performs s2 = s0 op s1.
668 * r0 = target dalvik register address
679 /* ------------------------------ */
681 .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
682 dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
683 /* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
684 /* File: armv5te-vfp/fbinopWide.S */
686 * Generic 64-bit floating point operation. Provide an "instr" line that
687 * specifies an instruction that performs s2 = s0 op s1.
690 * r0 = target dalvik register address
701 /* ------------------------------ */
703 .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
704 dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
705 /* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
706 /* File: armv5te-vfp/fbinopWide.S */
708 * Generic 64-bit floating point operation. Provide an "instr" line that
709 * specifies an instruction that performs s2 = s0 op s1.
712 * r0 = target dalvik register address
723 /* ------------------------------ */
725 .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
726 dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
727 /* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
728 /* File: armv5te-vfp/fbinopWide.S */
730 * Generic 64-bit floating point operation. Provide an "instr" line that
731 * specifies an instruction that performs s2 = s0 op s1.
734 * r0 = target dalvik register address
745 /* ------------------------------ */
747 .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
748 dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
749 /* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
750 /* File: armv5te-vfp/fbinopWide.S */
752 * Generic 64-bit floating point operation. Provide an "instr" line that
753 * specifies an instruction that performs s2 = s0 op s1.
756 * r0 = target dalvik register address
767 /* ------------------------------ */
769 .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
770 dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
771 /* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
772 /* File: armv5te-vfp/funopNarrower.S */
774 * Generic 64bit-to-32bit floating point unary operation. Provide an
775 * "instr" line that specifies an instruction that performs "s0 = op d0".
777 * For: double-to-int, double-to-float
780 * r0 = target dalvik register address
781 * r1 = src dalvik register address
784 fldd d0, [r1] @ d0<- vB
785 fcvtsd s0, d0 @ s0<- op d0
786 fsts s0, [r0] @ vA<- s0
790 /* ------------------------------ */
792 .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
793 dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
794 /* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
795 /* File: armv5te-vfp/funopNarrower.S */
797 * Generic 64bit-to-32bit floating point unary operation. Provide an
798 * "instr" line that specifies an instruction that performs "s0 = op d0".
800 * For: double-to-int, double-to-float
803 * r0 = target dalvik register address
804 * r1 = src dalvik register address
807 fldd d0, [r1] @ d0<- vB
808 ftosizd s0, d0 @ s0<- op d0
809 fsts s0, [r0] @ vA<- s0
813 /* ------------------------------ */
815 .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
816 dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
817 /* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
818 /* File: armv5te-vfp/funopWider.S */
820 * Generic 32bit-to-64bit floating point unary operation. Provide an
821 * "instr" line that specifies an instruction that performs "d0 = op s0".
823 * For: int-to-double, float-to-double
826 * r0 = target dalvik register address
827 * r1 = src dalvik register address
830 flds s0, [r1] @ s0<- vB
831 fcvtds d0, s0 @ d0<- op s0
832 fstd d0, [r0] @ vA<- d0
836 /* ------------------------------ */
838 .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
839 dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
840 /* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
841 /* File: armv5te-vfp/funop.S */
843 * Generic 32bit-to-32bit floating point unary operation. Provide an
844 * "instr" line that specifies an instruction that performs "s1 = op s0".
846 * For: float-to-int, int-to-float
849 * r0 = target dalvik register address
850 * r1 = src dalvik register address
853 flds s0, [r1] @ s0<- vB
854 ftosizs s1, s0 @ s1<- op s0
855 fsts s1, [r0] @ vA<- s1
859 /* ------------------------------ */
861 .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
862 dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
863 /* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
864 /* File: armv5te-vfp/funopWider.S */
866 * Generic 32bit-to-64bit floating point unary operation. Provide an
867 * "instr" line that specifies an instruction that performs "d0 = op s0".
869 * For: int-to-double, float-to-double
872 * r0 = target dalvik register address
873 * r1 = src dalvik register address
876 flds s0, [r1] @ s0<- vB
877 fsitod d0, s0 @ d0<- op s0
878 fstd d0, [r0] @ vA<- d0
882 /* ------------------------------ */
884 .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
885 dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
886 /* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
887 /* File: armv5te-vfp/funop.S */
889 * Generic 32bit-to-32bit floating point unary operation. Provide an
890 * "instr" line that specifies an instruction that performs "s1 = op s0".
892 * For: float-to-int, int-to-float
895 * r0 = target dalvik register address
896 * r1 = src dalvik register address
899 flds s0, [r1] @ s0<- vB
900 fsitos s1, s0 @ s1<- op s0
901 fsts s1, [r0] @ vA<- s1
905 /* ------------------------------ */
907 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
908 dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
909 /* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
911 * Compare two floating-point values. Puts 0, 1, or -1 into the
912 * destination register based on the results of the comparison.
914 * int compare(x, y) {
917 * } else if (x < y) {
919 * } else if (x > y) {
930 /* op vAA, vBB, vCC */
931 fldd d0, [r0] @ d0<- vBB
932 fldd d1, [r1] @ d1<- vCC
933 fcmpd d0, d1 @ compare (vBB, vCC)
934 mov r0, #1 @ r0<- 1 (default)
935 fmstat @ export status flags
936 mvnmi r0, #0 @ (less than) r0<- -1
937 moveq r0, #0 @ (equal) r0<- 0
940 /* ------------------------------ */
942 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
943 dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
944 /* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
946 * Compare two floating-point values. Puts 0, 1, or -1 into the
947 * destination register based on the results of the comparison.
949 * int compare(x, y) {
952 * } else if (x > y) {
954 * } else if (x < y) {
964 /* op vAA, vBB, vCC */
965 fldd d0, [r0] @ d0<- vBB
966 fldd d1, [r1] @ d1<- vCC
967 fcmped d0, d1 @ compare (vBB, vCC)
968 mvn r0, #0 @ r0<- -1 (default)
969 fmstat @ export status flags
970 movgt r0, #1 @ (greater than) r0<- 1
971 moveq r0, #0 @ (equal) r0<- 0
974 /* ------------------------------ */
976 .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
977 dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
978 /* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
980 * Compare two floating-point values. Puts 0, 1, or -1 into the
981 * destination register based on the results of the comparison.
983 * int compare(x, y) {
986 * } else if (x < y) {
988 * } else if (x > y) {
998 /* op vAA, vBB, vCC */
999 flds s0, [r0] @ d0<- vBB
1000 flds s1, [r1] @ d1<- vCC
1001 fcmps s0, s1 @ compare (vBB, vCC)
1002 mov r0, #1 @ r0<- 1 (default)
1003 fmstat @ export status flags
1004 mvnmi r0, #0 @ (less than) r0<- -1
1005 moveq r0, #0 @ (equal) r0<- 0
1008 /* ------------------------------ */
1010 .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
1011 dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
1012 /* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
1014 * Compare two floating-point values. Puts 0, 1, or -1 into the
1015 * destination register based on the results of the comparison.
1017 * int compare(x, y) {
1020 * } else if (x > y) {
1022 * } else if (x < y) {
1032 /* op vAA, vBB, vCC */
1033 flds s0, [r0] @ d0<- vBB
1034 flds s1, [r1] @ d1<- vCC
1035 fcmps s0, s1 @ compare (vBB, vCC)
1036 mvn r0, #0 @ r0<- -1 (default)
1037 fmstat @ export status flags
1038 movgt r0, #1 @ (greater than) r0<- 1
1039 moveq r0, #0 @ (equal) r0<- 0
1042 /* ------------------------------ */
1044 .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
1045 dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
1046 /* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
1048 * 64-bit floating point vfp sqrt operation.
1049 * If the result is a NaN, bail out to library code to do
1053 * r2 src addr of op1
1062 bxeq lr @ Result OK - return
1064 fmrrd r0, r1, d0 @ reload orig operand
1065 bx r2 @ tail call to sqrt library routine
1070 /* ------------------------------ */
1072 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
1073 dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
1074 /* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
1076 * Throw an exception from JIT'ed code.
1078 * r0 Dalvik PC that raises the exception
1082 /* ------------------------------ */
1084 .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
1085 dvmCompiler_TEMPLATE_MEM_OP_DECODE:
1086 /* File: armv5te-vfp/TEMPLATE_MEM_OP_DECODE.S */
1087 #if defined(WITH_SELF_VERIFICATION)
1089 * This handler encapsulates heap memory ops for selfVerification mode.
1091 * The call to the handler is inserted prior to a heap memory operation.
1092 * This handler then calls a function to decode the memory op, and process
1093 * it accordingly. Afterwards, the handler changes the return address to
1094 * skip the memory op so it never gets executed.
1096 vpush {d0-d15} @ save out all fp registers
1097 push {r0-r12,lr} @ save out all registers
1098 ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
1099 mov r0, lr @ arg0 <- link register
1100 mov r1, sp @ arg1 <- stack pointer
1101 blx r2 @ decode and handle the mem op
1102 pop {r0-r12,lr} @ restore all registers
1103 vpop {d0-d15} @ restore all fp registers
1104 bx lr @ return to compiled code
1107 /* ------------------------------ */
1109 .global dvmCompiler_TEMPLATE_STRING_COMPARETO
1110 dvmCompiler_TEMPLATE_STRING_COMPARETO:
1111 /* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
1113 * String's compareTo.
1115 * Requires r0/r1 to have been previously checked for null. Will
1116 * return negative if this's string is < comp, 0 if they are the
1117 * same and positive if >.
1121 * This code relies on hard-coded offsets for string objects, and must be
1122 * kept in sync with definitions in UtfString.h. See asm-constants.h
1125 * r0: this object pointer
1126 * r1: comp object pointer
1130 mov r2, r0 @ this to r2, opening up r0 for return value
1131 subs r0, r2, r1 @ Same?
1134 ldr r4, [r2, #STRING_FIELDOFF_OFFSET]
1135 ldr r9, [r1, #STRING_FIELDOFF_OFFSET]
1136 ldr r7, [r2, #STRING_FIELDOFF_COUNT]
1137 ldr r10, [r1, #STRING_FIELDOFF_COUNT]
1138 ldr r2, [r2, #STRING_FIELDOFF_VALUE]
1139 ldr r1, [r1, #STRING_FIELDOFF_VALUE]
1142 * At this point, we have:
1146 * We're going to compute
1153 /* Now, build pointers to the string data */
1154 add r2, r2, r4, lsl #1
1155 add r1, r1, r9, lsl #1
1157 * Note: data pointers point to previous element so we can use pre-index
1158 * mode with base writeback.
1160 add r2, #16-2 @ offset to contents[-1]
1161 add r1, #16-2 @ offset to contents[-1]
1164 * At this point we have:
1165 * r2: *this string data
1166 * r1: *comp string data
1167 * r10: iteration count for comparison
1168 * r11: value to return if the first part of the string is equal
1169 * r0: reserved for result
1170 * r3, r4, r7, r8, r9, r12 available for loading string data
1177 * Unroll the first two checks so we can quickly catch early mismatch
1178 * on long strings (but preserve incoming alignment)
1229 /* Long string case */
1246 /* ------------------------------ */
1248 .global dvmCompiler_TEMPLATE_STRING_INDEXOF
1249 dvmCompiler_TEMPLATE_STRING_INDEXOF:
1250 /* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
1254 * Requires r0 to have been previously checked for null. Will
1255 * return index of match of r1 in r0.
1259 * This code relies on hard-coded offsets for string objects, and must be
1260 * kept in sync wth definitions in UtfString.h See asm-constants.h
1263 * r0: string object pointer
1265 * r2: Starting offset in string data
1268 ldr r7, [r0, #STRING_FIELDOFF_OFFSET]
1269 ldr r8, [r0, #STRING_FIELDOFF_COUNT]
1270 ldr r0, [r0, #STRING_FIELDOFF_VALUE]
1273 * At this point, we have:
1274 * r0: object pointer
1276 * r2: starting offset
1281 /* Build pointer to start of string data */
1283 add r0, r0, r7, lsl #1
1285 /* Save a copy of starting data in r7 */
1288 /* Clamp start to [0..count] */
1294 /* Build pointer to start of data to compare and pre-bias */
1295 add r0, r0, r2, lsl #1
1298 /* Compute iteration count */
1302 * At this point we have:
1303 * r0: start of data to test
1304 * r1: chat to compare
1305 * r8: iteration count
1306 * r7: original start of string
1307 * r3, r4, r9, r10, r11, r12 available for loading string data
1311 blt indexof_remainder
1364 /* ------------------------------ */
1366 .global dvmCompiler_TEMPLATE_INTERPRET
1367 dvmCompiler_TEMPLATE_INTERPRET:
1368 /* File: armv5te/TEMPLATE_INTERPRET.S */
1370 * This handler transfers control to the interpeter without performing
1371 * any lookups. It may be called either as part of a normal chaining
1372 * operation, or from the transition code in header.S. We distinquish
1373 * the two cases by looking at the link register. If called from a
1374 * translation chain, it will point to the chaining Dalvik PC -3.
1377 * r1 - the Dalvik PC to begin interpretation.
1379 * [lr, #3] contains Dalvik PC to begin interpretation
1380 * rSELF - pointer to thread
1381 * rFP - Dalvik frame pointer
1384 #if defined(WORKAROUND_CORTEX_A9_745320)
1385 /* Don't use conditional loads if the HW defect exists */
1392 ldr r2, .LinterpPunt
1393 mov r0, r1 @ set Dalvik PC
1398 .word dvmJitToInterpPunt
1400 /* ------------------------------ */
1402 .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1403 dvmCompiler_TEMPLATE_MONITOR_ENTER:
1404 /* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1406 * Call out to the runtime to lock an object. Because this thread
1407 * may have been suspended in THREAD_MONITOR state and the Jit's
1408 * translation cache subsequently cleared, we cannot return directly.
1409 * Instead, unconditionally transition to the interpreter to resume.
1413 * r1 - the object (which has already been null-checked by the caller
1414 * r4 - the Dalvik PC of the following instruction.
1416 ldr r2, .LdvmLockObject
1417 mov r3, #0 @ Record that we're not returning
1418 str r3, [r0, #offThread_inJitCodeCache]
1419 blx r2 @ dvmLockObject(self, obj)
1420 ldr r2, .LdvmJitToInterpNoChain
1421 @ Bail to interpreter - no chain [note - r4 still contains rPC]
1422 #if defined(WITH_JIT_TUNING)
1423 mov r0, #kHeavyweightMonitor
1427 /* ------------------------------ */
1429 .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1430 dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1431 /* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1433 * To support deadlock prediction, this version of MONITOR_ENTER
1434 * will always call the heavyweight dvmLockObject, check for an
1435 * exception and then bail out to the interpreter.
1439 * r1 - the object (which has already been null-checked by the caller
1440 * r4 - the Dalvik PC of the following instruction.
1443 ldr r2, .LdvmLockObject
1444 mov r3, #0 @ Record that we're not returning
1445 str r3, [r0, #offThread_inJitCodeCache]
1446 blx r2 @ dvmLockObject(self, obj)
1447 @ test for exception
1448 ldr r1, [rSELF, #offThread_exception]
1451 ldr r2, .LhandleException
1452 sub r0, r4, #2 @ roll dPC back to this monitor instruction
1455 @ Bail to interpreter - no chain [note - r4 still contains rPC]
1456 #if defined(WITH_JIT_TUNING)
1457 mov r0, #kHeavyweightMonitor
1459 ldr pc, .LdvmJitToInterpNoChain
1461 /* ------------------------------ */
1463 .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING
1464 dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
1465 /* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */
1467 * Increment profile counter for this trace, and decrement
1468 * sample counter. If sample counter goes below zero, turn
1472 * (lr-11) is address of pointer to counter. Note: the counter
1473 * actually exists 10 bytes before the return target, but because
1474 * we are arriving from thumb mode, lr will have its low bit set.
1477 ldr r1, [rSELF, #offThread_pProfileCountdown]
1478 ldr r2, [r0] @ get counter
1479 ldr r3, [r1] @ get countdown timer
1482 blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling
1487 .LTEMPLATE_PERIODIC_PROFILING_disable_profiling:
1488 mov r4, lr @ preserve lr
1489 ldr r0, .LdvmJitTraceProfilingOff
1493 /* ------------------------------ */
1495 .global dvmCompiler_TEMPLATE_RETURN_PROF
1496 dvmCompiler_TEMPLATE_RETURN_PROF:
1497 /* File: armv5te/TEMPLATE_RETURN_PROF.S */
1498 #define TEMPLATE_INLINE_PROFILING
1499 /* File: armv5te/TEMPLATE_RETURN.S */
1501 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
1502 * If the stored value in returnAddr
1503 * is non-zero, the caller is compiled by the JIT thus return to the
1504 * address in the code cache following the invoke instruction. Otherwise
1505 * return to the special dvmJitToInterpNoChain entry point.
1507 #if defined(TEMPLATE_INLINE_PROFILING)
1508 stmfd sp!, {r0-r2,lr} @ preserve live registers
1511 ldr ip, .LdvmFastMethodTraceExit
1513 ldmfd sp!, {r0-r2,lr} @ restore live registers
1515 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
1516 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
1517 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags
1518 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
1519 #if !defined(WITH_SELF_VERIFICATION)
1520 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
1522 mov r9, #0 @ disable chaining
1524 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
1525 @ r2<- method we're returning to
1526 cmp r2, #0 @ break frame?
1527 #if !defined(WITH_SELF_VERIFICATION)
1528 beq 1f @ bail to interpreter
1530 blxeq lr @ punt to interpreter and compare state
1532 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
1533 mov rFP, r10 @ publish new FP
1534 ldr r10, [r2, #offMethod_clazz] @ r10<- method->clazz
1536 str r2, [rSELF, #offThread_method]@ self->method = newSave->method
1537 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
1538 str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
1539 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
1540 str r0, [rSELF, #offThread_methodClassDex]
1541 cmp r8, #0 @ check the break flags
1542 movne r9, #0 @ clear the chaining cell address
1543 str r9, [rSELF, #offThread_inJitCodeCache] @ in code cache or not
1544 cmp r9, #0 @ chaining cell exists?
1545 blxne r9 @ jump to the chaining cell
1546 #if defined(WITH_JIT_TUNING)
1547 mov r0, #kCallsiteInterpreted
1549 mov pc, r1 @ callsite is interpreted
1552 str r0, [rSELF, #offThread_inJitCodeCache] @ reset inJitCodeCache
1553 stmia rSELF, {rPC, rFP} @ SAVE_PC_FP_TO_SELF()
1554 ldr r2, .LdvmMterpStdBail @ defined in footer.S
1555 mov r0, rSELF @ Expecting rSELF in r0
1556 blx r2 @ exit the interpreter
1558 #undef TEMPLATE_INLINE_PROFILING
1560 /* ------------------------------ */
1562 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF
1563 dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT_PROF:
1564 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT_PROF.S */
1565 #define TEMPLATE_INLINE_PROFILING
1566 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
1568 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
1569 * into rPC then jump to dvmJitToInterpNoChain to dispatch the
1570 * runtime-resolved callee.
1572 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
1573 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
1574 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
1575 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
1576 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags
1577 add r3, r1, #1 @ Thumb addr is odd
1578 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
1579 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
1580 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
1581 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
1582 cmp r10, r9 @ bottom < interpStackEnd?
1583 bxlo lr @ return to raise stack overflow excep.
1584 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
1585 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
1586 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
1587 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1588 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
1589 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
1592 @ set up newSaveArea
1593 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
1594 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
1595 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
1596 cmp r8, #0 @ breakFlags != 0
1597 bxne lr @ bail to the interpreter
1598 tst r10, #ACC_NATIVE
1599 #if !defined(WITH_SELF_VERIFICATION)
1602 bxne lr @ bail to the interpreter
1605 ldr r10, .LdvmJitToInterpTraceSelectNoChain
1606 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
1608 @ Update "thread" values for the new method
1609 str r0, [rSELF, #offThread_method] @ self->method = methodToCall
1610 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
1611 mov rFP, r1 @ fp = newFp
1612 str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
1613 #if defined(TEMPLATE_INLINE_PROFILING)
1614 stmfd sp!, {r0-r3} @ preserve r0-r3
1616 @ r0=methodToCall, r1=rSELF
1617 ldr ip, .LdvmFastMethodTraceEnter
1619 ldmfd sp!, {r0-r3} @ restore r0-r3
1622 @ Start executing the callee
1623 #if defined(WITH_JIT_TUNING)
1624 mov r0, #kInlineCacheMiss
1626 bx r10 @ dvmJitToInterpTraceSelectNoChain
1628 #undef TEMPLATE_INLINE_PROFILING
1630 /* ------------------------------ */
1632 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF
1633 dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN_PROF:
1634 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN_PROF.S */
1635 #define TEMPLATE_INLINE_PROFILING
1636 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
1638 * For monomorphic callsite, setup the Dalvik frame and return to the
1639 * Thumb code through the link register to transfer control to the callee
1640 * method through a dedicated chaining cell.
1642 @ r0 = methodToCall, r1 = returnCell, r2 = methodToCall->outsSize
1643 @ rPC = dalvikCallsite, r7 = methodToCall->registersSize
1644 @ methodToCall is guaranteed to be non-native
1646 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
1647 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags
1648 add r3, r1, #1 @ Thumb addr is odd
1649 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
1650 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
1651 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
1652 add r12, lr, #2 @ setup the punt-to-interp address
1653 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
1654 cmp r10, r9 @ bottom < interpStackEnd?
1655 bxlo r12 @ return to raise stack overflow excep.
1656 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
1657 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
1658 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1659 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
1661 @ set up newSaveArea
1662 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
1663 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
1664 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
1665 cmp r8, #0 @ breakFlags != 0
1666 bxne r12 @ bail to the interpreter
1668 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
1670 @ Update "thread" values for the new method
1671 str r0, [rSELF, #offThread_method] @ self->method = methodToCall
1672 str r3, [rSELF, #offThread_methodClassDex] @ self->methodClassDex = ...
1673 mov rFP, r1 @ fp = newFp
1674 str rFP, [rSELF, #offThread_curFrame] @ curFrame = newFp
1675 #if defined(TEMPLATE_INLINE_PROFILING)
1676 stmfd sp!, {r0-r2,lr} @ preserve clobbered live registers
1678 @ r0=methodToCall, r1=rSELF
1679 ldr ip, .LdvmFastMethodTraceEnter
1681 ldmfd sp!, {r0-r2,lr} @ restore registers
1684 bx lr @ return to the callee-chaining cell
1686 #undef TEMPLATE_INLINE_PROFILING
1688 /* ------------------------------ */
1690 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF
1691 dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF:
1692 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN_PROF.S */
1693 #define TEMPLATE_INLINE_PROFILING
1694 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
1696 * For polymorphic callsite, check whether the cached class pointer matches
1697 * the current one. If so setup the Dalvik frame and return to the
1698 * Thumb code through the link register to transfer control to the callee
1699 * method through a dedicated chaining cell.
1701 * The predicted chaining cell is declared in ArmLIR.h with the
1704 * typedef struct PredictedChainingCell {
1706 * const ClassObject *clazz;
1707 * const Method *method;
1709 * } PredictedChainingCell;
1711 * Upon returning to the callsite:
1712 * - lr : to branch to the chaining cell
1713 * - lr+2: to punt to the interpreter
1714 * - lr+4: to fully resolve the callee and may rechain.
1718 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
1719 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
1720 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
1721 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
1722 ldr r9, [rSELF, #offThread_icRechainCount] @ r1 <- shared rechainCount
1723 cmp r3, r8 @ predicted class == actual class?
1724 #if defined(WITH_JIT_TUNING)
1725 ldr r7, .LdvmICHitCount
1726 #if defined(WORKAROUND_CORTEX_A9_745320)
1727 /* Don't use conditional loads if the HW defect exists */
1737 ldreqh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
1738 ldreqh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
1739 beq .LinvokeChainProf @ predicted chain is valid
1740 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
1741 cmp r8, #0 @ initialized class or not
1743 subne r1, r9, #1 @ count--
1744 strne r1, [rSELF, #offThread_icRechainCount] @ write back to thread
1745 add lr, lr, #4 @ return to fully-resolve landing pad
1748 * r2 <- &predictedChainCell
1751 * r7 <- this->class->vtable
1755 #undef TEMPLATE_INLINE_PROFILING
1757 /* ------------------------------ */
1759 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF
1760 dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE_PROF:
1761 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE_PROF.S */
1762 #define TEMPLATE_INLINE_PROFILING
1763 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
1764 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
1765 @ r7 = methodToCall->registersSize
1766 ldr r9, [rSELF, #offThread_interpStackEnd] @ r9<- interpStackEnd
1767 ldrb r8, [rSELF, #offThread_breakFlags] @ r8<- breakFlags
1768 add r3, r1, #1 @ Thumb addr is odd
1769 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
1770 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
1771 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
1772 cmp r10, r9 @ bottom < interpStackEnd?
1773 bxlo lr @ return to raise stack overflow excep.
1774 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
1775 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1776 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
1778 @ set up newSaveArea
1779 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
1780 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
1781 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
1782 cmp r8, #0 @ breakFlags != 0
1783 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
1784 #if !defined(WITH_SELF_VERIFICATION)
1785 bxne lr @ bail to the interpreter
1787 bx lr @ bail to interpreter unconditionally
1790 @ go ahead and transfer control to the native code
1791 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
1793 str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
1794 str r2, [rSELF, #offThread_inJitCodeCache] @ not in the jit code cache
1795 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1796 @ newFp->localRefCookie=top
1797 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
1799 mov r2, r0 @ arg2<- methodToCall
1800 mov r0, r1 @ arg0<- newFP
1801 add r1, rSELF, #offThread_retval @ arg1<- &retval
1802 mov r3, rSELF @ arg3<- self
1803 #if defined(TEMPLATE_INLINE_PROFILING)
1804 @ r2=methodToCall, r6=rSELF
1805 stmfd sp!, {r2,r6} @ to be consumed after JNI return
1806 stmfd sp!, {r0-r3} @ preserve r0-r3
1809 @ r0=JNIMethod, r1=rSELF
1810 ldr ip, .LdvmFastMethodTraceEnter
1812 ldmfd sp!, {r0-r3} @ restore r0-r3
1815 blx r8 @ off to the native code
1817 #if defined(TEMPLATE_INLINE_PROFILING)
1818 ldmfd sp!, {r0-r1} @ restore r2 and r6
1819 @ r0=JNIMethod, r1=rSELF
1820 ldr ip, .LdvmFastNativeMethodTraceExit
1823 @ native return; r10=newSaveArea
1824 @ equivalent to dvmPopJniLocals
1825 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1826 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1827 ldr r1, [rSELF, #offThread_exception] @ check for exception
1828 str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
1830 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
1831 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
1833 @ r0 = dalvikCallsitePC
1834 bne .LhandleException @ no, handle exception
1836 str r2, [rSELF, #offThread_inJitCodeCache] @ set the mode properly
1837 cmp r2, #0 @ return chaining cell still exists?
1838 bxne r2 @ yes - go ahead
1840 @ continue executing the next instruction through the interpreter
1841 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1842 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
1843 #if defined(WITH_JIT_TUNING)
1844 mov r0, #kCallsiteInterpreted
1848 #undef TEMPLATE_INLINE_PROFILING
1850 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1851 /* File: armv5te/footer.S */
1853 * ===========================================================================
1854 * Common subroutines and data
1855 * ===========================================================================
1858 .section .data.rel.ro
1861 @ Prep for the native call
1862 @ r1 = newFP, r0 = methodToCall
1864 ldr r9, [rSELF, #offThread_jniLocal_topCookie]@r9<-thread->localRef->...
1865 str r2, [rSELF, #offThread_inJitCodeCache] @ not in jit code cache
1866 str r1, [rSELF, #offThread_curFrame] @ curFrame = newFp
1867 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1868 @ newFp->localRefCookie=top
1869 ldrh lr, [rSELF, #offThread_subMode]
1870 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
1872 mov r2, r0 @ r2<- methodToCall
1873 mov r0, r1 @ r0<- newFP
1874 add r1, rSELF, #offThread_retval @ r1<- &retval
1875 mov r3, rSELF @ arg3<- self
1876 ands lr, #kSubModeMethodTrace
1877 beq 121f @ hop if not profiling
1878 @ r2: methodToCall, r6: rSELF
1883 ldr ip, .LdvmFastMethodTraceEnter
1887 ldr ip, [r2, #offMethod_nativeFunc]
1891 ldr ip, .LdvmFastNativeMethodTraceExit
1895 ldr ip, [r2, #offMethod_nativeFunc]
1899 @ native return; r10=newSaveArea
1900 @ equivalent to dvmPopJniLocals
1901 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1902 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1903 ldr r1, [rSELF, #offThread_exception] @ check for exception
1904 str rFP, [rSELF, #offThread_curFrame] @ curFrame = fp
1906 str r0, [rSELF, #offThread_jniLocal_topCookie] @ new top <- old top
1907 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1909 @ r0 = dalvikCallsitePC
1910 bne .LhandleException @ no, handle exception
1912 str r2, [rSELF, #offThread_inJitCodeCache] @ set the new mode
1913 cmp r2, #0 @ return chaining cell still exists?
1914 bxne r2 @ yes - go ahead
1916 @ continue executing the next instruction through the interpreter
1917 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1918 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
1919 #if defined(WITH_JIT_TUNING)
1920 mov r0, #kCallsiteInterpreted
1926 * r0 Faulting Dalvik PC
1929 #if defined(WITH_SELF_VERIFICATION)
1930 ldr pc, .LdeadFood @ should not see this under self-verification mode
1935 str r2, [rSELF, #offThread_inJitCodeCache] @ in interpreter land
1936 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1937 ldr rIBASE, .LdvmAsmInstructionStart @ same as above
1938 mov rPC, r0 @ reload the faulting Dalvik address
1939 bx r1 @ branch to dvmMterpCommonExceptionThrown
1942 .LdvmAsmInstructionStart:
1943 .word dvmAsmInstructionStart
1944 .LdvmJitToInterpNoChainNoProfile:
1945 .word dvmJitToInterpNoChainNoProfile
1946 .LdvmJitToInterpTraceSelectNoChain:
1947 .word dvmJitToInterpTraceSelectNoChain
1948 .LdvmJitToInterpNoChain:
1949 .word dvmJitToInterpNoChain
1951 .word dvmMterpStdBail
1952 .LdvmMterpCommonExceptionThrown:
1953 .word dvmMterpCommonExceptionThrown
1956 .LdvmJitTraceProfilingOff:
1957 .word dvmJitTraceProfilingOff
1958 #if defined(WITH_JIT_TUNING)
1960 .word gDvmICHitCount
1962 #if defined(WITH_SELF_VERIFICATION)
1963 .LdvmSelfVerificationMemOpDecode:
1964 .word dvmSelfVerificationMemOpDecode
1966 .LdvmFastMethodTraceEnter:
1967 .word dvmFastMethodTraceEnter
1968 .LdvmFastNativeMethodTraceExit:
1969 .word dvmFastNativeMethodTraceExit
1970 .LdvmFastMethodTraceExit:
1971 .word dvmFastMethodTraceExit
1973 .word __aeabi_cdcmple
1975 .word __aeabi_cfcmple
1977 .global dmvCompilerTemplateEnd
1978 dmvCompilerTemplateEnd:
1980 #endif /* WITH_JIT */