2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * JNI method invocation. This is used to call a C/C++ JNI method. The
19 * argument list has to be pushed onto the native stack according to
20 * local calling conventions.
22 * This version supports the "old" ARM ABI.
25 #include <machine/cpu-features.h>
32 void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc,
33 const u4* argv, const char* signature, void* func, JValue* pReturn)
35 The method we are calling has the form:
37 return_type func(JNIEnv* pEnv, ClassObject* clazz, ...)
39 return_type func(JNIEnv* pEnv, Object* this, ...)
41 We receive a collection of 32-bit values which correspond to arguments from
42 the interpreter (e.g. float occupies one, double occupies two). It's up to
43 us to convert these into local calling conventions.
49 r0-r3 hold first 4 args to a method
50 r9 is given special treatment in some situations, but not for us
51 r10 (sl) seems to be generally available
52 r11 (fp) is used by gcc
53 r12 (ip) is scratch -- not preserved across method calls
54 r13 (sp) should be managed carefully in case a signal arrives
55 r14 (lr) must be preserved
56 r15 (pc) can be tinkered with directly
58 r0 holds returns <= 4 bytes
59 r0-r1 hold returns of 5-8 bytes, low word in r0
61 Stack is "full descending". Only the arguments that don't fit in the first 4
62 registers are placed on the stack. "sp" points at the first stacked argument
65 VFP: single-precision results in s0, double-precision results in d0.
67 Happily we don't have to do anything special here -- the args from the
68 interpreter work directly as C/C++ args on ARM (with the "classic" ABI).
73 .global dvmPlatformInvoke
74 .type dvmPlatformInvoke, %function
79 r1 clazz (NULL for virtual method calls, non-NULL for static)
83 [sp,#4] signature (ignored)
88 @ Standard gcc stack frame setup. We don't need to push the original
89 @ sp or the current pc if "-fomit-frame-pointer" is in use for the
90 @ rest of the code. If we don't plan to use a debugger we can speed
93 stmfd sp!, {r4, r5, r6, fp, ip, lr, pc}
94 sub fp, ip, #4 @ set up fp, same way gdb does
96 @ We need to push a variable number of arguments onto the stack.
97 @ Rather than keep a count and pop them off after, we just hold on to
100 @ In theory we don't need to keep sp -- we can do an ldmdb instead of
101 @ an ldmia -- but we're doing the gcc frame trick where we push the
102 @ pc on with stmfd and don't pop it off.
106 @ argc is already in a scratch register (r3). Put argv into one. Note
107 @ argv can't go into r0-r3 because we need to use it to load those.
108 ldr ip, [r4, #0] @ ip <-- argv
110 @ Is this a static method?
113 @ No: set r1 to *argv++, and set argc--.
118 @ While we still have the use of r2/r3, copy excess args from argv
119 @ to the stack. We need to push the last item in argv first, and we
120 @ want the first two items in argv to end up in r2/r3.
124 @ If there are N args, we want to skip 0 and 1, and push (N-1)..2. We
125 @ have N-2 in r3. If we set argv=argv+1, we can count from N-2 to 1
126 @ inclusive and get the right set of args.
130 @ *--sp = argv[count]
131 ldr r2, [r6, r3, lsl #2]
137 @ Load the last two args. These are coming out of the interpreted stack,
138 @ and the VM preserves an overflow region at the bottom, so it should be
139 @ safe to load two items out of argv even if we're at the end.
143 @ Show time. Tuck the pc into lr and load the pc from the method
144 @ address supplied by the caller. The value for "pc" is offset by 8
145 @ due to instruction prefetching.
147 #ifdef __ARM_HAVE_PC_INTERWORK
155 @ We're back, result is in r0 or (for long/double) r0-r1.
157 @ In theory, we need to use the "return type" arg to figure out what
158 @ we have and how to return it. However, unless we have an FPU,
159 @ all we need to do is copy r0-r1 into the JValue union.
163 #ifdef __ARM_HAVE_PC_INTERWORK
164 @ Restore the registers we saved and return. Note this remaps stuff,
165 @ so that "sp" comes from "ip", "pc" comes from "lr", and the "pc"
166 @ we pushed on evaporates when we restore "sp".
167 ldmfd r5, {r4, r5, r6, fp, sp, pc}
169 ldmfd r5, {r4, r5, r6, fp, sp, lr}
173 #endif /*__ARM_EABI__*/