1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ----------------------------------------------------------------------- 2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc. 3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Copyright (c) 2008 David Daney 4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project MIPS Foreign Function Interface 6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Permission is hereby granted, free of charge, to any person obtaining 8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a copy of this software and associated documentation files (the 9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ``Software''), to deal in the Software without restriction, including 10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project without limitation the rights to use, copy, modify, merge, publish, 11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project distribute, sublicense, and/or sell copies of the Software, and to 12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project permit persons to whom the Software is furnished to do so, subject to 13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the following conditions: 14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The above copyright notice and this permission notice shall be included 16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in all copies or substantial portions of the Software. 17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project DEALINGS IN THE SOFTWARE. 26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ----------------------------------------------------------------------- */ 27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h> 29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h> 30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h> 32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __GNUC__ 34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) 35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# define USE__BUILTIN___CLEAR_CACHE 1 36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# endif 37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifndef USE__BUILTIN___CLEAR_CACHE 40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/cachectl.h> 41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_DEBUG 44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# define FFI_MIPS_STOP_HERE() ffi_stop_here() 45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# define FFI_MIPS_STOP_HERE() do {} while(0) 47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32 50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FIX_ARGP \ 51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source ProjectFFI_ASSERT(argp <= &stack[bytes]); \ 52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectif (argp == &stack[bytes]) \ 53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ \ 54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = stack; \ 55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_MIPS_STOP_HERE(); \ 56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FIX_ARGP 59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space 63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project has been allocated for the function's arguments */ 64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void ffi_prep_args(char *stack, 66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif *ecif, 67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int bytes, 68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int flags) 69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int i; 71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **p_argv; 72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *argp; 73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **p_arg; 74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32 76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* If more than 8 double words are used, the remainder go 77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project on the stack. We reorder stuff on the stack here to 78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project support this easily. */ 79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (bytes > 8 * sizeof(ffi_arg)) 80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = &stack[bytes - (8 * sizeof(ffi_arg))]; 81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = stack; 83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = stack; 85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memset(stack, 0, bytes); 88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32 90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ( ecif->cif->rstruct_flag != 0 ) 91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) 93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(ffi_arg *) argp = (ffi_arg) ecif->rvalue; 96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp += sizeof(ffi_arg); 97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FIX_ARGP; 98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv = ecif->avalue; 101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++) 103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t z; 105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int a; 106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Align if necessary. */ 108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a = (*p_arg)->alignment; 109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (a < sizeof(ffi_arg)) 110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a = sizeof(ffi_arg); 111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((a - 1) & (unsigned long) argp) 113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = (char *) ALIGN(argp, a); 115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FIX_ARGP; 116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = (*p_arg)->size; 119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (z <= sizeof(ffi_arg)) 120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int type = (*p_arg)->type; 122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = sizeof(ffi_arg); 123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* The size of a pointer depends on the ABI */ 125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (type == FFI_TYPE_POINTER) 126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project type = 127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; 128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (type) 130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(ffi_arg *)argp = *(SINT8 *)(* p_argv); 133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(ffi_arg *)argp = *(UINT8 *)(* p_argv); 137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(ffi_arg *)argp = *(SINT16 *)(* p_argv); 141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(ffi_arg *)argp = *(UINT16 *)(* p_argv); 145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT32: 148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(ffi_arg *)argp = *(SINT32 *)(* p_argv); 149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT32: 152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(ffi_arg *)argp = *(UINT32 *)(* p_argv); 153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* This can only happen with 64bit slots. */ 156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(float *) argp = *(float *)(* p_argv); 158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Handle structures. */ 161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(argp, *p_argv, (*p_arg)->size); 163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_O32 169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(argp, *p_argv, z); 170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned long end = (unsigned long) argp + z; 173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned long cap = (unsigned long) stack + bytes; 174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Check if the data will fit within the register space. 176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Handle it if it doesn't. */ 177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (end <= cap) 179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(argp, *p_argv, z); 180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned long portion = cap - (unsigned long)argp; 183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(argp, *p_argv, portion); 185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = stack; 186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z -= portion; 187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(argp, (void*)((unsigned long)(*p_argv) + portion), 188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z); 189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv++; 194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp += z; 195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FIX_ARGP; 196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32 200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* The n32 spec says that if "a chunk consists solely of a double 202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project float field (but not a double, which is part of a union), it 203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project is passed in a floating point register. Any other chunk is 204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project passed in an integer register". This code traverses structure 205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project definitions and generates the appropriate flags. */ 206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic unsigned 208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectcalc_n32_struct_flags(ffi_type *arg, unsigned *loc, unsigned *arg_reg) 209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned flags = 0; 211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned index = 0; 212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type *e; 214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while ((e = arg->elements[index])) 216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Align this object. */ 218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *loc = ALIGN(*loc, e->alignment); 219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (e->type == FFI_TYPE_DOUBLE) 220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Already aligned to FFI_SIZEOF_ARG. */ 222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *arg_reg = *loc / FFI_SIZEOF_ARG; 223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (*arg_reg > 7) 224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS)); 226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *loc += e->size; 227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *loc += e->size; 230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project index++; 231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Next Argument register at alignment of FFI_SIZEOF_ARG. */ 233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; 234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return flags; 236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic unsigned 239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectcalc_n32_return_struct_flags(ffi_type *arg) 240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned flags = 0; 242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned small = FFI_TYPE_SMALLSTRUCT; 243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type *e; 244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Returning structures under n32 is a tricky thing. 246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project A struct with only one or two floating point fields 247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project is returned in $f0 (and $f2 if necessary). Any other 248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project struct results at most 128 bits are returned in $2 249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (the first 64 bits) and $3 (remainder, if necessary). 250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Larger structs are handled normally. */ 251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg->size > 16) 253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return 0; 254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg->size > 8) 256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project small = FFI_TYPE_SMALLSTRUCT2; 257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project e = arg->elements[0]; 259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (e->type == FFI_TYPE_DOUBLE) 260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags = FFI_TYPE_DOUBLE; 261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (e->type == FFI_TYPE_FLOAT) 262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags = FFI_TYPE_FLOAT; 263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (flags && (e = arg->elements[1])) 265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (e->type == FFI_TYPE_DOUBLE) 267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS; 268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (e->type == FFI_TYPE_FLOAT) 269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS; 270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return small; 272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (flags && (arg->elements[2])) 274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* There are three arguments and the first two are 276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project floats! This must be passed the old way. */ 277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return small; 278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (!flags) 282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return small; 283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return flags; 285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */ 290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif) 291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = 0; 293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_O32 295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT 296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * does not have special handling for floating point args. 297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */ 298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32) 300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->nargs > 0) 302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch ((cif->arg_types)[0]->type) 304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += (cif->arg_types)[0]->type; 308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->nargs > 1) 315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Only handle the second argument if the first 317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project is a float or double. */ 318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->flags) 319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch ((cif->arg_types)[1]->type) 321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS; 325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Set the return type flag */ 336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->abi == FFI_O32_SOFT_FLOAT) 338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->rtype->type) 340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_VOID: 342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); 344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2); 350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); 355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* FFI_O32 */ 361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->rtype->type) 362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_VOID: 364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2); 368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2); 373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2); 377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32 383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Set the flags necessary for N32 processing */ 384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned arg_reg = 0; 386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned loc = 0; 387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned count = (cif->nargs < 8) ? cif->nargs : 8; 388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned index = 0; 389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned struct_flags = 0; 391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->rtype->type == FFI_TYPE_STRUCT) 393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project struct_flags = calc_n32_return_struct_flags(cif->rtype); 395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (struct_flags == 0) 397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* This means that the structure is being passed as 399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a hidden argument */ 400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_reg = 1; 402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project count = (cif->nargs < 7) ? cif->nargs : 7; 403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->rstruct_flag = !0; 405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->rstruct_flag = 0; 408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->rstruct_flag = 0; 411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while (count-- > 0 && arg_reg < 8) 413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch ((cif->arg_types)[index]->type) 415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += 419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS)); 420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_reg++; 421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_LONGDOUBLE: 423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Align it. */ 424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_reg = ALIGN(arg_reg, 2); 425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Treat it as two adjacent doubles. */ 426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += 427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); 428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_reg++; 429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += 430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS)); 431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_reg++; 432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project loc = arg_reg * FFI_SIZEOF_ARG; 436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += calc_n32_struct_flags((cif->arg_types)[index], 437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project &loc, &arg_reg); 438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_reg++; 442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project index++; 446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Set the return type flag */ 449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->rtype->type) 450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (struct_flags == 0) 454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* The structure is returned through a hidden 456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project first argument. Do nothing, 'cause FFI_TYPE_VOID 457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project is 0 */ 458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* The structure is returned via some tricky 462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project mechanism */ 463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); 464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8)); 465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_VOID: 470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Do nothing, 'cause FFI_TYPE_VOID is 0 */ 471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8); 476a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 477a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_LONGDOUBLE: 478a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Long double is returned as if it were a struct containing 479a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project two doubles. */ 480a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8); 481a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += (FFI_TYPE_DOUBLE + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS)) 482a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project << (4 + (FFI_FLAG_BITS * 8)); 483a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 484a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 485a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8); 486a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 487a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 488a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 489a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 490a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 491a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 492a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 493a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 494a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Low level routine for calling O32 functions */ 495a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), 496a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif *, unsigned, 497a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned, unsigned *, void (*)(void)); 498a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 499a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Low level routine for calling N32 functions */ 500a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), 501a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif *, unsigned, 502a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned, unsigned *, void (*)(void)); 503a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 504a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 505a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 506a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif ecif; 507a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 508a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.cif = cif; 509a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.avalue = avalue; 510a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 511a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* If the return value is a struct and we don't have a return */ 512a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* value address then we need to make one */ 513a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 514a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((rvalue == NULL) && 515a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (cif->rtype->type == FFI_TYPE_STRUCT)) 516a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = alloca(cif->rtype->size); 517a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 518a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = rvalue; 519a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 520a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->abi) 521a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 522a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_O32 523a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_O32: 524a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_O32_SOFT_FLOAT: 525a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, 526a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags, ecif.rvalue, fn); 527a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 528a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 529a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 530a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32 531a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_N32: 532a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_N64: 533a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 534a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int copy_rvalue = 0; 535a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *rvalue_copy = ecif.rvalue; 536a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16) 537a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 538a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* For structures smaller than 16 bytes we clobber memory 539a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in 8 byte increments. Make a copy so we don't clobber 540a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the callers memory outside of the struct bounds. */ 541a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project rvalue_copy = alloca(16); 542a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project copy_rvalue = 1; 543a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 544a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, 545a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags, rvalue_copy, fn); 546a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (copy_rvalue) 547a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size); 548a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 549a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 550a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 551a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 552a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 553a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 554a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 555a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 556a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 557a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 558a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURES 559a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_O32) 560a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_O32(void); 561a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 562a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_N32(void); 563a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_MIPS_O32 */ 564a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 565a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status 566a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure *closure, 567a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif *cif, 568a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void (*fun)(ffi_cif*,void*,void**,void*), 569a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *user_data, 570a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *codeloc) 571a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 572a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int *tramp = (unsigned int *) &closure->tramp[0]; 573a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void * fn; 574a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *clear_location = (char *) codeloc; 575a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 576a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_O32) 577a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT); 578a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fn = ffi_closure_O32; 579a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else /* FFI_MIPS_N32 */ 580a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64); 581a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fn = ffi_closure_N32; 582a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_MIPS_O32 */ 583a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 584a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32) 585a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* lui $25,high(fn) */ 586a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[0] = 0x3c190000 | ((unsigned)fn >> 16); 587a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $25,low(fn) */ 588a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff); 589a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* lui $12,high(codeloc) */ 590a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16); 591a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* jr $25 */ 592a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[3] = 0x03200008; 593a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $12,low(codeloc) */ 594a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff); 595a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 596a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* N64 has a somewhat larger trampoline. */ 597a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* lui $25,high(fn) */ 598a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48); 599a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* lui $12,high(codeloc) */ 600a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48); 601a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $25,mid-high(fn) */ 602a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff); 603a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $12,mid-high(codeloc) */ 604a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff); 605a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* dsll $25,$25,16 */ 606a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[4] = 0x0019cc38; 607a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* dsll $12,$12,16 */ 608a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[5] = 0x000c6438; 609a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $25,mid-low(fn) */ 610a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff); 611a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $12,mid-low(codeloc) */ 612a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff); 613a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* dsll $25,$25,16 */ 614a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[8] = 0x0019cc38; 615a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* dsll $12,$12,16 */ 616a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[9] = 0x000c6438; 617a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $25,low(fn) */ 618a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff); 619a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* jr $25 */ 620a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[11] = 0x03200008; 621a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* ori $12,low(codeloc) */ 622a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff); 623a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 624a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 625a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 626a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->cif = cif; 627a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->fun = fun; 628a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->user_data = user_data; 629a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 630a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef USE__BUILTIN___CLEAR_CACHE 631a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE); 632a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else 633a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE); 634a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 635a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 636a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 637a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 638a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* 639a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Decodes the arguments to a function, which will be stored on the 640a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stack. AR is the pointer to the beginning of the integer arguments 641a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * (and, depending upon the arguments, some floating-point arguments 642a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * as well). FPR is a pointer to the area where floating point 643a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * registers have been saved, if any. 644a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 645a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * RVALUE is the location where the function return value will be 646a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stored. CLOSURE is the prepared closure to invoke. 647a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 648a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * This function should only be called from assembly, which is in 649a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * turn called from a trampoline. 650a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 651a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Returns the function return type. 652a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 653a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Based on the similar routine for sparc. 654a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */ 655a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint 656a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_mips_inner_O32 (ffi_closure *closure, 657a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *rvalue, ffi_arg *ar, 658a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project double *fpr) 659a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 660a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif *cif; 661a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **avaluep; 662a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_arg *avalue; 663a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **arg_types; 664a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int i, avn, argn, seen_int; 665a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 666a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif = closure->cif; 667a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue = alloca (cif->nargs * sizeof (ffi_arg)); 668a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep = alloca (cif->nargs * sizeof (ffi_arg)); 669a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 670a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project seen_int = (cif->abi == FFI_O32_SOFT_FLOAT); 671a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn = 0; 672a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 673a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT) 674a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 675a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project rvalue = (void *)(UINT32)ar[0]; 676a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn = 1; 677a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 678a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 679a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project i = 0; 680a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avn = cif->nargs; 681a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_types = cif->arg_types; 682a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 683a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while (i < avn) 684a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 685a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (i < 2 && !seen_int && 686a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (arg_types[i]->type == FFI_TYPE_FLOAT || 687a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_types[i]->type == FFI_TYPE_DOUBLE)) 688a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 689a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __MIPSEB__ 690a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg_types[i]->type == FFI_TYPE_FLOAT) 691a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = ((char *) &fpr[i]) + sizeof (float); 692a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 693a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 694a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = (char *) &fpr[i]; 695a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 696a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 697a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 698a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg_types[i]->alignment == 8 && (argn & 0x1)) 699a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn++; 700a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (arg_types[i]->type) 701a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 702a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 703a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 704a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(SINT8 *) &avalue[i] = (SINT8) ar[argn]; 705a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 706a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 707a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 708a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 709a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT8 *) &avalue[i] = (UINT8) ar[argn]; 710a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 711a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 712a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 713a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 714a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(SINT16 *) &avalue[i] = (SINT16) ar[argn]; 715a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 716a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 717a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 718a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 719a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT16 *) &avalue[i] = (UINT16) ar[argn]; 720a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 721a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 722a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 723a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = (char *) &ar[argn]; 724a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 725a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 726a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project seen_int = 1; 727a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 728a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; 729a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project i++; 730a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 731a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 732a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Invoke the closure. */ 733a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (closure->fun) (cif, rvalue, avaluep, closure->user_data); 734a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 735a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->abi == FFI_O32_SOFT_FLOAT) 736a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 737a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->rtype->type) 738a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 739a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 740a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_INT; 741a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 742a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_TYPE_UINT64; 743a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 744a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return cif->rtype->type; 745a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 746a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 747a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 748a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 749a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return cif->rtype->type; 750a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 751a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 752a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 753a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_N32) 754a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 755a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void 756a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectcopy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type, 757a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int argn, unsigned arg_offset, ffi_arg *ar, 758a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_arg *fpr) 759a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 760a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **elt_typep = type->elements; 761a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while(*elt_typep) 762a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 763a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type *elt_type = *elt_typep; 764a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned o; 765a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *tp; 766a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *argp; 767a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project char *fpp; 768a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 769a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project o = ALIGN(offset, elt_type->alignment); 770a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_offset += o - offset; 771a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project offset = o; 772a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn += arg_offset / sizeof(ffi_arg); 773a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_offset = arg_offset % sizeof(ffi_arg); 774a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 775a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = (char *)(ar + argn); 776a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn); 777a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 778a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project tp = target + offset; 779a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 780a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (elt_type->type == FFI_TYPE_DOUBLE) 781a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(double *)tp = *(double *)fpp; 782a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 783a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(tp, argp + arg_offset, elt_type->size); 784a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 785a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project offset += elt_type->size; 786a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_offset += elt_type->size; 787a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project elt_typep++; 788a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn += arg_offset / sizeof(ffi_arg); 789a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_offset = arg_offset % sizeof(ffi_arg); 790a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 791a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 792a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 793a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* 794a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Decodes the arguments to a function, which will be stored on the 795a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stack. AR is the pointer to the beginning of the integer 796a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * arguments. FPR is a pointer to the area where floating point 797a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * registers have been saved. 798a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 799a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * RVALUE is the location where the function return value will be 800a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stored. CLOSURE is the prepared closure to invoke. 801a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 802a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * This function should only be called from assembly, which is in 803a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * turn called from a trampoline. 804a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 805a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Returns the function return flags. 806a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * 807a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */ 808a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint 809a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_mips_inner_N32 (ffi_closure *closure, 810a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *rvalue, ffi_arg *ar, 811a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_arg *fpr) 812a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 813a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif *cif; 814a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **avaluep; 815a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_arg *avalue; 816a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_type **arg_types; 817a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int i, avn, argn; 818a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 819a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif = closure->cif; 820a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avalue = alloca (cif->nargs * sizeof (ffi_arg)); 821a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep = alloca (cif->nargs * sizeof (ffi_arg)); 822a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 823a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn = 0; 824a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 825a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->rstruct_flag) 826a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 827a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if _MIPS_SIM==_ABIN32 828a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project rvalue = (void *)(UINT32)ar[0]; 829a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else /* N64 */ 830a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project rvalue = (void *)ar[0]; 831a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 832a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn = 1; 833a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 834a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 835a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project i = 0; 836a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avn = cif->nargs; 837a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_types = cif->arg_types; 838a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 839a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project while (i < avn) 840a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 841a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg_types[i]->type == FFI_TYPE_FLOAT 842a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project || arg_types[i]->type == FFI_TYPE_DOUBLE) 843a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 844a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_arg *argp = argn >= 8 ? ar + argn : fpr + argn; 845a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __MIPSEB__ 846a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8) 847a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = ((char *) argp) + sizeof (float); 848a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 849a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif 850a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = (char *) argp; 851a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 852a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 853a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 854a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned type = arg_types[i]->type; 855a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 856a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (arg_types[i]->alignment > sizeof(ffi_arg)) 857a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg)); 858a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 859a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_arg *argp = ar + argn; 860a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 861a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* The size of a pointer depends on the ABI */ 862a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (type == FFI_TYPE_POINTER) 863a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project type = (cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32; 864a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 865a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (type) 866a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 867a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 868a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 869a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(SINT8 *) &avalue[i] = (SINT8) *argp; 870a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 871a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 872a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 873a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 874a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT8 *) &avalue[i] = (UINT8) *argp; 875a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 876a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 877a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 878a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 879a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(SINT16 *) &avalue[i] = (SINT16) *argp; 880a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 881a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 882a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 883a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 884a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT16 *) &avalue[i] = (UINT16) *argp; 885a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 886a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 887a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT32: 888a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 889a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(SINT32 *) &avalue[i] = (SINT32) *argp; 890a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 891a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 892a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT32: 893a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = &avalue[i]; 894a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(UINT32 *) &avalue[i] = (UINT32) *argp; 895a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 896a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 897a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 898a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (argn < 8) 899a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 900a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Allocate space for the struct as at least part of 901a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project it was passed in registers. */ 902a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = alloca(arg_types[i]->size); 903a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i], 904a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn, 0, ar, fpr); 905a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 906a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 907a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 908a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Else fall through. */ 909a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 910a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project avaluep[i] = (char *) argp; 911a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 912a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 913a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 914a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg); 915a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project i++; 916a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 917a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 918a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Invoke the closure. */ 919a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (closure->fun) (cif, rvalue, avaluep, closure->user_data); 920a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 921a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return cif->flags >> (FFI_FLAG_BITS * 8); 922a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 923a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 924a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_MIPS_N32 */ 925a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 926a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_CLOSURES */ 927