blob: 801c0c7e3e1e065dea36a9014110d9b0b3d5b851 [file] [log] [blame]
Ben Chengba4fc8b2009-06-01 13:00:29 -07001/*
2 * This file was generated automatically by gen-template.py for 'armv5te'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24#if defined(WITH_JIT)
25
26/*
27 * ARMv5 definitions and declarations.
28 */
29
30/*
31ARM EABI general notes:
32
33r0-r3 hold first 4 args to a method; they are not preserved across method calls
34r4-r8 are available for general use
35r9 is given special treatment in some situations, but not for us
36r10 (sl) seems to be generally available
37r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
38r12 (ip) is scratch -- not preserved across method calls
39r13 (sp) should be managed carefully in case a signal arrives
40r14 (lr) must be preserved
41r15 (pc) can be tinkered with directly
42
43r0 holds returns of <= 4 bytes
44r0-r1 hold returns of 8 bytes, low word in r0
45
46Callee must save/restore r4+ (except r12) if it modifies them.
47
48Stack is "full descending". Only the arguments that don't fit in the first 4
49registers are placed on the stack. "sp" points at the first stacked argument
50(i.e. the 5th arg).
51
52VFP: single-precision results in s0, double-precision results in d0.
53
54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5564-bit quantities (long long, double) must be 64-bit aligned.
56*/
57
58/*
59JIT and ARM notes:
60
61The following registers have fixed assignments:
62
63 reg nick purpose
64 r5 rFP interpreted frame pointer, used for accessing locals and args
65 r6 rGLUE MterpGlue pointer
66
67The following registers have fixed assignments in mterp but are scratch
68registers in compiled code
69
70 reg nick purpose
71 r4 rPC interpreted program counter, used for fetching instructions
Andy McFadden1da12162009-06-05 16:19:13 -070072 r7 rINST first 16-bit code unit of current instruction
73 r8 rIBASE interpreted instruction base pointer, used for computed goto
Ben Chengba4fc8b2009-06-01 13:00:29 -070074
75Macros are provided for common operations. Each macro MUST emit only
76one instruction to make instruction-counting easier. They MUST NOT alter
77unspecified registers or condition codes.
78*/
79
80/* single-purpose registers, given names for clarity */
81#define rPC r4
82#define rFP r5
83#define rGLUE r6
Andy McFadden1da12162009-06-05 16:19:13 -070084#define rINST r7
85#define rIBASE r8
Ben Chengba4fc8b2009-06-01 13:00:29 -070086
87/*
88 * Given a frame pointer, find the stack save area.
89 *
90 * In C this is "((StackSaveArea*)(_fp) -1)".
91 */
92#define SAVEAREA_FROM_FP(_reg, _fpreg) \
93 sub _reg, _fpreg, #sizeofStackSaveArea
94
95/*
96 * This is a #include, not a %include, because we want the C pre-processor
97 * to expand the macros into assembler assignment statements.
98 */
99#include "../../../mterp/common/asm-constants.h"
100
101
102/* File: armv5te/platform.S */
103/*
104 * ===========================================================================
105 * CPU-version-specific defines
106 * ===========================================================================
107 */
108
109/*
110 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
111 * Jump to subroutine.
112 *
113 * May modify IP and LR.
114 */
115.macro LDR_PC_LR source
116 mov lr, pc
117 ldr pc, \source
118.endm
119
120
121 .global dvmCompilerTemplateStart
122 .type dvmCompilerTemplateStart, %function
123 .text
124
125dvmCompilerTemplateStart:
126
127/* ------------------------------ */
128 .balign 4
129 .global dvmCompiler_TEMPLATE_CMP_LONG
130dvmCompiler_TEMPLATE_CMP_LONG:
131/* File: armv5te/TEMPLATE_CMP_LONG.S */
132 /*
133 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination
134 * register based on the results of the comparison.
135 *
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.
139 *
140 * If we just wanted to set condition flags, we could do this:
141 * subs ip, r0, r2
142 * sbcs ip, r1, r3
143 * subeqs ip, r0, r2
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).
151 */
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
157 bxeq lr
158 bhi .LTEMPLATE_CMP_LONG_greater @ unsigned compare on low part
159.LTEMPLATE_CMP_LONG_less:
160 mvn r0, #0 @ r0<- -1
161 bx lr
162.LTEMPLATE_CMP_LONG_greater:
163 mov r0, #1 @ r0<- 1
164 bx lr
165
166
167/* ------------------------------ */
168 .balign 4
169 .global dvmCompiler_TEMPLATE_RETURN
170dvmCompiler_TEMPLATE_RETURN:
171/* File: armv5te/TEMPLATE_RETURN.S */
172 /*
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.
178 */
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
Jeff Hao97319a82009-08-12 16:57:15 -0700183#if !defined(WITH_SELF_VERIFICATION)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700184 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
Jeff Hao97319a82009-08-12 16:57:15 -0700185#else
186 mov r9, #0 @ disable chaining
187#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -0700188 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?
Jeff Hao97319a82009-08-12 16:57:15 -0700192#if !defined(WITH_SELF_VERIFICATION)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700193 beq 1f @ bail to interpreter
Jeff Hao97319a82009-08-12 16:57:15 -0700194#else
195 blxeq lr @ punt to interpreter and compare state
196#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -0700197 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
201
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
2121:
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
218
219/* ------------------------------ */
220 .balign 4
221 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
222dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
223/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
224 /*
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.
228 */
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
248
249
250 @ set up newSaveArea
251 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
252 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
253 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
254 cmp r8, #0 @ suspendCount != 0
255 bxne lr @ bail to the interpreter
256 tst r10, #ACC_NATIVE
Jeff Hao97319a82009-08-12 16:57:15 -0700257#if !defined(WITH_SELF_VERIFICATION)
Ben Chengba4fc8b2009-06-01 13:00:29 -0700258 bne .LinvokeNative
Jeff Hao97319a82009-08-12 16:57:15 -0700259#else
260 bxne lr @ bail to the interpreter
261#endif
Ben Chengba4fc8b2009-06-01 13:00:29 -0700262
263 ldr r10, .LdvmJitToInterpNoChain
264 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
265 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
266
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
272
273 @ Start executing the callee
274 mov pc, r10 @ dvmJitToInterpNoChain
275
276/* ------------------------------ */
277 .balign 4
278 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
279dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
280/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
281 /*
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.
285 */
286 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
Ben Cheng38329f52009-07-07 14:19:20 -0700287 @ methodToCall is guaranteed to be non-native
288.LinvokeChain:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700289 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
Ben Chengba4fc8b2009-06-01 13:00:29 -0700304 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
305 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
306 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
307
308
309 @ set up newSaveArea
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
Ben Chengba4fc8b2009-06-01 13:00:29 -0700315
316 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
317 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
318
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
324
325 bx lr @ return to the callee-chaining cell
326
327
328
329/* ------------------------------ */
330 .balign 4
Ben Cheng38329f52009-07-07 14:19:20 -0700331 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
332dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
333/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
334 /*
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.
339 *
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700340 * The predicted chaining cell is declared in ArmLIR.h with the
Ben Cheng38329f52009-07-07 14:19:20 -0700341 * following layout:
342 *
343 * typedef struct PredictedChainingCell {
344 * u4 branch;
345 * const ClassObject *clazz;
346 * const Method *method;
347 * u4 counter;
348 * } PredictedChainingCell;
349 *
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.
354 * r3 <- class
355 * r9 <- counter
356 */
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
368 /*
369 * r1 <- count
370 * r2 <- &predictedChainCell
371 * r3 <- this->class
372 * r4 <- dPC
373 * r7 <- this->class->vtable
374 */
375 bx lr
376
377/* ------------------------------ */
378 .balign 4
379 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
380dvmCompiler_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
397
398
399 @ set up newSaveArea
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
Jeff Hao97319a82009-08-12 16:57:15 -0700406#if !defined(WITH_SELF_VERIFICATION)
Ben Cheng38329f52009-07-07 14:19:20 -0700407 bxne lr @ bail to the interpreter
Jeff Hao97319a82009-08-12 16:57:15 -0700408#else
409 bx lr @ bail to interpreter unconditionally
410#endif
Ben Cheng38329f52009-07-07 14:19:20 -0700411
412 @ go ahead and transfer control to the native code
Andy McFaddend5ab7262009-08-25 07:19:34 -0700413 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
Ben Cheng38329f52009-07-07 14:19:20 -0700414 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
Andy McFaddend5ab7262009-08-25 07:19:34 -0700415 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
416 @ newFp->localRefCookie=top
Ben Cheng38329f52009-07-07 14:19:20 -0700417 mov r9, r3 @ r9<- glue->self (preserve)
418 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
419
420 mov r2, r0 @ r2<- methodToCall
421 mov r0, r1 @ r0<- newFP
422 add r1, rGLUE, #offGlue_retval @ r1<- &retval
423
424 blx r8 @ off to the native code
425
426 @ native return; r9=self, r10=newSaveArea
427 @ equivalent to dvmPopJniLocals
428 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
Andy McFaddend5ab7262009-08-25 07:19:34 -0700429 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
Ben Cheng38329f52009-07-07 14:19:20 -0700430 ldr r1, [r9, #offThread_exception] @ check for exception
431 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
432 cmp r1, #0 @ null?
Andy McFaddend5ab7262009-08-25 07:19:34 -0700433 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
Ben Cheng38329f52009-07-07 14:19:20 -0700434 bne .LhandleException @ no, handle exception
435 bx r2
436
437
438/* ------------------------------ */
439 .balign 4
Ben Chengba4fc8b2009-06-01 13:00:29 -0700440 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE
441dvmCompiler_TEMPLATE_CMPG_DOUBLE:
442/* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */
443/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
444 /*
445 * For the JIT: incoming arguments are pointers to the arguments in r0/r1
446 * result in r0
447 *
448 * Compare two floating-point values. Puts 0, 1, or -1 into the
449 * destination register based on the results of the comparison.
450 *
451 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
452 * on what value we'd like to return when one of the operands is NaN.
453 *
454 * See OP_CMPL_FLOAT for an explanation.
455 *
456 * For: cmpl-double, cmpg-double
457 */
458 /* op vAA, vBB, vCC */
459 mov r4, lr @ save return address
460 mov r9, r0 @ save copy of &arg1
461 mov r10, r1 @ save copy of &arg2
462 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
463 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
464 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple"
465 bhi .LTEMPLATE_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
466 mvncc r0, #0 @ (less than) r1<- -1
467 moveq r0, #0 @ (equal) r1<- 0, trumps less than
468 bx r4
469
470 @ Test for NaN with a second comparison. EABI forbids testing bit
471 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
472 @ make the library call.
473.LTEMPLATE_CMPG_DOUBLE_gt_or_nan:
474 ldmia r10, {r0-r1} @ reverse order
475 ldmia r9, {r2-r3}
476 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if <
477 movcc r0, #1 @ (greater than) r1<- 1
478 bxcc r4
479 mov r0, #1 @ r1<- 1 or -1 for NaN
480 bx r4
481
482
483
484/* ------------------------------ */
485 .balign 4
486 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE
487dvmCompiler_TEMPLATE_CMPL_DOUBLE:
488/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
489 /*
490 * For the JIT: incoming arguments are pointers to the arguments in r0/r1
491 * result in r0
492 *
493 * Compare two floating-point values. Puts 0, 1, or -1 into the
494 * destination register based on the results of the comparison.
495 *
496 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
497 * on what value we'd like to return when one of the operands is NaN.
498 *
499 * See OP_CMPL_FLOAT for an explanation.
500 *
501 * For: cmpl-double, cmpg-double
502 */
503 /* op vAA, vBB, vCC */
504 mov r4, lr @ save return address
505 mov r9, r0 @ save copy of &arg1
506 mov r10, r1 @ save copy of &arg2
507 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
508 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
509 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple"
510 bhi .LTEMPLATE_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
511 mvncc r0, #0 @ (less than) r1<- -1
512 moveq r0, #0 @ (equal) r1<- 0, trumps less than
513 bx r4
514
515 @ Test for NaN with a second comparison. EABI forbids testing bit
516 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
517 @ make the library call.
518.LTEMPLATE_CMPL_DOUBLE_gt_or_nan:
519 ldmia r10, {r0-r1} @ reverse order
520 ldmia r9, {r2-r3}
521 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if <
522 movcc r0, #1 @ (greater than) r1<- 1
523 bxcc r4
524 mvn r0, #0 @ r1<- 1 or -1 for NaN
525 bx r4
526
527
528/* ------------------------------ */
529 .balign 4
530 .global dvmCompiler_TEMPLATE_CMPG_FLOAT
531dvmCompiler_TEMPLATE_CMPG_FLOAT:
532/* File: armv5te/TEMPLATE_CMPG_FLOAT.S */
533/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
534 /*
535 * For the JIT: incoming arguments in r0, r1
536 * result in r0
537 *
538 * Compare two floating-point values. Puts 0, 1, or -1 into the
539 * destination register based on the results of the comparison.
540 *
541 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
542 * on what value we'd like to return when one of the operands is NaN.
543 *
544 * The operation we're implementing is:
545 * if (x == y)
546 * return 0;
547 * else if (x < y)
548 * return -1;
549 * else if (x > y)
550 * return 1;
551 * else
552 * return {-1,1}; // one or both operands was NaN
553 *
554 * The straightforward implementation requires 3 calls to functions
555 * that return a result in r0. We can do it with two calls if our
556 * EABI library supports __aeabi_cfcmple (only one if we want to check
557 * for NaN directly):
558 * check x <= y
559 * if <, return -1
560 * if ==, return 0
561 * check y <= x
562 * if <, return 1
563 * return {-1,1}
564 *
565 * for: cmpl-float, cmpg-float
566 */
567 /* op vAA, vBB, vCC */
568 mov r4, lr @ save return address
569 mov r9, r0 @ Save copies - we may need to redo
570 mov r10, r1
571 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq
572 bhi .LTEMPLATE_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
573 mvncc r0, #0 @ (less than) r0<- -1
574 moveq r0, #0 @ (equal) r0<- 0, trumps less than
575 bx r4
576 @ Test for NaN with a second comparison. EABI forbids testing bit
577 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
578 @ make the library call.
579.LTEMPLATE_CMPG_FLOAT_gt_or_nan:
580 mov r1, r9 @ reverse order
581 mov r0, r10
582 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if <
583 movcc r0, #1 @ (greater than) r1<- 1
584 bxcc r4
585 mov r0, #1 @ r1<- 1 or -1 for NaN
586 bx r4
587
588
589
590
591/* ------------------------------ */
592 .balign 4
593 .global dvmCompiler_TEMPLATE_CMPL_FLOAT
594dvmCompiler_TEMPLATE_CMPL_FLOAT:
595/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
596 /*
597 * For the JIT: incoming arguments in r0, r1
598 * result in r0
599 *
600 * Compare two floating-point values. Puts 0, 1, or -1 into the
601 * destination register based on the results of the comparison.
602 *
603 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
604 * on what value we'd like to return when one of the operands is NaN.
605 *
606 * The operation we're implementing is:
607 * if (x == y)
608 * return 0;
609 * else if (x < y)
610 * return -1;
611 * else if (x > y)
612 * return 1;
613 * else
614 * return {-1,1}; // one or both operands was NaN
615 *
616 * The straightforward implementation requires 3 calls to functions
617 * that return a result in r0. We can do it with two calls if our
618 * EABI library supports __aeabi_cfcmple (only one if we want to check
619 * for NaN directly):
620 * check x <= y
621 * if <, return -1
622 * if ==, return 0
623 * check y <= x
624 * if <, return 1
625 * return {-1,1}
626 *
627 * for: cmpl-float, cmpg-float
628 */
629 /* op vAA, vBB, vCC */
630 mov r4, lr @ save return address
631 mov r9, r0 @ Save copies - we may need to redo
632 mov r10, r1
633 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq
634 bhi .LTEMPLATE_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
635 mvncc r0, #0 @ (less than) r0<- -1
636 moveq r0, #0 @ (equal) r0<- 0, trumps less than
637 bx r4
638 @ Test for NaN with a second comparison. EABI forbids testing bit
639 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
640 @ make the library call.
641.LTEMPLATE_CMPL_FLOAT_gt_or_nan:
642 mov r1, r9 @ reverse order
643 mov r0, r10
644 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if <
645 movcc r0, #1 @ (greater than) r1<- 1
646 bxcc r4
647 mvn r0, #0 @ r1<- 1 or -1 for NaN
648 bx r4
649
650
651
652/* ------------------------------ */
653 .balign 4
654 .global dvmCompiler_TEMPLATE_MUL_LONG
655dvmCompiler_TEMPLATE_MUL_LONG:
656/* File: armv5te/TEMPLATE_MUL_LONG.S */
657 /*
658 * Signed 64-bit integer multiply.
659 *
660 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
661 *
662 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
663 * WX
664 * x YZ
665 * --------
666 * ZW ZX
667 * YW YX
668 *
669 * The low word of the result holds ZX, the high word holds
670 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
671 * it doesn't fit in the low 64 bits.
672 *
673 * Unlike most ARM math operations, multiply instructions have
674 * restrictions on using the same register more than once (Rd and Rm
675 * cannot be the same).
676 */
677 /* mul-long vAA, vBB, vCC */
678 mul ip, r2, r1 @ ip<- ZxW
679 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
680 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
681 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
682 mov r0,r9
683 mov r1,r10
684 bx lr
685
686/* ------------------------------ */
687 .balign 4
688 .global dvmCompiler_TEMPLATE_SHL_LONG
689dvmCompiler_TEMPLATE_SHL_LONG:
690/* File: armv5te/TEMPLATE_SHL_LONG.S */
691 /*
692 * Long integer shift. This is different from the generic 32/64-bit
693 * binary operations because vAA/vBB are 64-bit but vCC (the shift
694 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
695 * 6 bits.
696 */
697 /* shl-long vAA, vBB, vCC */
698 and r2, r2, #63 @ r2<- r2 & 0x3f
699 mov r1, r1, asl r2 @ r1<- r1 << r2
700 rsb r3, r2, #32 @ r3<- 32 - r2
701 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
702 subs ip, r2, #32 @ ip<- r2 - 32
703 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
704 mov r0, r0, asl r2 @ r0<- r0 << r2
705 bx lr
706
707/* ------------------------------ */
708 .balign 4
709 .global dvmCompiler_TEMPLATE_SHR_LONG
710dvmCompiler_TEMPLATE_SHR_LONG:
711/* File: armv5te/TEMPLATE_SHR_LONG.S */
712 /*
713 * Long integer shift. This is different from the generic 32/64-bit
714 * binary operations because vAA/vBB are 64-bit but vCC (the shift
715 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
716 * 6 bits.
717 */
718 /* shr-long vAA, vBB, vCC */
719 and r2, r2, #63 @ r0<- r0 & 0x3f
720 mov r0, r0, lsr r2 @ r0<- r2 >> r2
721 rsb r3, r2, #32 @ r3<- 32 - r2
722 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
723 subs ip, r2, #32 @ ip<- r2 - 32
724 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
725 mov r1, r1, asr r2 @ r1<- r1 >> r2
726 bx lr
727
728
729/* ------------------------------ */
730 .balign 4
731 .global dvmCompiler_TEMPLATE_USHR_LONG
732dvmCompiler_TEMPLATE_USHR_LONG:
733/* File: armv5te/TEMPLATE_USHR_LONG.S */
734 /*
735 * Long integer shift. This is different from the generic 32/64-bit
736 * binary operations because vAA/vBB are 64-bit but vCC (the shift
737 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
738 * 6 bits.
739 */
740 /* ushr-long vAA, vBB, vCC */
741 and r2, r2, #63 @ r0<- r0 & 0x3f
742 mov r0, r0, lsr r2 @ r0<- r2 >> r2
743 rsb r3, r2, #32 @ r3<- 32 - r2
744 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
745 subs ip, r2, #32 @ ip<- r2 - 32
746 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
747 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
748 bx lr
749
750
Ben Chengba4fc8b2009-06-01 13:00:29 -0700751 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
752/* File: armv5te/footer.S */
753/*
754 * ===========================================================================
755 * Common subroutines and data
756 * ===========================================================================
757 */
758
759 .text
760 .align 2
761.LinvokeNative:
762 @ Prep for the native call
763 @ r1 = newFP, r0 = methodToCall
764 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
Andy McFaddend5ab7262009-08-25 07:19:34 -0700765 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
Ben Chengba4fc8b2009-06-01 13:00:29 -0700766 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
Andy McFaddend5ab7262009-08-25 07:19:34 -0700767 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
768 @ newFp->localRefCookie=top
Ben Chengba4fc8b2009-06-01 13:00:29 -0700769 mov r9, r3 @ r9<- glue->self (preserve)
770 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
771
772 mov r2, r0 @ r2<- methodToCall
773 mov r0, r1 @ r0<- newFP
774 add r1, rGLUE, #offGlue_retval @ r1<- &retval
775
776 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
777
778 @ native return; r9=self, r10=newSaveArea
779 @ equivalent to dvmPopJniLocals
780 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
Andy McFaddend5ab7262009-08-25 07:19:34 -0700781 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
Ben Chengba4fc8b2009-06-01 13:00:29 -0700782 ldr r1, [r9, #offThread_exception] @ check for exception
783 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
784 cmp r1, #0 @ null?
Andy McFaddend5ab7262009-08-25 07:19:34 -0700785 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
Ben Chengba4fc8b2009-06-01 13:00:29 -0700786 bne .LhandleException @ no, handle exception
787 bx r2
788
Ben Cheng38329f52009-07-07 14:19:20 -0700789/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
Ben Chengba4fc8b2009-06-01 13:00:29 -0700790.LhandleException:
Ben Chengcc6600c2009-06-22 14:45:16 -0700791 ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
792 ldr rIBASE, .LdvmAsmInstructionStart @ same as above
Ben Chengba4fc8b2009-06-01 13:00:29 -0700793 ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
Ben Chengcc6600c2009-06-22 14:45:16 -0700794 mov pc, r0 @ branch to dvmMterpCommonExceptionThrown
Ben Chengba4fc8b2009-06-01 13:00:29 -0700795
796 .align 2
797.LdvmAsmInstructionStart:
798 .word dvmAsmInstructionStart
799.LdvmJitToInterpNoChain:
800 .word dvmJitToInterpNoChain
801.LdvmMterpStdBail:
802 .word dvmMterpStdBail
Ben Chengcc6600c2009-06-22 14:45:16 -0700803.LdvmMterpCommonExceptionThrown:
804 .word dvmMterpCommonExceptionThrown
Ben Chengba4fc8b2009-06-01 13:00:29 -0700805.L__aeabi_cdcmple:
806 .word __aeabi_cdcmple
807.L__aeabi_cfcmple:
808 .word __aeabi_cfcmple
809
810 .global dmvCompilerTemplateEnd
811dmvCompilerTemplateEnd:
812
813#endif /* WITH_JIT */
814