1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
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
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16/*
17 * JNI method invocation.  This is used to call a C/C++ JNI method.  The
18 * argument list has to be pushed onto the native stack according to
19 * local calling conventions.
20 *
21 * This version supports 32-bit x86
22 */
23
24/*
25Function prototype:
26
27void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc,
28    const u4* argv, const char* signature, void* func, JValue* pReturn)
29
30The method we are calling has the form:
31
32  return_type func(JNIEnv* pEnv, ClassObject* clazz, ...)
33    -or-
34  return_type func(JNIEnv* pEnv, Object* this, ...)
35
36We receive a collection of 32-bit values which correspond to arguments from
37the interpreter (e.g. float occupies one, double occupies two).  It's up to
38us to convert these into local calling conventions.
39*/
40
41/*
42x86 notes:
43
44The native code expects arguments on the stack, pushed from right to left.
45This matches what Dalvik is passing here.
46
47EAX, EDX and ECX are scratch.
48
494-byte alignment is required for long long and double, so we won't pad
50
51Non-FP return types <= 4 bytes come back in EAX
52Non-FP return types of 8 bytes come back in EAX:EDX, with lsw in EAX.
53Float and double returned on top of FP stack.
54
55*/
56
57    .text
58    .align  4
59    .global dvmPlatformInvoke
60    .type   dvmPlatformInvoke, @function
61
62/*
63 * On entry:
64 *  [ 8]  arg0  JNIEnv (can be left alone)
65 *  [12]  arg1  clazz (NULL for virtual method calls, non-NULL for static)
66 *  [16]  arg2  arg info
67 *  [20]  arg3  argc
68 *  [24]  arg4  argv
69 *  [28]  arg5  short signature
70 *  [32]  arg6  func
71 *  [36]  arg7  pReturn
72 *
73 * For a virtual method call, the "this" reference is in argv[0].
74 *
75 * argInfo (32-bit int) layout:
76 *   SRRRZZZZ ZZZZZZZZ AAAAAAAA AAAAAAAA
77 *
78 *   Z - reserved
79 *   S - if set, argInfo hints are invalid
80 *   R - return type enumeration (see jniInternal.h)
81 *       VOID   -> 0
82 *       FLOAT  -> 1
83 *       DOUBLE -> 2
84 *       S8     -> 3
85 *       S4     -> 4
86 *   A - size of the variable argument block in 32-bit words
87 *
88 */
89dvmPlatformInvoke:
90/* Establish the frame pointer, spill & align to 16b */
91    pushl    %ebp
92    movl     %esp,%ebp
93    pushl    %edi
94    pushl    %esi
95    pushl    %ebx
96    subl     $12,%esp
97/* For 386 ABI, argInfo hints should always be valid.  Abort if not. */
98    movl     16(%ebp),%ebx
99    testl    %ebx,%ebx
100    js       dvmAbort
101/*
102 * Get the size of the variable region, add two more slots for the first
103 * two arguments and grow (preserving alignment)
104 */
105    movl     %ebx,%ecx
106    leal     20(,%ecx,4),%ecx
107    andl     $0x0003FFF0,%ecx
108    subl     %ecx,%esp
109/* Handle this/class */
110    movl     8(%ebp),%ecx
111    movl     12(%ebp),%eax
112    movl     24(%ebp),%esi
113    testl    %eax,%eax
114    jne      isClass
115    movl     (%esi),%eax
116    addl     $4,%esi
117isClass:
118    movl     %eax,4(%esp)
119    movl     %ecx,0(%esp)
120/* Now, copy the variable arguments region */
121    movl     %ebx,%ecx
122    andl     $0x0000FFFF,%ecx
123    leal     8(%esp),%edi
124    cld
125    rep
126    movsd
127/* Ready to go - call the native code */
128    call     *32(%ebp)
129/* Store the result. */
130    sarl      $28,%ebx
131    /* Is void? */
132    testl     %ebx,%ebx
133    je       cleanUpAndExit
134    movl     36(%ebp),%ecx
135    /* Is FP? */
136    cmpl     $2,%ebx
137    jle      isFP
138    cmpl     $4,%ebx  /* smaller than 32-bits? */
139    jg       isSmall
140storeRetval:
141    /* Blindly storing 64-bits won't hurt 32-bit case */
142    movl     %eax,(%ecx)
143    movl     %edx,4(%ecx)
144    jmp      cleanUpAndExit
145isSmall:
146    cmpl     $7,%ebx  /* S1? */
147    jne      checkShort
148    movsbl   %al,%eax
149    movl     %eax,(%ecx)
150    jmp      cleanUpAndExit
151checkShort:
152    cmpl     $6,%ebx  /* U2? */
153    jne      isSignedShort
154    movzwl   %ax,%eax
155    movl     %eax,(%ecx)
156    jmp      cleanUpAndExit
157isSignedShort:
158    /* Must be S2 */
159    movswl   %ax,%eax
160    movl     %eax,(%ecx)
161    jmp      cleanUpAndExit
162isFP:
163    /* Is Float? */
164    cmpl    $1,%ebx
165    je       saveFloat
166    fstpl    (%ecx)
167    jmp      cleanUpAndExit
168saveFloat:
169    fstps    (%ecx)
170cleanUpAndExit:
171    leal     -12(%ebp),%esp
172    pop      %ebx
173    pop      %esi
174    pop      %edi
175    pop      %ebp
176    ret
177    .size    dvmPlatformInvoke, .-dvmPlatformInvoke
178    .section .note.GNU-stack,"",@progbits
179