blob: 29dde742215d7595a76df61fdae3b8a197019733 [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
183 ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
184 ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
185 @ r2<- method we're returning to
186 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
187 cmp r2, #0 @ break frame?
188 beq 1f @ bail to interpreter
189 ldr r0, .LdvmJitToInterpNoChain @ defined in footer.S
190 mov rFP, r10 @ publish new FP
191 ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
192 ldr r8, [r8] @ r8<- suspendCount
193
194 str r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
195 ldr r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
196 str rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
197 add rPC, rPC, #6 @ publish new rPC (advance 6 bytes)
198 str r1, [rGLUE, #offGlue_methodClassDex]
199 cmp r8, #0 @ check the suspendCount
200 movne r9, #0 @ clear the chaining cell address
201 cmp r9, #0 @ chaining cell exists?
202 blxne r9 @ jump to the chaining cell
203 mov pc, r0 @ callsite is interpreted
2041:
205 stmia rGLUE, {rPC, rFP} @ SAVE_PC_FP_TO_GLUE()
206 ldr r2, .LdvmMterpStdBail @ defined in footer.S
207 mov r1, #0 @ changeInterp = false
208 mov r0, rGLUE @ Expecting rGLUE in r0
209 blx r2 @ exit the interpreter
210
211/* ------------------------------ */
212 .balign 4
213 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
214dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
215/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
216 /*
217 * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
218 * into rPC then jump to dvmJitToInterpNoChain to dispatch the
219 * runtime-resolved callee.
220 */
221 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
222 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
223 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
224 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
225 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
226 add r3, r1, #1 @ Thumb addr is odd
227 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
228 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
229 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
230 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
231 ldr r8, [r8] @ r3<- suspendCount (int)
232 cmp r10, r9 @ bottom < interpStackEnd?
233 bxlt lr @ return to raise stack overflow excep.
234 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
235 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
236 ldr r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
237 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
238 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
239 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
240
241
242 @ set up newSaveArea
243 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
244 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
245 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
246 cmp r8, #0 @ suspendCount != 0
247 bxne lr @ bail to the interpreter
248 tst r10, #ACC_NATIVE
249 bne .LinvokeNative
Ben Chengba4fc8b2009-06-01 13:00:29 -0700250
251 ldr r10, .LdvmJitToInterpNoChain
252 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
253 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
254
255 @ Update "glue" values for the new method
256 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
257 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
258 mov rFP, r1 @ fp = newFp
259 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
260
261 @ Start executing the callee
262 mov pc, r10 @ dvmJitToInterpNoChain
263
264/* ------------------------------ */
265 .balign 4
266 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
267dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
268/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
269 /*
270 * For monomorphic callsite, setup the Dalvik frame and return to the
271 * Thumb code through the link register to transfer control to the callee
272 * method through a dedicated chaining cell.
273 */
274 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
Ben Cheng38329f52009-07-07 14:19:20 -0700275 @ methodToCall is guaranteed to be non-native
276.LinvokeChain:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700277 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
278 ldrh r2, [r0, #offMethod_outsSize] @ r2<- methodToCall->outsSize
279 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
280 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
281 add r3, r1, #1 @ Thumb addr is odd
282 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
283 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
284 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
285 add r12, lr, #2 @ setup the punt-to-interp address
286 sub r10, r10, r2, lsl #2 @ r10<- bottom (newsave - outsSize)
287 ldr r8, [r8] @ r3<- suspendCount (int)
288 cmp r10, r9 @ bottom < interpStackEnd?
289 bxlt r12 @ return to raise stack overflow excep.
290 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
291 ldr r9, [r0, #offMethod_clazz] @ r9<- method->clazz
Ben Chengba4fc8b2009-06-01 13:00:29 -0700292 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
293 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
294 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
295
296
297 @ set up newSaveArea
298 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
299 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
300 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
301 cmp r8, #0 @ suspendCount != 0
302 bxne r12 @ bail to the interpreter
Ben Chengba4fc8b2009-06-01 13:00:29 -0700303
304 ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
305 ldr r2, [rGLUE, #offGlue_self] @ r2<- glue->self
306
307 @ Update "glue" values for the new method
308 str r0, [rGLUE, #offGlue_method] @ glue->method = methodToCall
309 str r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
310 mov rFP, r1 @ fp = newFp
311 str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
312
313 bx lr @ return to the callee-chaining cell
314
315
316
317/* ------------------------------ */
318 .balign 4
Ben Cheng38329f52009-07-07 14:19:20 -0700319 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
320dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
321/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
322 /*
323 * For polymorphic callsite, check whether the cached class pointer matches
324 * the current one. If so setup the Dalvik frame and return to the
325 * Thumb code through the link register to transfer control to the callee
326 * method through a dedicated chaining cell.
327 *
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700328 * The predicted chaining cell is declared in ArmLIR.h with the
Ben Cheng38329f52009-07-07 14:19:20 -0700329 * following layout:
330 *
331 * typedef struct PredictedChainingCell {
332 * u4 branch;
333 * const ClassObject *clazz;
334 * const Method *method;
335 * u4 counter;
336 * } PredictedChainingCell;
337 *
338 * Upon returning to the callsite:
339 * - lr : to branch to the chaining cell
340 * - lr+2: to punt to the interpreter
341 * - lr+4: to fully resolve the callee and may rechain.
342 * r3 <- class
343 * r9 <- counter
344 */
345 @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
346 ldr r3, [r0, #offObject_clazz] @ r3 <- this->class
347 ldr r8, [r2, #4] @ r8 <- predictedChainCell->clazz
348 ldr r0, [r2, #8] @ r0 <- predictedChainCell->method
349 ldr r9, [r2, #12] @ r9 <- predictedChainCell->counter
350 cmp r3, r8 @ predicted class == actual class?
351 beq .LinvokeChain @ predicted chain is valid
352 ldr r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
353 sub r1, r9, #1 @ count--
354 str r1, [r2, #12] @ write back to PredictedChainingCell->counter
355 add lr, lr, #4 @ return to fully-resolve landing pad
356 /*
357 * r1 <- count
358 * r2 <- &predictedChainCell
359 * r3 <- this->class
360 * r4 <- dPC
361 * r7 <- this->class->vtable
362 */
363 bx lr
364
365/* ------------------------------ */
366 .balign 4
367 .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
368dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
369/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
370 @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
371 ldrh r7, [r0, #offMethod_registersSize] @ r7<- methodToCall->regsSize
372 ldr r9, [rGLUE, #offGlue_interpStackEnd] @ r9<- interpStackEnd
373 ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
374 add r3, r1, #1 @ Thumb addr is odd
375 SAVEAREA_FROM_FP(r1, rFP) @ r1<- stack save area
376 sub r1, r1, r7, lsl #2 @ r1<- newFp (old savearea - regsSize)
377 SAVEAREA_FROM_FP(r10, r1) @ r10<- stack save area
378 ldr r8, [r8] @ r3<- suspendCount (int)
379 cmp r10, r9 @ bottom < interpStackEnd?
380 bxlt lr @ return to raise stack overflow excep.
381 @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
382 str rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
383 str rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
384 ldr rPC, [r0, #offMethod_insns] @ rPC<- methodToCall->insns
385
386
387 @ set up newSaveArea
388 str rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
389 str r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
390 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
391 str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
392 cmp r8, #0 @ suspendCount != 0
393 ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
394 bxne lr @ bail to the interpreter
395
396 @ go ahead and transfer control to the native code
Andy McFaddend5ab7262009-08-25 07:19:34 -0700397 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
Ben Cheng38329f52009-07-07 14:19:20 -0700398 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
Andy McFaddend5ab7262009-08-25 07:19:34 -0700399 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
400 @ newFp->localRefCookie=top
Ben Cheng38329f52009-07-07 14:19:20 -0700401 mov r9, r3 @ r9<- glue->self (preserve)
402 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
403
404 mov r2, r0 @ r2<- methodToCall
405 mov r0, r1 @ r0<- newFP
406 add r1, rGLUE, #offGlue_retval @ r1<- &retval
407
408 blx r8 @ off to the native code
409
410 @ native return; r9=self, r10=newSaveArea
411 @ equivalent to dvmPopJniLocals
412 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
Andy McFaddend5ab7262009-08-25 07:19:34 -0700413 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
Ben Cheng38329f52009-07-07 14:19:20 -0700414 ldr r1, [r9, #offThread_exception] @ check for exception
415 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
416 cmp r1, #0 @ null?
Andy McFaddend5ab7262009-08-25 07:19:34 -0700417 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
Ben Cheng38329f52009-07-07 14:19:20 -0700418 bne .LhandleException @ no, handle exception
419 bx r2
420
421
422/* ------------------------------ */
423 .balign 4
Ben Chengba4fc8b2009-06-01 13:00:29 -0700424 .global dvmCompiler_TEMPLATE_CMPG_DOUBLE
425dvmCompiler_TEMPLATE_CMPG_DOUBLE:
426/* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */
427/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
428 /*
429 * For the JIT: incoming arguments are pointers to the arguments in r0/r1
430 * result in r0
431 *
432 * Compare two floating-point values. Puts 0, 1, or -1 into the
433 * destination register based on the results of the comparison.
434 *
435 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
436 * on what value we'd like to return when one of the operands is NaN.
437 *
438 * See OP_CMPL_FLOAT for an explanation.
439 *
440 * For: cmpl-double, cmpg-double
441 */
442 /* op vAA, vBB, vCC */
443 mov r4, lr @ save return address
444 mov r9, r0 @ save copy of &arg1
445 mov r10, r1 @ save copy of &arg2
446 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
447 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
448 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple"
449 bhi .LTEMPLATE_CMPG_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
450 mvncc r0, #0 @ (less than) r1<- -1
451 moveq r0, #0 @ (equal) r1<- 0, trumps less than
452 bx r4
453
454 @ Test for NaN with a second comparison. EABI forbids testing bit
455 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
456 @ make the library call.
457.LTEMPLATE_CMPG_DOUBLE_gt_or_nan:
458 ldmia r10, {r0-r1} @ reverse order
459 ldmia r9, {r2-r3}
460 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if <
461 movcc r0, #1 @ (greater than) r1<- 1
462 bxcc r4
463 mov r0, #1 @ r1<- 1 or -1 for NaN
464 bx r4
465
466
467
468/* ------------------------------ */
469 .balign 4
470 .global dvmCompiler_TEMPLATE_CMPL_DOUBLE
471dvmCompiler_TEMPLATE_CMPL_DOUBLE:
472/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
473 /*
474 * For the JIT: incoming arguments are pointers to the arguments in r0/r1
475 * result in r0
476 *
477 * Compare two floating-point values. Puts 0, 1, or -1 into the
478 * destination register based on the results of the comparison.
479 *
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.
482 *
483 * See OP_CMPL_FLOAT for an explanation.
484 *
485 * For: cmpl-double, cmpg-double
486 */
487 /* op vAA, vBB, vCC */
488 mov r4, lr @ save return address
489 mov r9, r0 @ save copy of &arg1
490 mov r10, r1 @ save copy of &arg2
491 ldmia r9, {r0-r1} @ r0/r1<- vBB/vBB+1
492 ldmia r10, {r2-r3} @ r2/r3<- vCC/vCC+1
493 LDR_PC_LR ".L__aeabi_cdcmple" @ PIC way of "bl __aeabi_cdcmple"
494 bhi .LTEMPLATE_CMPL_DOUBLE_gt_or_nan @ C set and Z clear, disambiguate
495 mvncc r0, #0 @ (less than) r1<- -1
496 moveq r0, #0 @ (equal) r1<- 0, trumps less than
497 bx r4
498
499 @ Test for NaN with a second comparison. EABI forbids testing bit
500 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
501 @ make the library call.
502.LTEMPLATE_CMPL_DOUBLE_gt_or_nan:
503 ldmia r10, {r0-r1} @ reverse order
504 ldmia r9, {r2-r3}
505 LDR_PC_LR ".L__aeabi_cdcmple" @ r0<- Z set if eq, C clear if <
506 movcc r0, #1 @ (greater than) r1<- 1
507 bxcc r4
508 mvn r0, #0 @ r1<- 1 or -1 for NaN
509 bx r4
510
511
512/* ------------------------------ */
513 .balign 4
514 .global dvmCompiler_TEMPLATE_CMPG_FLOAT
515dvmCompiler_TEMPLATE_CMPG_FLOAT:
516/* File: armv5te/TEMPLATE_CMPG_FLOAT.S */
517/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
518 /*
519 * For the JIT: incoming arguments in r0, r1
520 * result in r0
521 *
522 * Compare two floating-point values. Puts 0, 1, or -1 into the
523 * destination register based on the results of the comparison.
524 *
525 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
526 * on what value we'd like to return when one of the operands is NaN.
527 *
528 * The operation we're implementing is:
529 * if (x == y)
530 * return 0;
531 * else if (x < y)
532 * return -1;
533 * else if (x > y)
534 * return 1;
535 * else
536 * return {-1,1}; // one or both operands was NaN
537 *
538 * The straightforward implementation requires 3 calls to functions
539 * that return a result in r0. We can do it with two calls if our
540 * EABI library supports __aeabi_cfcmple (only one if we want to check
541 * for NaN directly):
542 * check x <= y
543 * if <, return -1
544 * if ==, return 0
545 * check y <= x
546 * if <, return 1
547 * return {-1,1}
548 *
549 * for: cmpl-float, cmpg-float
550 */
551 /* op vAA, vBB, vCC */
552 mov r4, lr @ save return address
553 mov r9, r0 @ Save copies - we may need to redo
554 mov r10, r1
555 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq
556 bhi .LTEMPLATE_CMPG_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
557 mvncc r0, #0 @ (less than) r0<- -1
558 moveq r0, #0 @ (equal) r0<- 0, trumps less than
559 bx r4
560 @ Test for NaN with a second comparison. EABI forbids testing bit
561 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
562 @ make the library call.
563.LTEMPLATE_CMPG_FLOAT_gt_or_nan:
564 mov r1, r9 @ reverse order
565 mov r0, r10
566 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if <
567 movcc r0, #1 @ (greater than) r1<- 1
568 bxcc r4
569 mov r0, #1 @ r1<- 1 or -1 for NaN
570 bx r4
571
572
573
574
575/* ------------------------------ */
576 .balign 4
577 .global dvmCompiler_TEMPLATE_CMPL_FLOAT
578dvmCompiler_TEMPLATE_CMPL_FLOAT:
579/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
580 /*
581 * For the JIT: incoming arguments in r0, r1
582 * result in r0
583 *
584 * Compare two floating-point values. Puts 0, 1, or -1 into the
585 * destination register based on the results of the comparison.
586 *
587 * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
588 * on what value we'd like to return when one of the operands is NaN.
589 *
590 * The operation we're implementing is:
591 * if (x == y)
592 * return 0;
593 * else if (x < y)
594 * return -1;
595 * else if (x > y)
596 * return 1;
597 * else
598 * return {-1,1}; // one or both operands was NaN
599 *
600 * The straightforward implementation requires 3 calls to functions
601 * that return a result in r0. We can do it with two calls if our
602 * EABI library supports __aeabi_cfcmple (only one if we want to check
603 * for NaN directly):
604 * check x <= y
605 * if <, return -1
606 * if ==, return 0
607 * check y <= x
608 * if <, return 1
609 * return {-1,1}
610 *
611 * for: cmpl-float, cmpg-float
612 */
613 /* op vAA, vBB, vCC */
614 mov r4, lr @ save return address
615 mov r9, r0 @ Save copies - we may need to redo
616 mov r10, r1
617 LDR_PC_LR ".L__aeabi_cfcmple" @ cmp <=: C clear if <, Z set if eq
618 bhi .LTEMPLATE_CMPL_FLOAT_gt_or_nan @ C set and Z clear, disambiguate
619 mvncc r0, #0 @ (less than) r0<- -1
620 moveq r0, #0 @ (equal) r0<- 0, trumps less than
621 bx r4
622 @ Test for NaN with a second comparison. EABI forbids testing bit
623 @ patterns, and we can't represent 0x7fc00000 in immediate form, so
624 @ make the library call.
625.LTEMPLATE_CMPL_FLOAT_gt_or_nan:
626 mov r1, r9 @ reverse order
627 mov r0, r10
628 LDR_PC_LR ".L__aeabi_cfcmple" @ r0<- Z set if eq, C clear if <
629 movcc r0, #1 @ (greater than) r1<- 1
630 bxcc r4
631 mvn r0, #0 @ r1<- 1 or -1 for NaN
632 bx r4
633
634
635
636/* ------------------------------ */
637 .balign 4
638 .global dvmCompiler_TEMPLATE_MUL_LONG
639dvmCompiler_TEMPLATE_MUL_LONG:
640/* File: armv5te/TEMPLATE_MUL_LONG.S */
641 /*
642 * Signed 64-bit integer multiply.
643 *
644 * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
645 *
646 * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
647 * WX
648 * x YZ
649 * --------
650 * ZW ZX
651 * YW YX
652 *
653 * The low word of the result holds ZX, the high word holds
654 * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because
655 * it doesn't fit in the low 64 bits.
656 *
657 * Unlike most ARM math operations, multiply instructions have
658 * restrictions on using the same register more than once (Rd and Rm
659 * cannot be the same).
660 */
661 /* mul-long vAA, vBB, vCC */
662 mul ip, r2, r1 @ ip<- ZxW
663 umull r9, r10, r2, r0 @ r9/r10 <- ZxX
664 mla r2, r0, r3, ip @ r2<- YxX + (ZxW)
665 add r10, r2, r10 @ r10<- r10 + low(ZxW + (YxX))
666 mov r0,r9
667 mov r1,r10
668 bx lr
669
670/* ------------------------------ */
671 .balign 4
672 .global dvmCompiler_TEMPLATE_SHL_LONG
673dvmCompiler_TEMPLATE_SHL_LONG:
674/* File: armv5te/TEMPLATE_SHL_LONG.S */
675 /*
676 * Long integer shift. This is different from the generic 32/64-bit
677 * binary operations because vAA/vBB are 64-bit but vCC (the shift
678 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
679 * 6 bits.
680 */
681 /* shl-long vAA, vBB, vCC */
682 and r2, r2, #63 @ r2<- r2 & 0x3f
683 mov r1, r1, asl r2 @ r1<- r1 << r2
684 rsb r3, r2, #32 @ r3<- 32 - r2
685 orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2))
686 subs ip, r2, #32 @ ip<- r2 - 32
687 movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32)
688 mov r0, r0, asl r2 @ r0<- r0 << r2
689 bx lr
690
691/* ------------------------------ */
692 .balign 4
693 .global dvmCompiler_TEMPLATE_SHR_LONG
694dvmCompiler_TEMPLATE_SHR_LONG:
695/* File: armv5te/TEMPLATE_SHR_LONG.S */
696 /*
697 * Long integer shift. This is different from the generic 32/64-bit
698 * binary operations because vAA/vBB are 64-bit but vCC (the shift
699 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
700 * 6 bits.
701 */
702 /* shr-long vAA, vBB, vCC */
703 and r2, r2, #63 @ r0<- r0 & 0x3f
704 mov r0, r0, lsr r2 @ r0<- r2 >> r2
705 rsb r3, r2, #32 @ r3<- 32 - r2
706 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
707 subs ip, r2, #32 @ ip<- r2 - 32
708 movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32)
709 mov r1, r1, asr r2 @ r1<- r1 >> r2
710 bx lr
711
712
713/* ------------------------------ */
714 .balign 4
715 .global dvmCompiler_TEMPLATE_USHR_LONG
716dvmCompiler_TEMPLATE_USHR_LONG:
717/* File: armv5te/TEMPLATE_USHR_LONG.S */
718 /*
719 * Long integer shift. This is different from the generic 32/64-bit
720 * binary operations because vAA/vBB are 64-bit but vCC (the shift
721 * distance) is 32-bit. Also, Dalvik requires us to ignore all but the low
722 * 6 bits.
723 */
724 /* ushr-long vAA, vBB, vCC */
725 and r2, r2, #63 @ r0<- r0 & 0x3f
726 mov r0, r0, lsr r2 @ r0<- r2 >> r2
727 rsb r3, r2, #32 @ r3<- 32 - r2
728 orr r0, r0, r1, asl r3 @ r0<- r0 | (r1 << (32-r2))
729 subs ip, r2, #32 @ ip<- r2 - 32
730 movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32)
731 mov r1, r1, lsr r2 @ r1<- r1 >>> r2
732 bx lr
733
734
Ben Chengba4fc8b2009-06-01 13:00:29 -0700735 .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
736/* File: armv5te/footer.S */
737/*
738 * ===========================================================================
739 * Common subroutines and data
740 * ===========================================================================
741 */
742
743 .text
744 .align 2
745.LinvokeNative:
746 @ Prep for the native call
747 @ r1 = newFP, r0 = methodToCall
748 ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
Andy McFaddend5ab7262009-08-25 07:19:34 -0700749 ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
Ben Chengba4fc8b2009-06-01 13:00:29 -0700750 str r1, [r3, #offThread_curFrame] @ self->curFrame = newFp
Andy McFaddend5ab7262009-08-25 07:19:34 -0700751 str r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
752 @ newFp->localRefCookie=top
Ben Chengba4fc8b2009-06-01 13:00:29 -0700753 mov r9, r3 @ r9<- glue->self (preserve)
754 SAVEAREA_FROM_FP(r10, r1) @ r10<- new stack save area
755
756 mov r2, r0 @ r2<- methodToCall
757 mov r0, r1 @ r0<- newFP
758 add r1, rGLUE, #offGlue_retval @ r1<- &retval
759
760 LDR_PC_LR "[r2, #offMethod_nativeFunc]"
761
762 @ native return; r9=self, r10=newSaveArea
763 @ equivalent to dvmPopJniLocals
764 ldr r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
Andy McFaddend5ab7262009-08-25 07:19:34 -0700765 ldr r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
Ben Chengba4fc8b2009-06-01 13:00:29 -0700766 ldr r1, [r9, #offThread_exception] @ check for exception
767 str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
768 cmp r1, #0 @ null?
Andy McFaddend5ab7262009-08-25 07:19:34 -0700769 str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
Ben Chengba4fc8b2009-06-01 13:00:29 -0700770 bne .LhandleException @ no, handle exception
771 bx r2
772
Ben Cheng38329f52009-07-07 14:19:20 -0700773/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
Ben Chengba4fc8b2009-06-01 13:00:29 -0700774.LhandleException:
Ben Chengcc6600c2009-06-22 14:45:16 -0700775 ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
776 ldr rIBASE, .LdvmAsmInstructionStart @ same as above
Ben Chengba4fc8b2009-06-01 13:00:29 -0700777 ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
Ben Chengcc6600c2009-06-22 14:45:16 -0700778 mov pc, r0 @ branch to dvmMterpCommonExceptionThrown
Ben Chengba4fc8b2009-06-01 13:00:29 -0700779
780 .align 2
781.LdvmAsmInstructionStart:
782 .word dvmAsmInstructionStart
783.LdvmJitToInterpNoChain:
784 .word dvmJitToInterpNoChain
785.LdvmMterpStdBail:
786 .word dvmMterpStdBail
Ben Chengcc6600c2009-06-22 14:45:16 -0700787.LdvmMterpCommonExceptionThrown:
788 .word dvmMterpCommonExceptionThrown
Ben Chengba4fc8b2009-06-01 13:00:29 -0700789.L__aeabi_cdcmple:
790 .word __aeabi_cdcmple
791.L__aeabi_cfcmple:
792 .word __aeabi_cfcmple
793
794 .global dmvCompilerTemplateEnd
795dmvCompilerTemplateEnd:
796
797#endif /* WITH_JIT */
798