OSDN Git Service

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