2 * This file was generated automatically by gen-template.py for 'armv5te-vfp'.
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 * This is a #include, not a %include, because we want the C pre-processor
97 * to expand the macros into assembler assignment statements.
99 #include "../../../mterp/common/asm-constants.h"
102 /* File: armv5te/platform.S */
104 * ===========================================================================
105 * CPU-version-specific defines
106 * ===========================================================================
110 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
111 * Jump to subroutine.
113 * May modify IP and LR.
115 .macro LDR_PC_LR source
121 .global dvmCompilerTemplateStart
122 .type dvmCompilerTemplateStart, %function
125 dvmCompilerTemplateStart:
127 /* ------------------------------ */
129 .global dvmCompiler_TEMPLATE_CMP_LONG
130 dvmCompiler_TEMPLATE_CMP_LONG:
131 /* File: armv5te/TEMPLATE_CMP_LONG.S */
133 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
134 * register based on the results of the comparison.
136 * We load the full values with LDM, but in practice many values could
137 * be resolved by only looking at the high word. This could be made
138 * faster or slower by splitting the LDM into a pair of LDRs.
140 * If we just wanted to set condition flags, we could do this:
144 * Leaving { <0, 0, >0 } in ip. However, we have to set it to a specific
145 * integer value, which we can do with 2 conditional mov/mvn instructions
146 * (set 1, set -1; if they're equal we already have 0 in ip), giving
147 * us a constant 5-cycle path plus a branch at the end to the
148 * instruction epilogue code. The multi-compare approach below needs
149 * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
150 * in the worst case (the 64-bit values are equal).
152 /* cmp-long vAA, vBB, vCC */
153 cmp r1, r3 @ compare (vBB+1, vCC+1)
154 blt .LTEMPLATE_CMP_LONG_less @ signed compare on high part
155 bgt .LTEMPLATE_CMP_LONG_greater
156 subs r0, r0, r2 @ r0<- r0 - r2
158 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part
159 .LTEMPLATE_CMP_LONG_less:
162 .LTEMPLATE_CMP_LONG_greater:
167 /* ------------------------------ */
169 .global dvmCompiler_TEMPLATE_RETURN
170 dvmCompiler_TEMPLATE_RETURN:
171 /* File: armv5te/TEMPLATE_RETURN.S */
173 * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
174 * If the stored value in returnAddr
175 * is non-zero, the caller is compiled by the JIT thus return to the
176 * address in the code cache following the invoke instruction. Otherwise
177 * return to the special dvmJitToInterpNoChain entry point.
179 SAVEAREA_FROM_FP(r0, rFP) @ r0<- saveArea (old)
180 ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
181 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
182 ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
183 #if !defined(WITH_SELF_VERIFICATION)
184 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
186 mov r9, #0 @ disable chaining
188 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
189 @ r2<- method we're returning to
190 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
191 cmp r2, #0 @ break frame?
192 #if !defined(WITH_SELF_VERIFICATION)
193 beq 1f @ bail to interpreter
195 blxeq lr @ punt to interpreter and compare state
197 ldr r0, .LdvmJitToInterpNoChain @ defined in footer.S
198 mov rFP, r10 @ publish new FP
199 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
200 ldr r8, [r8] @ r8<- suspendCount
202 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
203 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
204 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
205 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
206 str r1, [rGLUE, #offGlue_methodClassDex]
207 cmp r8, #0 @ check the suspendCount
208 movne r9, #0 @ clear the chaining cell address
209 cmp r9, #0 @ chaining cell exists?
210 blxne r9 @ jump to the chaining cell
211 mov pc, r0 @ callsite is interpreted
213 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE()
214 ldr r2, .LdvmMterpStdBail @ defined in footer.S
215 mov r1, #0 @ changeInterp = false
216 mov r0, rGLUE @ Expecting rGLUE in r0
217 blx r2 @ exit the interpreter
219 /* ------------------------------ */
221 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
222 dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
223 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
225 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
226 * into rPC then jump to dvmJitToInterpNoChain to dispatch the
227 * runtime-resolved callee.
229 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
230 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
231 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
232 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
233 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
234 add r3, r1, #1 @ Thumb addr is odd
235 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
236 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
237 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
238 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
239 ldr r8, [r8] @ r3<- suspendCount (int)
240 cmp r10, r9 @ bottom < interpStackEnd?
241 bxlt 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 @ suspendCount != 0
255 bxne lr @ bail to the interpreter
257 #if !defined(WITH_SELF_VERIFICATION)
260 bxne lr @ bail to the interpreter
263 ldr r10, .LdvmJitToInterpNoChain
264 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
265 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
267 @ Update "glue" values for the new method
268 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
269 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
270 mov rFP, r1 @ fp = newFp
271 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
273 @ Start executing the callee
274 mov pc, r10 @ dvmJitToInterpNoChain
276 /* ------------------------------ */
278 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
279 dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
280 /* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
282 * For monomorphic callsite, setup the Dalvik frame and return to the
283 * Thumb code through the link register to transfer control to the callee
284 * method through a dedicated chaining cell.
286 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
287 @ methodToCall is guaranteed to be non-native
289 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
290 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
291 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
292 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
293 add r3, r1, #1 @ Thumb addr is odd
294 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
295 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
296 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
297 add r12, lr, #2 @ setup the punt-to-interp address
298 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
299 ldr r8, [r8] @ r3<- suspendCount (int)
300 cmp r10, r9 @ bottom < interpStackEnd?
301 bxlt r12 @ return to raise stack overflow excep.
302 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
303 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
304 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
305 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
306 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
310 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
311 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
312 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
313 cmp r8, #0 @ suspendCount != 0
314 bxne r12 @ bail to the interpreter
316 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
317 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
319 @ Update "glue" values for the new method
320 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
321 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
322 mov rFP, r1 @ fp = newFp
323 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
325 bx lr @ return to the callee-chaining cell
329 /* ------------------------------ */
331 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
332 dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
333 /* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
335 * For polymorphic callsite, check whether the cached class pointer matches
336 * the current one. If so setup the Dalvik frame and return to the
337 * Thumb code through the link register to transfer control to the callee
338 * method through a dedicated chaining cell.
340 * The predicted chaining cell is declared in ArmLIR.h with the
343 * typedef struct PredictedChainingCell {
345 * const ClassObject *clazz;
346 * const Method *method;
348 * } PredictedChainingCell;
350 * Upon returning to the callsite:
351 * - lr : to branch to the chaining cell
352 * - lr+2: to punt to the interpreter
353 * - lr+4: to fully resolve the callee and may rechain.
357 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
358 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
359 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
360 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
361 ldr r9, [r2, #12] @ r9 <- predictedChainCell->counter
362 cmp r3, r8 @ predicted class == actual class?
363 beq .LinvokeChain @ predicted chain is valid
364 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
365 sub r1, r9, #1 @ count--
366 str r1, [r2, #12] @ write back to PredictedChainingCell->counter
367 add lr, lr, #4 @ return to fully-resolve landing pad
370 * r2 <- &predictedChainCell
373 * r7 <- this->class->vtable
377 /* ------------------------------ */
379 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
380 dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
381 /* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
382 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
383 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
384 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
385 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
386 add r3, r1, #1 @ Thumb addr is odd
387 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
388 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
389 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
390 ldr r8, [r8] @ r3<- suspendCount (int)
391 cmp r10, r9 @ bottom < interpStackEnd?
392 bxlt lr @ return to raise stack overflow excep.
393 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
394 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
395 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
396 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
400 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
401 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
402 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
403 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
404 cmp r8, #0 @ suspendCount != 0
405 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
406 #if !defined(WITH_SELF_VERIFICATION)
407 bxne lr @ bail to the interpreter
409 bx lr @ bail to interpreter unconditionally
412 @ go ahead and transfer control to the native code
413 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
414 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
415 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
416 @ newFp->localRefCookie=top
417 mov r9, r3 @ r9<- glue->self (preserve)
418 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
420 mov r2, r0 @ r2<- methodToCall
421 mov r0, r1 @ r0<- newFP
422 add r1, rGLUE, #offGlue_retval @ r1<- &retval
424 blx r8 @ off to the native code
426 @ native return; r9=self, r10=newSaveArea
427 @ equivalent to dvmPopJniLocals
428 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
429 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
430 ldr r1, [r9, #offThread_exception] @ check for exception
431 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
433 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
434 bne .LhandleException @ no, handle exception
438 /* ------------------------------ */
440 .global dvmCompiler_TEMPLATE_MUL_LONG
441 dvmCompiler_TEMPLATE_MUL_LONG:
442 /* File: armv5te/TEMPLATE_MUL_LONG.S */
444 * Signed 64-bit integer multiply.
446 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
448 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
455 * The low word of the result holds ZX, the high word holds
456 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
457 * it doesn't fit in the low 64 bits.
459 * Unlike most ARM math operations, multiply instructions have
460 * restrictions on using the same register more than once (Rd and Rm
461 * cannot be the same).
463 /* mul-long vAA, vBB, vCC */
464 mul ip, r2, r1 @ ip<- ZxW
465 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
466 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
467 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
472 /* ------------------------------ */
474 .global dvmCompiler_TEMPLATE_SHL_LONG
475 dvmCompiler_TEMPLATE_SHL_LONG:
476 /* File: armv5te/TEMPLATE_SHL_LONG.S */
478 * Long integer shift. This is different from the generic 32/64-bit
479 * binary operations because vAA/vBB are 64-bit but vCC (the shift
480 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
483 /* shl-long vAA, vBB, vCC */
484 and r2, r2, #63 @ r2<- r2 & 0x3f
485 mov r1, r1, asl r2 @ r1<- r1 << r2
486 rsb r3, r2, #32 @ r3<- 32 - r2
487 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
488 subs ip, r2, #32 @ ip<- r2 - 32
489 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
490 mov r0, r0, asl r2 @ r0<- r0 << r2
493 /* ------------------------------ */
495 .global dvmCompiler_TEMPLATE_SHR_LONG
496 dvmCompiler_TEMPLATE_SHR_LONG:
497 /* File: armv5te/TEMPLATE_SHR_LONG.S */
499 * Long integer shift. This is different from the generic 32/64-bit
500 * binary operations because vAA/vBB are 64-bit but vCC (the shift
501 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
504 /* shr-long vAA, vBB, vCC */
505 and r2, r2, #63 @ r0<- r0 & 0x3f
506 mov r0, r0, lsr r2 @ r0<- r2 >> r2
507 rsb r3, r2, #32 @ r3<- 32 - r2
508 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
509 subs ip, r2, #32 @ ip<- r2 - 32
510 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
511 mov r1, r1, asr r2 @ r1<- r1 >> r2
515 /* ------------------------------ */
517 .global dvmCompiler_TEMPLATE_USHR_LONG
518 dvmCompiler_TEMPLATE_USHR_LONG:
519 /* File: armv5te/TEMPLATE_USHR_LONG.S */
521 * Long integer shift. This is different from the generic 32/64-bit
522 * binary operations because vAA/vBB are 64-bit but vCC (the shift
523 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
526 /* ushr-long vAA, vBB, vCC */
527 and r2, r2, #63 @ r0<- r0 & 0x3f
528 mov r0, r0, lsr r2 @ r0<- r2 >> r2
529 rsb r3, r2, #32 @ r3<- 32 - r2
530 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
531 subs ip, r2, #32 @ ip<- r2 - 32
532 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
533 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
537 /* ------------------------------ */
539 .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
540 dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
541 /* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
542 /* File: armv5te-vfp/fbinop.S */
544 * Generic 32-bit floating point operation. Provide an "instr" line that
545 * specifies an instruction that performs s2 = s0 op s1.
548 * r0 = target dalvik register address
559 /* ------------------------------ */
561 .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
562 dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
563 /* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
564 /* File: armv5te-vfp/fbinop.S */
566 * Generic 32-bit floating point operation. Provide an "instr" line that
567 * specifies an instruction that performs s2 = s0 op s1.
570 * r0 = target dalvik register address
581 /* ------------------------------ */
583 .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
584 dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
585 /* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
586 /* File: armv5te-vfp/fbinop.S */
588 * Generic 32-bit floating point operation. Provide an "instr" line that
589 * specifies an instruction that performs s2 = s0 op s1.
592 * r0 = target dalvik register address
603 /* ------------------------------ */
605 .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
606 dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
607 /* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
608 /* File: armv5te-vfp/fbinop.S */
610 * Generic 32-bit floating point operation. Provide an "instr" line that
611 * specifies an instruction that performs s2 = s0 op s1.
614 * r0 = target dalvik register address
625 /* ------------------------------ */
627 .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
628 dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
629 /* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
630 /* File: armv5te-vfp/fbinopWide.S */
632 * Generic 64-bit floating point operation. Provide an "instr" line that
633 * specifies an instruction that performs s2 = s0 op s1.
636 * r0 = target dalvik register address
647 /* ------------------------------ */
649 .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
650 dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
651 /* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
652 /* File: armv5te-vfp/fbinopWide.S */
654 * Generic 64-bit floating point operation. Provide an "instr" line that
655 * specifies an instruction that performs s2 = s0 op s1.
658 * r0 = target dalvik register address
669 /* ------------------------------ */
671 .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
672 dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
673 /* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
674 /* File: armv5te-vfp/fbinopWide.S */
676 * Generic 64-bit floating point operation. Provide an "instr" line that
677 * specifies an instruction that performs s2 = s0 op s1.
680 * r0 = target dalvik register address
691 /* ------------------------------ */
693 .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
694 dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
695 /* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
696 /* File: armv5te-vfp/fbinopWide.S */
698 * Generic 64-bit floating point operation. Provide an "instr" line that
699 * specifies an instruction that performs s2 = s0 op s1.
702 * r0 = target dalvik register address
713 /* ------------------------------ */
715 .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
716 dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
717 /* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
718 /* File: armv5te-vfp/funopNarrower.S */
720 * Generic 64bit-to-32bit floating point unary operation. Provide an
721 * "instr" line that specifies an instruction that performs "s0 = op d0".
723 * For: double-to-int, double-to-float
726 * r0 = target dalvik register address
727 * r1 = src dalvik register address
730 fldd d0, [r1] @ d0<- vB
731 fcvtsd s0, d0 @ s0<- op d0
732 fsts s0, [r0] @ vA<- s0
736 /* ------------------------------ */
738 .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
739 dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
740 /* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
741 /* File: armv5te-vfp/funopNarrower.S */
743 * Generic 64bit-to-32bit floating point unary operation. Provide an
744 * "instr" line that specifies an instruction that performs "s0 = op d0".
746 * For: double-to-int, double-to-float
749 * r0 = target dalvik register address
750 * r1 = src dalvik register address
753 fldd d0, [r1] @ d0<- vB
754 ftosizd s0, d0 @ s0<- op d0
755 fsts s0, [r0] @ vA<- s0
759 /* ------------------------------ */
761 .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
762 dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
763 /* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
764 /* File: armv5te-vfp/funopWider.S */
766 * Generic 32bit-to-64bit floating point unary operation. Provide an
767 * "instr" line that specifies an instruction that performs "d0 = op s0".
769 * For: int-to-double, float-to-double
772 * r0 = target dalvik register address
773 * r1 = src dalvik register address
776 flds s0, [r1] @ s0<- vB
777 fcvtds d0, s0 @ d0<- op s0
778 fstd d0, [r0] @ vA<- d0
782 /* ------------------------------ */
784 .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
785 dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
786 /* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
787 /* File: armv5te-vfp/funop.S */
789 * Generic 32bit-to-32bit floating point unary operation. Provide an
790 * "instr" line that specifies an instruction that performs "s1 = op s0".
792 * For: float-to-int, int-to-float
795 * r0 = target dalvik register address
796 * r1 = src dalvik register address
799 flds s0, [r1] @ s0<- vB
800 ftosizs s1, s0 @ s1<- op s0
801 fsts s1, [r0] @ vA<- s1
805 /* ------------------------------ */
807 .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
808 dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
809 /* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
810 /* File: armv5te-vfp/funopWider.S */
812 * Generic 32bit-to-64bit floating point unary operation. Provide an
813 * "instr" line that specifies an instruction that performs "d0 = op s0".
815 * For: int-to-double, float-to-double
818 * r0 = target dalvik register address
819 * r1 = src dalvik register address
822 flds s0, [r1] @ s0<- vB
823 fsitod d0, s0 @ d0<- op s0
824 fstd d0, [r0] @ vA<- d0
828 /* ------------------------------ */
830 .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
831 dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
832 /* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
833 /* File: armv5te-vfp/funop.S */
835 * Generic 32bit-to-32bit floating point unary operation. Provide an
836 * "instr" line that specifies an instruction that performs "s1 = op s0".
838 * For: float-to-int, int-to-float
841 * r0 = target dalvik register address
842 * r1 = src dalvik register address
845 flds s0, [r1] @ s0<- vB
846 fsitos s1, s0 @ s1<- op s0
847 fsts s1, [r0] @ vA<- s1
851 /* ------------------------------ */
853 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
854 dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
855 /* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
857 * Compare two floating-point values. Puts 0, 1, or -1 into the
858 * destination register based on the results of the comparison.
860 * int compare(x, y) {
863 * } else if (x < y) {
865 * } else if (x > y) {
876 /* op vAA, vBB, vCC */
877 fldd d0, [r0] @ d0<- vBB
878 fldd d1, [r1] @ d1<- vCC
879 fcmped d0, d1 @ compare (vBB, vCC)
880 mov r0, #1 @ r0<- 1 (default)
881 fmstat @ export status flags
882 mvnmi r0, #0 @ (less than) r0<- -1
883 moveq r0, #0 @ (equal) r0<- 0
887 /* ------------------------------ */
889 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
890 dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
891 /* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
893 * Compare two floating-point values. Puts 0, 1, or -1 into the
894 * destination register based on the results of the comparison.
896 * int compare(x, y) {
899 * } else if (x > y) {
901 * } else if (x < y) {
911 /* op vAA, vBB, vCC */
912 fldd d0, [r0] @ d0<- vBB
913 fldd d1, [r1] @ d1<- vCC
914 fcmped d0, d1 @ compare (vBB, vCC)
915 mvn r0, #0 @ r0<- -1 (default)
916 fmstat @ export status flags
917 movgt r0, #1 @ (greater than) r0<- 1
918 moveq r0, #0 @ (equal) r0<- 0
921 /* ------------------------------ */
923 .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
924 dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
925 /* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
927 * Compare two floating-point values. Puts 0, 1, or -1 into the
928 * destination register based on the results of the comparison.
930 * int compare(x, y) {
933 * } else if (x < y) {
935 * } else if (x > y) {
945 /* op vAA, vBB, vCC */
946 flds s0, [r0] @ d0<- vBB
947 flds s1, [r1] @ d1<- vCC
948 fcmpes s0, s1 @ compare (vBB, vCC)
949 mov r0, #1 @ r0<- 1 (default)
950 fmstat @ export status flags
951 mvnmi r0, #0 @ (less than) r0<- -1
952 moveq r0, #0 @ (equal) r0<- 0
955 /* ------------------------------ */
957 .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
958 dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
959 /* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
961 * Compare two floating-point values. Puts 0, 1, or -1 into the
962 * destination register based on the results of the comparison.
964 * int compare(x, y) {
967 * } else if (x > y) {
969 * } else if (x < y) {
979 /* op vAA, vBB, vCC */
980 flds s0, [r0] @ d0<- vBB
981 flds s1, [r1] @ d1<- vCC
982 fcmpes s0, s1 @ compare (vBB, vCC)
983 mvn r0, #0 @ r0<- -1 (default)
984 fmstat @ export status flags
985 movgt r0, #1 @ (greater than) r0<- 1
986 moveq r0, #0 @ (equal) r0<- 0
989 /* ------------------------------ */
991 .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
992 dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
993 /* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
995 * 64-bit floating point vfp sqrt operation.
996 * If the result is a NaN, bail out to library code to do
1000 * r2 src addr of op1
1009 bxeq lr @ Result OK - return
1011 fmrrd r0, r1, d0 @ reload orig operand
1012 bx r2 @ tail call to sqrt library routine
1017 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
1018 /* File: armv5te/footer.S */
1020 * ===========================================================================
1021 * Common subroutines and data
1022 * ===========================================================================
1028 @ Prep for the native call
1029 @ r1 = newFP, r0 = methodToCall
1030 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
1031 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
1032 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
1033 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
1034 @ newFp->localRefCookie=top
1035 mov r9, r3 @ r9<- glue->self (preserve)
1036 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
1038 mov r2, r0 @ r2<- methodToCall
1039 mov r0, r1 @ r0<- newFP
1040 add r1, rGLUE, #offGlue_retval @ r1<- &retval
1042 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
1044 @ native return; r9=self, r10=newSaveArea
1045 @ equivalent to dvmPopJniLocals
1046 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
1047 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
1048 ldr r1, [r9, #offThread_exception] @ check for exception
1049 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
1051 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
1052 bne .LhandleException @ no, handle exception
1055 /* NOTE - this path can be exercised if the JIT threshold is set to 5 */
1057 ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
1058 ldr rIBASE, .LdvmAsmInstructionStart @ same as above
1059 ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
1060 mov pc, r0 @ branch to dvmMterpCommonExceptionThrown
1063 .LdvmAsmInstructionStart:
1064 .word dvmAsmInstructionStart
1065 .LdvmJitToInterpNoChain:
1066 .word dvmJitToInterpNoChain
1068 .word dvmMterpStdBail
1069 .LdvmMterpCommonExceptionThrown:
1070 .word dvmMterpCommonExceptionThrown
1072 .word __aeabi_cdcmple
1074 .word __aeabi_cfcmple
1076 .global dmvCompilerTemplateEnd
1077 dmvCompilerTemplateEnd:
1079 #endif /* WITH_JIT */