1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * JNI method invocation.  This is used to call a C/C++ JNI method.  The
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * argument list has to be pushed onto the native stack according to
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * local calling conventions.
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This version supports the "old" ARM ABI.
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <machine/cpu-features.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef __ARM_EABI__
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectFunction prototype:
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc,
33de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    const u4* argv, const char* signature, void* func, JValue* pReturn)
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe method we are calling has the form:
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  return_type func(JNIEnv* pEnv, ClassObject* clazz, ...)
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    -or-
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  return_type func(JNIEnv* pEnv, Object* this, ...)
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe receive a collection of 32-bit values which correspond to arguments from
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe interpreter (e.g. float occupies one, double occupies two).  It's up to
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectus to convert these into local calling conventions.
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectARM ABI notes:
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr0-r3 hold first 4 args to a method
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr9 is given special treatment in some situations, but not for us
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr10 (sl) seems to be generally available
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr11 (fp) is used by gcc
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr12 (ip) is scratch -- not preserved across method calls
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr13 (sp) should be managed carefully in case a signal arrives
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr14 (lr) must be preserved
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr15 (pc) can be tinkered with directly
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr0 holds returns <= 4 bytes
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectr0-r1 hold returns of 5-8 bytes, low word in r0
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectStack is "full descending".  Only the arguments that don't fit in the first 4
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectregisters are placed on the stack.  "sp" points at the first stacked argument
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project(i.e. the 5th arg).
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectVFP: single-precision results in s0, double-precision results in d0.
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectHappily we don't have to do anything special here -- the args from the
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectinterpreter work directly as C/C++ args on ARM (with the "classic" ABI).
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    .text
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    .align  2
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    .global dvmPlatformInvoke
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    .type   dvmPlatformInvoke, %function
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectOn entry:
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  r0  JNIEnv
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  r1  clazz (NULL for virtual method calls, non-NULL for static)
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  r2  arg info (ignored)
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  r3  argc
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  [sp]     argv
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  [sp,#4]  signature (ignored)
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  [sp,#8]  func
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project  [sp,#12] pReturn
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectdvmPlatformInvoke:
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ Standard gcc stack frame setup.  We don't need to push the original
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ sp or the current pc if "-fomit-frame-pointer" is in use for the
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ rest of the code.  If we don't plan to use a debugger we can speed
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ this up a little.
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mov     ip, sp
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stmfd   sp!, {r4, r5, r6, fp, ip, lr, pc}
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    sub     fp, ip, #4          @ set up fp, same way gdb does
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ We need to push a variable number of arguments onto the stack.
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ Rather than keep a count and pop them off after, we just hold on to
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ the stack pointers.
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ In theory we don't need to keep sp -- we can do an ldmdb instead of
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ an ldmia -- but we're doing the gcc frame trick where we push the
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ pc on with stmfd and don't pop it off.
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mov     r4, ip
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mov     r5, sp
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ argc is already in a scratch register (r3).  Put argv into one.  Note
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ argv can't go into r0-r3 because we need to use it to load those.
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldr     ip, [r4, #0]        @ ip <-- argv
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ Is this a static method?
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cmp     r1, #0
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ No: set r1 to *argv++, and set argc--.
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ (r0=pEnv, r1=this)
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldreq   r1, [ip], #4
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    subeq   r3, r3, #1
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ While we still have the use of r2/r3, copy excess args from argv
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ to the stack.  We need to push the last item in argv first, and we
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ want the first two items in argv to end up in r2/r3.
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    subs    r3, r3, #2
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ble     .Lno_copy
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ If there are N args, we want to skip 0 and 1, and push (N-1)..2.  We
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ have N-2 in r3.  If we set argv=argv+1, we can count from N-2 to 1
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ inclusive and get the right set of args.
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    add     r6, ip, #4
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project.Lcopy:
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ *--sp = argv[count]
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldr     r2, [r6, r3, lsl #2]
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    str     r2, [sp, #-4]!
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    subs    r3, r3, #1
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bne     .Lcopy
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project.Lno_copy:
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ Load the last two args.  These are coming out of the interpreted stack,
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ and the VM preserves an overflow region at the bottom, so it should be
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ safe to load two items out of argv even if we're at the end.
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldr     r2, [ip]
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldr     r3, [ip, #4]
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ Show time.  Tuck the pc into lr and load the pc from the method
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ address supplied by the caller.  The value for "pc" is offset by 8
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ due to instruction prefetching.
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef __ARM_HAVE_PC_INTERWORK
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    mov     lr, pc
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldr     pc, [r4, #8]
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldr     ip, [r4, #8]
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    blx     ip
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ We're back, result is in r0 or (for long/double) r0-r1.
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ In theory, we need to use the "return type" arg to figure out what
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ we have and how to return it.  However, unless we have an FPU,
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ all we need to do is copy r0-r1 into the JValue union.
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldr     ip, [r4, #12]
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stmia   ip, {r0-r1}
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef __ARM_HAVE_PC_INTERWORK
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ Restore the registers we saved and return.  Note this remaps stuff,
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ so that "sp" comes from "ip", "pc" comes from "lr", and the "pc"
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @ we pushed on evaporates when we restore "sp".
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldmfd   r5, {r4, r5, r6, fp, sp, pc}
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ldmfd   r5, {r4, r5, r6, fp, sp, lr}
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bx      lr
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif /*__ARM_EABI__*/
174