2 * This file was generated automatically by gen-template.py for 'armv5te'.
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 rGLUE MterpGlue 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/platform.S */
106 * ===========================================================================
107 * CPU-version-specific defines and utility
108 * ===========================================================================
112 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
113 * Jump to subroutine.
115 * May modify IP and LR.
117 .macro LDR_PC_LR source
123 .global dvmCompilerTemplateStart
124 .type dvmCompilerTemplateStart, %function
127 dvmCompilerTemplateStart:
129 /* ------------------------------ */
131 .global dvmCompiler_TEMPLATE_CMP_LONG
132 dvmCompiler_TEMPLATE_CMP_LONG:
133 /* File: armv5te/TEMPLATE_CMP_LONG.S */
135 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
136 * register based on the results of the comparison.
138 * We load the full values with LDM, but in practice many values could
139 * be resolved by only looking at the high word. This could be made
140 * faster or slower by splitting the LDM into a pair of LDRs.
142 * If we just wanted to set condition flags, we could do this:
146 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
147 * integer value, which we can do with 2 conditional mov/mvn instructions
148 * (set 1, set -1; if they're equal we already have 0 in ip), giving
149 * us a constant 5-cycle path plus a branch at the end to the
150 * instruction epilogue code. The multi-compare approach below needs
151 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
152 * in the worst case (the 64-bit values are equal).
154 /* cmp-long vAA, vBB, vCC */
155 cmp r1, r3 @ compare (vBB+1, vCC+1)
156 blt .LTEMPLATE_CMP_LONG_less @ signed compare on high part
157 bgt .LTEMPLATE_CMP_LONG_greater
158 subs r0, r0, r2 @ r0<- r0 - r2
160 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part
161 .LTEMPLATE_CMP_LONG_less:
164 .LTEMPLATE_CMP_LONG_greater:
168 /* ------------------------------ */
170 .global dvmCompiler_TEMPLATE_RETURN
171 dvmCompiler_TEMPLATE_RETURN:
172 /* File: armv5te/TEMPLATE_RETURN.S */
174 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
175 * If the stored value in returnAddr
176 * is non-zero, the caller is compiled by the JIT thus return to the
177 * address in the code cache following the invoke instruction. Otherwise
178 * return to the special dvmJitToInterpNoChain entry point.
180 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
181 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
182 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
183 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
184 #if !defined(WITH_SELF_VERIFICATION)
185 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
187 mov r9, #0 @ disable chaining
189 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
190 @ r2<- method we're returning to
191 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
192 cmp r2, #0 @ break frame?
193 #if !defined(WITH_SELF_VERIFICATION)
194 beq 1f @ bail to interpreter
196 blxeq lr @ punt to interpreter and compare state
198 ldr r1, .LdvmJitToInterpNoChainNoProfile @ defined in footer.S
199 mov rFP, r10 @ publish new FP
200 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
201 ldr r8, [r8] @ r8<- suspendCount
203 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
204 ldr r0, [r10, #offClassObject_pDvmDex] @ r0<- method->clazz->pDvmDex
205 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
206 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
207 str r0, [rGLUE, #offGlue_methodClassDex]
208 cmp r8, #0 @ check the suspendCount
209 movne r9, #0 @ clear the chaining cell address
210 str r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
211 cmp r9, #0 @ chaining cell exists?
212 blxne r9 @ jump to the chaining cell
213 #if defined(WITH_JIT_TUNING)
214 mov r0, #kCallsiteInterpreted
216 mov pc, r1 @ callsite is interpreted
218 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE()
219 ldr r2, .LdvmMterpStdBail @ defined in footer.S
220 mov r1, #0 @ changeInterp = false
221 mov r0, rGLUE @ Expecting rGLUE in r0
222 blx r2 @ exit the interpreter
224 /* ------------------------------ */
226 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
227 dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
228 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
230 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
231 * into rPC then jump to dvmJitToInterpNoChain to dispatch the
232 * runtime-resolved callee.
234 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
235 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
236 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
237 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
238 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
239 add r3, r1, #1 @ Thumb addr is odd
240 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
241 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
242 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
243 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
244 ldr r8, [r8] @ r8<- suspendCount (int)
245 cmp r10, r9 @ bottom < interpStackEnd?
246 bxlo lr @ return to raise stack overflow excep.
247 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
248 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
249 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
250 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
251 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
252 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
256 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
257 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
258 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
259 cmp r8, #0 @ suspendCount != 0
260 bxne lr @ bail to the interpreter
262 #if !defined(WITH_SELF_VERIFICATION)
265 bxne lr @ bail to the interpreter
268 ldr r10, .LdvmJitToInterpTraceSelectNoChain
269 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
270 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
272 @ Update "glue" values for the new method
273 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
274 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
275 mov rFP, r1 @ fp = newFp
276 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
278 @ Start executing the callee
279 #if defined(WITH_JIT_TUNING)
280 mov r0, #kInlineCacheMiss
282 mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
284 /* ------------------------------ */
286 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
287 dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
288 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
290 * For monomorphic callsite, setup the Dalvik frame and return to the
291 * Thumb code through the link register to transfer control to the callee
292 * method through a dedicated chaining cell.
294 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
295 @ methodToCall is guaranteed to be non-native
297 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
298 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
299 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
300 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
301 add r3, r1, #1 @ Thumb addr is odd
302 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
303 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
304 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
305 add r12, lr, #2 @ setup the punt-to-interp address
306 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
307 ldr r8, [r8] @ r8<- suspendCount (int)
308 cmp r10, r9 @ bottom < interpStackEnd?
309 bxlo r12 @ return to raise stack overflow excep.
310 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
311 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
312 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
313 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
314 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
318 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
319 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
320 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
321 cmp r8, #0 @ suspendCount != 0
322 bxne r12 @ bail to the interpreter
324 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
325 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
327 @ Update "glue" values for the new method
328 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
329 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
330 mov rFP, r1 @ fp = newFp
331 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
333 bx lr @ return to the callee-chaining cell
335 /* ------------------------------ */
337 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
338 dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
339 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
341 * For polymorphic callsite, check whether the cached class pointer matches
342 * the current one. If so setup the Dalvik frame and return to the
343 * Thumb code through the link register to transfer control to the callee
344 * method through a dedicated chaining cell.
346 * The predicted chaining cell is declared in ArmLIR.h with the
349 * typedef struct PredictedChainingCell {
351 * const ClassObject *clazz;
352 * const Method *method;
354 * } PredictedChainingCell;
356 * Upon returning to the callsite:
357 * - lr : to branch to the chaining cell
358 * - lr+2: to punt to the interpreter
359 * - lr+4: to fully resolve the callee and may rechain.
363 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
364 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
365 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
366 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
367 ldr r9, [rGLUE, #offGlue_icRechainCount] @ r1 <- shared rechainCount
368 cmp r3, r8 @ predicted class == actual class?
369 #if defined(WITH_JIT_TUNING)
370 ldr r7, .LdvmICHitCount
375 beq .LinvokeChain @ predicted chain is valid
376 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
377 cmp r8, #0 @ initialized class or not
379 subne r1, r9, #1 @ count--
380 strne r1, [rGLUE, #offGlue_icRechainCount] @ write back to InterpState
381 add lr, lr, #4 @ return to fully-resolve landing pad
384 * r2 <- &predictedChainCell
387 * r7 <- this->class->vtable
391 /* ------------------------------ */
393 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
394 dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
395 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
396 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
397 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
398 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
399 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
400 add r3, r1, #1 @ Thumb addr is odd
401 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
402 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
403 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
404 ldr r8, [r8] @ r3<- suspendCount (int)
405 cmp r10, r9 @ bottom < interpStackEnd?
406 bxlo lr @ return to raise stack overflow excep.
407 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
408 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
409 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
410 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
414 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
415 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
416 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
417 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
418 cmp r8, #0 @ suspendCount != 0
419 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
420 #if !defined(WITH_SELF_VERIFICATION)
421 bxne lr @ bail to the interpreter
423 bx lr @ bail to interpreter unconditionally
426 @ go ahead and transfer control to the native code
427 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
429 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
430 str r2, [r3, #offThread_inJitCodeCache] @ not in the jit code cache
431 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
432 @ newFp->localRefCookie=top
433 mov r9, r3 @ r9<- glue->self (preserve)
434 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
436 mov r2, r0 @ r2<- methodToCall
437 mov r0, r1 @ r0<- newFP
438 add r1, rGLUE, #offGlue_retval @ r1<- &retval
440 blx r8 @ off to the native code
442 @ native return; r9=self, r10=newSaveArea
443 @ equivalent to dvmPopJniLocals
444 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
445 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
446 ldr r1, [r9, #offThread_exception] @ check for exception
447 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
449 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
450 ldr r0, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
452 @ r0 = dalvikCallsitePC
453 bne .LhandleException @ no, handle exception
455 str r2, [r9, #offThread_inJitCodeCache] @ set the mode properly
456 cmp r2, #0 @ return chaining cell still exists?
457 bxne r2 @ yes - go ahead
459 @ continue executing the next instruction through the interpreter
460 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
461 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
462 #if defined(WITH_JIT_TUNING)
463 mov r0, #kCallsiteInterpreted
467 /* ------------------------------ */
469 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE
470 dvmCompiler_TEMPLATE_CMPG_DOUBLE:
471 /* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */
472 /* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
474 * For the JIT: incoming arguments in r0-r1, r2-r3
477 * Compare two floating-point values. Puts 0, 1, or -1 into the
478 * destination register based on the results of the comparison.
480 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
481 * on what value we'd like to return when one of the operands is NaN.
483 * See OP_CMPL_FLOAT for an explanation.
485 * For: cmpl-double, cmpg-double
487 /* op vAA, vBB, vCC */
488 push {r0-r3} @ save operands
489 mov r11, lr @ save return address
490 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple"
491 bhi .LTEMPLATE_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
492 mvncc r0, #0 @ (less than) r1<- -1
493 moveq r0, #0 @ (equal) r1<- 0, trumps less than
494 add sp, #16 @ drop unused operands
497 @ Test for NaN with a second comparison. EABI forbids testing bit
498 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
499 @ make the library call.
500 .LTEMPLATE_CMPG_DOUBLE_gt_or_nan:
501 pop {r2-r3} @ restore operands in reverse order
502 pop {r0-r1} @ restore operands in reverse order
503 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if <
504 movcc r0, #1 @ (greater than) r1<- 1
506 mov r0, #1 @ r1<- 1 or -1 for NaN
510 /* ------------------------------ */
512 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE
513 dvmCompiler_TEMPLATE_CMPL_DOUBLE:
514 /* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
516 * For the JIT: incoming arguments in r0-r1, r2-r3
519 * Compare two floating-point values. Puts 0, 1, or -1 into the
520 * destination register based on the results of the comparison.
522 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
523 * on what value we'd like to return when one of the operands is NaN.
525 * See OP_CMPL_FLOAT for an explanation.
527 * For: cmpl-double, cmpg-double
529 /* op vAA, vBB, vCC */
530 push {r0-r3} @ save operands
531 mov r11, lr @ save return address
532 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple"
533 bhi .LTEMPLATE_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
534 mvncc r0, #0 @ (less than) r1<- -1
535 moveq r0, #0 @ (equal) r1<- 0, trumps less than
536 add sp, #16 @ drop unused operands
539 @ Test for NaN with a second comparison. EABI forbids testing bit
540 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
541 @ make the library call.
542 .LTEMPLATE_CMPL_DOUBLE_gt_or_nan:
543 pop {r2-r3} @ restore operands in reverse order
544 pop {r0-r1} @ restore operands in reverse order
545 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if <
546 movcc r0, #1 @ (greater than) r1<- 1
548 mvn r0, #0 @ r1<- 1 or -1 for NaN
551 /* ------------------------------ */
553 .global dvmCompiler_TEMPLATE_CMPG_FLOAT
554 dvmCompiler_TEMPLATE_CMPG_FLOAT:
555 /* File: armv5te/TEMPLATE_CMPG_FLOAT.S */
556 /* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
558 * For the JIT: incoming arguments in r0-r1, r2-r3
561 * Compare two floating-point values. Puts 0, 1, or -1 into the
562 * destination register based on the results of the comparison.
564 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
565 * on what value we'd like to return when one of the operands is NaN.
567 * The operation we're implementing is:
575 * return {-1,1}; // one or both operands was NaN
577 * The straightforward implementation requires 3 calls to functions
578 * that return a result in r0. We can do it with two calls if our
579 * EABI library supports __aeabi_cfcmple (only one if we want to check
588 * for: cmpl-float, cmpg-float
590 /* op vAA, vBB, vCC */
591 mov r9, r0 @ Save copies - we may need to redo
593 mov r11, lr @ save return address
594 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq
595 bhi .LTEMPLATE_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
596 mvncc r0, #0 @ (less than) r0<- -1
597 moveq r0, #0 @ (equal) r0<- 0, trumps less than
599 @ Test for NaN with a second comparison. EABI forbids testing bit
600 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
601 @ make the library call.
602 .LTEMPLATE_CMPG_FLOAT_gt_or_nan:
603 mov r0, r10 @ restore in reverse order
605 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if <
606 movcc r0, #1 @ (greater than) r1<- 1
608 mov r0, #1 @ r1<- 1 or -1 for NaN
612 /* ------------------------------ */
614 .global dvmCompiler_TEMPLATE_CMPL_FLOAT
615 dvmCompiler_TEMPLATE_CMPL_FLOAT:
616 /* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
618 * For the JIT: incoming arguments in r0-r1, r2-r3
621 * Compare two floating-point values. Puts 0, 1, or -1 into the
622 * destination register based on the results of the comparison.
624 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
625 * on what value we'd like to return when one of the operands is NaN.
627 * The operation we're implementing is:
635 * return {-1,1}; // one or both operands was NaN
637 * The straightforward implementation requires 3 calls to functions
638 * that return a result in r0. We can do it with two calls if our
639 * EABI library supports __aeabi_cfcmple (only one if we want to check
648 * for: cmpl-float, cmpg-float
650 /* op vAA, vBB, vCC */
651 mov r9, r0 @ Save copies - we may need to redo
653 mov r11, lr @ save return address
654 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq
655 bhi .LTEMPLATE_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
656 mvncc r0, #0 @ (less than) r0<- -1
657 moveq r0, #0 @ (equal) r0<- 0, trumps less than
659 @ Test for NaN with a second comparison. EABI forbids testing bit
660 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
661 @ make the library call.
662 .LTEMPLATE_CMPL_FLOAT_gt_or_nan:
663 mov r0, r10 @ restore in reverse order
665 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if <
666 movcc r0, #1 @ (greater than) r1<- 1
668 mvn r0, #0 @ r1<- 1 or -1 for NaN
671 /* ------------------------------ */
673 .global dvmCompiler_TEMPLATE_MUL_LONG
674 dvmCompiler_TEMPLATE_MUL_LONG:
675 /* File: armv5te/TEMPLATE_MUL_LONG.S */
677 * Signed 64-bit integer multiply.
679 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
681 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
688 * The low word of the result holds ZX, the high word holds
689 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
690 * it doesn't fit in the low 64 bits.
692 * Unlike most ARM math operations, multiply instructions have
693 * restrictions on using the same register more than once (Rd and Rm
694 * cannot be the same).
696 /* mul-long vAA, vBB, vCC */
697 mul ip, r2, r1 @ ip<- ZxW
698 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
699 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
700 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
705 /* ------------------------------ */
707 .global dvmCompiler_TEMPLATE_SHL_LONG
708 dvmCompiler_TEMPLATE_SHL_LONG:
709 /* File: armv5te/TEMPLATE_SHL_LONG.S */
711 * Long integer shift. This is different from the generic 32/64-bit
712 * binary operations because vAA/vBB are 64-bit but vCC (the shift
713 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
716 /* shl-long vAA, vBB, vCC */
717 and r2, r2, #63 @ r2<- r2 & 0x3f
718 mov r1, r1, asl r2 @ r1<- r1 << r2
719 rsb r3, r2, #32 @ r3<- 32 - r2
720 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
721 subs ip, r2, #32 @ ip<- r2 - 32
722 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
723 mov r0, r0, asl r2 @ r0<- r0 << r2
726 /* ------------------------------ */
728 .global dvmCompiler_TEMPLATE_SHR_LONG
729 dvmCompiler_TEMPLATE_SHR_LONG:
730 /* File: armv5te/TEMPLATE_SHR_LONG.S */
732 * Long integer shift. This is different from the generic 32/64-bit
733 * binary operations because vAA/vBB are 64-bit but vCC (the shift
734 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
737 /* shr-long vAA, vBB, vCC */
738 and r2, r2, #63 @ r0<- r0 & 0x3f
739 mov r0, r0, lsr r2 @ r0<- r2 >> r2
740 rsb r3, r2, #32 @ r3<- 32 - r2
741 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
742 subs ip, r2, #32 @ ip<- r2 - 32
743 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
744 mov r1, r1, asr r2 @ r1<- r1 >> r2
747 /* ------------------------------ */
749 .global dvmCompiler_TEMPLATE_USHR_LONG
750 dvmCompiler_TEMPLATE_USHR_LONG:
751 /* File: armv5te/TEMPLATE_USHR_LONG.S */
753 * Long integer shift. This is different from the generic 32/64-bit
754 * binary operations because vAA/vBB are 64-bit but vCC (the shift
755 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
758 /* ushr-long vAA, vBB, vCC */
759 and r2, r2, #63 @ r0<- r0 & 0x3f
760 mov r0, r0, lsr r2 @ r0<- r2 >> r2
761 rsb r3, r2, #32 @ r3<- 32 - r2
762 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
763 subs ip, r2, #32 @ ip<- r2 - 32
764 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
765 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
768 /* ------------------------------ */
770 .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
771 dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
772 /* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
774 * Throw an exception from JIT'ed code.
776 * r0 Dalvik PC that raises the exception
780 /* ------------------------------ */
782 .global dvmCompiler_TEMPLATE_MEM_OP_DECODE
783 dvmCompiler_TEMPLATE_MEM_OP_DECODE:
784 /* File: armv5te/TEMPLATE_MEM_OP_DECODE.S */
785 #if defined(WITH_SELF_VERIFICATION)
787 * This handler encapsulates heap memory ops for selfVerification mode.
789 * The call to the handler is inserted prior to a heap memory operation.
790 * This handler then calls a function to decode the memory op, and process
791 * it accordingly. Afterwards, the handler changes the return address to
792 * skip the memory op so it never gets executed.
794 push {r0-r12,lr} @ save out all registers
795 mov r0, lr @ arg0 <- link register
796 mov r1, sp @ arg1 <- stack pointer
797 ldr r2, .LdvmSelfVerificationMemOpDecode @ defined in footer.S
798 blx r2 @ decode and handle the mem op
799 pop {r0-r12,lr} @ restore all registers
800 bx lr @ return to compiled code
803 /* ------------------------------ */
805 .global dvmCompiler_TEMPLATE_STRING_COMPARETO
806 dvmCompiler_TEMPLATE_STRING_COMPARETO:
807 /* File: armv5te/TEMPLATE_STRING_COMPARETO.S */
809 * String's compareTo.
811 * Requires r0/r1 to have been previously checked for null. Will
812 * return negative if this's string is < comp, 0 if they are the
813 * same and positive if >.
817 * This code relies on hard-coded offsets for string objects, and must be
818 * kept in sync with definitions in UtfString.h. See asm-constants.h
821 * r0: this object pointer
822 * r1: comp object pointer
826 mov r2, r0 @ this to r2, opening up r0 for return value
827 subs r0, r2, r1 @ Same?
830 ldr r4, [r2, #STRING_FIELDOFF_OFFSET]
831 ldr r9, [r1, #STRING_FIELDOFF_OFFSET]
832 ldr r7, [r2, #STRING_FIELDOFF_COUNT]
833 ldr r10, [r1, #STRING_FIELDOFF_COUNT]
834 ldr r2, [r2, #STRING_FIELDOFF_VALUE]
835 ldr r1, [r1, #STRING_FIELDOFF_VALUE]
838 * At this point, we have:
842 * We're going to compute
849 /* Now, build pointers to the string data */
850 add r2, r2, r4, lsl #1
851 add r1, r1, r9, lsl #1
853 * Note: data pointers point to previous element so we can use pre-index
854 * mode with base writeback.
856 add r2, #16-2 @ offset to contents[-1]
857 add r1, #16-2 @ offset to contents[-1]
860 * At this point we have:
861 * r2: *this string data
862 * r1: *comp string data
863 * r10: iteration count for comparison
864 * r11: value to return if the first part of the string is equal
865 * r0: reserved for result
866 * r3, r4, r7, r8, r9, r12 available for loading string data
873 * Unroll the first two checks so we can quickly catch early mismatch
874 * on long strings (but preserve incoming alignment)
925 /* Long string case */
942 /* ------------------------------ */
944 .global dvmCompiler_TEMPLATE_STRING_INDEXOF
945 dvmCompiler_TEMPLATE_STRING_INDEXOF:
946 /* File: armv5te/TEMPLATE_STRING_INDEXOF.S */
950 * Requires r0 to have been previously checked for null. Will
951 * return index of match of r1 in r0.
955 * This code relies on hard-coded offsets for string objects, and must be
956 * kept in sync wth definitions in UtfString.h See asm-constants.h
959 * r0: string object pointer
961 * r2: Starting offset in string data
964 ldr r7, [r0, #STRING_FIELDOFF_OFFSET]
965 ldr r8, [r0, #STRING_FIELDOFF_COUNT]
966 ldr r0, [r0, #STRING_FIELDOFF_VALUE]
969 * At this point, we have:
972 * r2: starting offset
977 /* Build pointer to start of string data */
979 add r0, r0, r7, lsl #1
981 /* Save a copy of starting data in r7 */
984 /* Clamp start to [0..count] */
990 /* Build pointer to start of data to compare and pre-bias */
991 add r0, r0, r2, lsl #1
994 /* Compute iteration count */
998 * At this point we have:
999 * r0: start of data to test
1000 * r1: chat to compare
1001 * r8: iteration count
1002 * r7: original start of string
1003 * r3, r4, r9, r10, r11, r12 available for loading string data
1007 blt indexof_remainder
1060 /* ------------------------------ */
1062 .global dvmCompiler_TEMPLATE_INTERPRET
1063 dvmCompiler_TEMPLATE_INTERPRET:
1064 /* File: armv5te/TEMPLATE_INTERPRET.S */
1066 * This handler transfers control to the interpeter without performing
1067 * any lookups. It may be called either as part of a normal chaining
1068 * operation, or from the transition code in header.S. We distinquish
1069 * the two cases by looking at the link register. If called from a
1070 * translation chain, it will point to the chaining Dalvik PC -3.
1073 * r1 - the Dalvik PC to begin interpretation.
1075 * [lr, #3] contains Dalvik PC to begin interpretation
1076 * rGLUE - pointer to interpState
1077 * rFP - Dalvik frame pointer
1081 ldr r2, .LinterpPunt
1082 mov r0, r1 @ set Dalvik PC
1087 .word dvmJitToInterpPunt
1089 /* ------------------------------ */
1091 .global dvmCompiler_TEMPLATE_MONITOR_ENTER
1092 dvmCompiler_TEMPLATE_MONITOR_ENTER:
1093 /* File: armv5te/TEMPLATE_MONITOR_ENTER.S */
1095 * Call out to the runtime to lock an object. Because this thread
1096 * may have been suspended in THREAD_MONITOR state and the Jit's
1097 * translation cache subsequently cleared, we cannot return directly.
1098 * Instead, unconditionally transition to the interpreter to resume.
1102 * r1 - the object (which has already been null-checked by the caller
1103 * r4 - the Dalvik PC of the following instruction.
1105 ldr r2, .LdvmLockObject
1106 mov r3, #0 @ Record that we're not returning
1107 str r3, [r0, #offThread_inJitCodeCache]
1108 blx r2 @ dvmLockObject(self, obj)
1109 @ refresh Jit's on/off status
1110 ldr r0, [rGLUE, #offGlue_ppJitProfTable]
1112 ldr r2, .LdvmJitToInterpNoChain
1113 str r0, [rGLUE, #offGlue_pJitProfTable]
1114 @ Bail to interpreter - no chain [note - r4 still contains rPC]
1115 #if defined(WITH_JIT_TUNING)
1116 mov r0, #kHeavyweightMonitor
1120 /* ------------------------------ */
1122 .global dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG
1123 dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
1124 /* File: armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S */
1126 * To support deadlock prediction, this version of MONITOR_ENTER
1127 * will always call the heavyweight dvmLockObject, check for an
1128 * exception and then bail out to the interpreter.
1132 * r1 - the object (which has already been null-checked by the caller
1133 * r4 - the Dalvik PC of the following instruction.
1136 ldr r2, .LdvmLockObject
1137 mov r3, #0 @ Record that we're not returning
1138 str r3, [r0, #offThread_inJitCodeCache]
1139 blx r2 @ dvmLockObject(self, obj)
1140 @ refresh Jit's on/off status & test for exception
1141 ldr r0, [rGLUE, #offGlue_ppJitProfTable]
1142 ldr r1, [rGLUE, #offGlue_self]
1144 ldr r1, [r1, #offThread_exception]
1145 str r0, [rGLUE, #offGlue_pJitProfTable]
1148 ldr r2, .LhandleException
1149 sub r0, r4, #2 @ roll dPC back to this monitor instruction
1152 @ Bail to interpreter - no chain [note - r4 still contains rPC]
1153 #if defined(WITH_JIT_TUNING)
1154 mov r0, #kHeavyweightMonitor
1156 ldr pc, .LdvmJitToInterpNoChain
1158 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1159 /* File: armv5te/footer.S */
1161 * ===========================================================================
1162 * Common subroutines and data
1163 * ===========================================================================
1169 @ Prep for the native call
1170 @ r1 = newFP, r0 = methodToCall
1171 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
1173 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1174 str r2, [r3, #offThread_inJitCodeCache] @ not in jit code cache
1175 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
1176 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1177 @ newFp->localRefCookie=top
1178 mov r9, r3 @ r9<- glue->self (preserve)
1179 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
1181 mov r2, r0 @ r2<- methodToCall
1182 mov r0, r1 @ r0<- newFP
1183 add r1, rGLUE, #offGlue_retval @ r1<- &retval
1185 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1187 @ Refresh Jit's on/off status
1188 ldr r3, [rGLUE, #offGlue_ppJitProfTable]
1190 @ native return; r9=self, r10=newSaveArea
1191 @ equivalent to dvmPopJniLocals
1192 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1193 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1194 ldr r1, [r9, #offThread_exception] @ check for exception
1195 ldr r3, [r3] @ r1 <- pointer to Jit profile table
1196 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
1198 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1199 ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
1200 str r3, [rGLUE, #offGlue_pJitProfTable] @ cache current JitProfTable
1202 @ r0 = dalvikCallsitePC
1203 bne .LhandleException @ no, handle exception
1205 str r2, [r9, #offThread_inJitCodeCache] @ set the new mode
1206 cmp r2, #0 @ return chaining cell still exists?
1207 bxne r2 @ yes - go ahead
1209 @ continue executing the next instruction through the interpreter
1210 ldr r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
1211 add rPC, r0, #6 @ reconstruct new rPC (advance 6 bytes)
1212 #if defined(WITH_JIT_TUNING)
1213 mov r0, #kCallsiteInterpreted
1219 * r0 Faulting Dalvik PC
1222 #if defined(WITH_SELF_VERIFICATION)
1223 ldr pc, .LdeadFood @ should not see this under self-verification mode
1227 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
1229 str r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
1230 ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1231 ldr rIBASE, .LdvmAsmInstructionStart @ same as above
1232 mov rPC, r0 @ reload the faulting Dalvik address
1233 mov pc, r1 @ branch to dvmMterpCommonExceptionThrown
1236 .LdvmAsmInstructionStart:
1237 .word dvmAsmInstructionStart
1238 .LdvmJitToInterpNoChainNoProfile:
1239 .word dvmJitToInterpNoChainNoProfile
1240 .LdvmJitToInterpTraceSelectNoChain:
1241 .word dvmJitToInterpTraceSelectNoChain
1242 .LdvmJitToInterpNoChain:
1243 .word dvmJitToInterpNoChain
1245 .word dvmMterpStdBail
1246 .LdvmMterpCommonExceptionThrown:
1247 .word dvmMterpCommonExceptionThrown
1250 #if defined(WITH_JIT_TUNING)
1252 .word gDvmICHitCount
1254 #if defined(WITH_SELF_VERIFICATION)
1255 .LdvmSelfVerificationMemOpDecode:
1256 .word dvmSelfVerificationMemOpDecode
1259 .word __aeabi_cdcmple
1261 .word __aeabi_cfcmple
1263 .global dmvCompilerTemplateEnd
1264 dmvCompilerTemplateEnd:
1266 #endif /* WITH_JIT */