blob: f996168c5d01ed4ab24fa1302da77960740d7ce4 [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.
*/
/*
* File: CallABI.S
*
* Code: facilitates call to native code C and C++ routines.
*
*/
/*
* 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.
*/
/*
* On entry:
* 4(%sp) JNIEnv (can be left alone)
* 8(%esp) clazz (NULL for virtual method calls, non-NULL for static)
* 12(%esp) arg info
* 16(%esp) argc (number of 32-bit values in argv)
* 20(%esp) argv
* 24(%esp) short signature
* 28(%esp) func
* 32(%esp) pReturn
*
* For a virtual method call, the "this" reference is in argv[0].
*
* argInfo (32-bit int) layout:
*
* SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
*
* S - if set, argInfo hints are invalid
* R - return type enumeration (see jniInternal.h)
* VOID -> 0
* FLOAT -> 1
* DOUBLE -> 2
* S8 -> 3
* S4 -> 4
* H - target-specific hints (see below for details)
*
* IA32 ABI JNI hint format
*
* ZZZZ ZZZZZZZZ AAAAAAAA AAAAAAAA
*
* Z - reserved
* A - size of the variable argument block in 32-bit words
*/
.text
.align 4
.global dvmPlatformInvoke
.type dvmPlatformInvoke, %function
dvmPlatformInvoke:
CallABI_ENTER:
/*
* Save registers.
*/
movl %ebp, -4(%esp)
movl %ebx, -8(%esp) # save %ebx
movl %esi, -12(%esp) # save %esi
movl %edi, -16(%esp) # save %edi
lea (%esp), %ebp
/*
* Check if argInfo is valid. Is always valid so should remove this check?
*/
movzwl 12(%ebp), %ecx # %ecx<- argsize in words
movl 12(%ebp), %ebx # %ebx<- argInfo
shl $2, %ecx # %ecx<- argsize in bytes
subl %ecx, %esp # %esp<- expanded for arg region
/*
* Prepare for 16 byte alignment
*/
and $0xfffffff0, %esp
subl $24, %esp
movl 8(%ebp), %eax # %eax<- clazz
cmpl $0, %eax # Check virtual or static
movl 4(%ebp), %ecx # %ecx<- JNIEnv
movl 20(%ebp), %esi # %esi<- argV
jne 1f # Branch if static
movl (%esi), %eax # get the this pointer
addl $4, %esi # %esi<- update past this
1:
movl %ecx, -8(%esp) # push JNIEnv as arg #1
movl %eax, -4(%esp) # push clazz or this as arg #2
lea -8(%esp), %esp
/*
* Copy arguments
*/
movzwl %bx, %ecx # %ecx<- %bx; argsize in words
lea 8(%esp), %edi # %edi<- stack location for arguments
cld
rep movsl # move %ecx arguments to 8(%esp)
call *28(%ebp)
sarl $28, %ebx # %ebx<- SRRR (low 4 bits)
je CallABI_EXIT # exit call
cmpl $2, %ebx
movl 32(%ebp), %ecx # %ecx<- return pointer
je 2f # handle double return
jl 1f # handle float return
/*
* If a native function returns a result smaller than 8-bytes
* then higher bytes may contain garbage.
* This code does type-checking based on size of return result.
* We zero higher bytes instead of allowing the garbage to go through.
*/
cmpl $3,%ebx
je S8
cmpl $4,%ebx
je S4
cmpl $7,%ebx
je S1
cmpl $6,%ebx
jne S2
U2:
movzwl %ax, %eax
movl %eax, (%ecx) # save 32-bit return
jmp CallABI_EXIT # exit call
S1:
movsbl %al, %eax
movl %eax, (%ecx) # save 32-bit return
jmp CallABI_EXIT # exit call
S2:
movswl %ax, %eax
movl %eax, (%ecx) # save 32-bit return
jmp CallABI_EXIT # exit call
S4:
cltd
movl %eax, (%ecx) # save 32-bit return
jmp CallABI_EXIT # exit call
S8:
movl %edx, 4(%ecx) # save 64-bit return
movl %eax, (%ecx) # save 32-bit return
jmp CallABI_EXIT # exit call
2:
fstpl (%ecx) # save double return
jmp CallABI_EXIT # exit call
1:
fstps (%ecx) # save float return
CallABI_EXIT:
lea (%ebp), %esp
movl -16(%ebp), %edi # restore %edi
movl -12(%ebp), %esi # restore %esi
movl -8(%ebp), %ebx # restore %ebx
movl -4(%ebp), %ebp # restore caller base pointer
ret # return