/* 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