blob: 766aff725ef71cb4a9b40c528c488bff2b651501 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* JNI method invocation. This is used to call a C/C++ JNI method. The
* argument list has to be pushed onto the native stack according to
* local calling conventions.
*
* This version supports 32-bit x86
*/
/*
Function prototype:
void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc,
const u4* argv, const char* signature, void* func, JValue* pReturn)
The method we are calling has the form:
return_type func(JNIEnv* pEnv, ClassObject* clazz, ...)
-or-
return_type func(JNIEnv* pEnv, Object* this, ...)
We receive a collection of 32-bit values which correspond to arguments from
the interpreter (e.g. float occupies one, double occupies two). It's up to
us to convert these into local calling conventions.
*/
/*
x86 notes:
The native code expects arguments on the stack, pushed from right to left.
This matches what Dalvik is passing here.
EAX, EDX and ECX are scratch.
4-byte alignment is required for long long and double, so we won't pad
Non-FP return types <= 4 bytes come back in EAX
Non-FP return types of 8 bytes come back in EAX:EDX, with lsw in EAX.
Float and double returned on top of FP stack.
*/
.text
.align 4
.global dvmPlatformInvoke
.type dvmPlatformInvoke, @function
/*
* On entry:
* [ 8] arg0 JNIEnv (can be left alone)
* [12] arg1 clazz (NULL for virtual method calls, non-NULL for static)
* [16] arg2 arg info
* [20] arg3 argc
* [24] arg4 argv
* [28] arg5 short signature
* [32] arg6 func
* [36] arg7 pReturn
*
* For a virtual method call, the "this" reference is in argv[0].
*
* argInfo (32-bit int) layout:
* SRRRZZZZ ZZZZZZZZ AAAAAAAA AAAAAAAA
*
* Z - reserved
* S - if set, argInfo hints are invalid
* R - return type enumeration (see jniInternal.h)
* VOID -> 0
* FLOAT -> 1
* DOUBLE -> 2
* S8 -> 3
* S4 -> 4
* A - size of the variable argument block in 32-bit words
*
*/
dvmPlatformInvoke:
/* Establish the frame pointer, spill & align to 16b */
pushl %ebp
movl %esp,%ebp
pushl %edi
pushl %esi
pushl %ebx
subl $12,%esp
/* For 386 ABI, argInfo hints should always be valid. Abort if not. */
movl 16(%ebp),%ebx
testl %ebx,%ebx
js dvmAbort
/*
* Get the size of the variable region, add two more slots for the first
* two arguments and grow (preserving alignment)
*/
movl %ebx,%ecx
leal 20(,%ecx,4),%ecx
andl $0x0003FFF0,%ecx
subl %ecx,%esp
/* Handle this/class */
movl 8(%ebp),%ecx
movl 12(%ebp),%eax
movl 24(%ebp),%esi
testl %eax,%eax
jne isClass
movl (%esi),%eax
addl $4,%esi
isClass:
movl %eax,4(%esp)
movl %ecx,0(%esp)
/* Now, copy the variable arguments region */
movl %ebx,%ecx
andl $0x0000FFFF,%ecx
leal 8(%esp),%edi
cld
rep
movsd
/* Ready to go - call the native code */
call *32(%ebp)
/* Store the result. */
sarl $28,%ebx
/* Is void? */
testl %ebx,%ebx
je cleanUpAndExit
movl 36(%ebp),%ecx
/* Is FP? */
cmpl $2,%ebx
jle isFP
cmpl $4,%ebx /* smaller than 32-bits? */
jg isSmall
storeRetval:
/* Blindly storing 64-bits won't hurt 32-bit case */
movl %eax,(%ecx)
movl %edx,4(%ecx)
jmp cleanUpAndExit
isSmall:
cmpl $7,%ebx /* S1? */
jne checkShort
movsbl %al,%eax
movl %eax,(%ecx)
jmp cleanUpAndExit
checkShort:
cmpl $6,%ebx /* U2? */
jne isSignedShort
movzwl %ax,%eax
movl %eax,(%ecx)
jmp cleanUpAndExit
isSignedShort:
/* Must be S2 */
movswl %ax,%eax
movl %eax,(%ecx)
jmp cleanUpAndExit
isFP:
/* Is Float? */
cmpl $1,%ebx
je saveFloat
fstpl (%ecx)
jmp cleanUpAndExit
saveFloat:
fstps (%ecx)
cleanUpAndExit:
leal -12(%ebp),%esp
pop %ebx
pop %esi
pop %edi
pop %ebp
ret
.size dvmPlatformInvoke, .-dvmPlatformInvoke
.section .note.GNU-stack,"",@progbits