1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ----------------------------------------------------------------------- 2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi.c - Copyright (c) 1998, 2008 Red Hat, Inc. 3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ARM Foreign Function Interface 5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project Permission is hereby granted, free of charge, to any person obtaining 7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project a copy of this software and associated documentation files (the 8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ``Software''), to deal in the Software without restriction, including 9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project without limitation the rights to use, copy, modify, merge, publish, 10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project distribute, sublicense, and/or sell copies of the Software, and to 11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project permit persons to whom the Software is furnished to do so, subject to 12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project the following conditions: 13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project The above copyright notice and this permission notice shall be included 15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project in all copies or substantial portions of the Software. 16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project DEALINGS IN THE SOFTWARE. 25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ----------------------------------------------------------------------- */ 26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h> 28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h> 29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h> 31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space 33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project has been allocated for the function's arguments */ 34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_prep_args(char *stack, extended_cif *ecif) 36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register unsigned int i; 38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register void **p_argv; 39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register char *argp; 40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register ffi_type **p_arg; 41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = stack; 43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { 45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(void **) argp = ecif->rvalue; 46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp += 4; 47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv = ecif->avalue; 50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; 52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (i != 0); 53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project i--, p_arg++) 54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t z; 56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Align if necessary */ 58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (((*p_arg)->alignment - 1) & (unsigned) argp) { 59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = (char *) ALIGN(argp, (*p_arg)->alignment); 60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((*p_arg)->type == FFI_TYPE_STRUCT) 63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = (char *) ALIGN(argp, 4); 64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = (*p_arg)->size; 66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (z < sizeof(int)) 67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = sizeof(int); 69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch ((*p_arg)->type) 70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT8: 72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); 73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT8: 76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); 77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT16: 80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); 81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT16: 84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); 85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(argp, *p_argv, (*p_arg)->size); 89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (z == sizeof(int)) 96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); 98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy(argp, *p_argv, z); 102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv++; 104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp += z; 105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return; 108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */ 111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif) 112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Round the stack up to a multiple of 8 bytes. This isn't needed 114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project everywhere, but it is on some platforms, and it doesn't harm anything 115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project when it isn't needed. */ 116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->bytes = (cif->bytes + 7) & ~7; 117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Set the return type flag */ 119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->rtype->type) 120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_VOID: 122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_FLOAT: 123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_DOUBLE: 124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = (unsigned) cif->rtype->type; 125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_SINT64: 128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_UINT64: 129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = (unsigned) FFI_TYPE_SINT64; 130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_TYPE_STRUCT: 133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (cif->rtype->size <= 4) 134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* A Composite Type not larger than 4 bytes is returned in r0. */ 135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = (unsigned)FFI_TYPE_INT; 136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* A Composite Type larger than 4 bytes, or whose size cannot 138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project be determined statically ... is stored in memory at an 139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project address passed [in r0]. */ 140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = (unsigned)FFI_TYPE_STRUCT; 141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif->flags = FFI_TYPE_INT; 145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, 152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned, unsigned, unsigned *, void (*fn)(void)); 153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project extended_cif ecif; 157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project int small_struct = (cif->flags == FFI_TYPE_INT 159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project && cif->rtype->type == FFI_TYPE_STRUCT); 160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.cif = cif; 162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.avalue = avalue; 163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int temp; 165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* If the return value is a struct and we don't have a return */ 167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* value address then we need to make one */ 168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((rvalue == NULL) && 170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (cif->flags == FFI_TYPE_STRUCT)) 171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = alloca(cif->rtype->size); 173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else if (small_struct) 175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = &temp; 176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project else 177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ecif.rvalue = rvalue; 178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project switch (cif->abi) 180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project case FFI_SYSV: 182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, 183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project fn); 184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project default: 187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT(0); 188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project break; 189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (small_struct) 191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project memcpy (rvalue, &temp, cif->rtype->size); 192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/** private members **/ 195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void ffi_prep_incoming_args_SYSV (char *stack, void **ret, 197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void** args, ffi_cif* cif); 198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_closure_SYSV (ffi_closure *); 200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This function is jumped to by the trampoline */ 202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectunsigned int 204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_SYSV_inner (closure, respp, args) 205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_closure *closure; 206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **respp; 207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *args; 208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project // our various things... 210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif *cif; 211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **arg_area; 212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project cif = closure->cif; 214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project arg_area = (void**) alloca (cif->nargs * sizeof (void*)); 215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* this call will initialize ARG_AREA, such that each 217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * element in that array points to the corresponding 218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * value on the stack; and if the function returns 219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * a structure, it will re-set RESP to point to the 220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * structure return address. */ 221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); 223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project (closure->fun) (cif, *respp, arg_area, closure->user_data); 225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return cif->flags; 227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@-exportheader@*/ 230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void 231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_incoming_args_SYSV(char *stack, void **rvalue, 232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void **avalue, ffi_cif *cif) 233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@=exportheader@*/ 234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register unsigned int i; 236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register void **p_argv; 237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register char *argp; 238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project register ffi_type **p_arg; 239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = stack; 241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ( cif->flags == FFI_TYPE_STRUCT ) { 243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *rvalue = *(void **) argp; 244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp += 4; 245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv = avalue; 248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) 250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project { 251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t z; 252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project size_t alignment = (*p_arg)->alignment; 254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if (alignment < 4) 255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project alignment = 4; 256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* Align if necessary */ 257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project if ((alignment - 1) & (unsigned) argp) { 258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp = (char *) ALIGN(argp, alignment); 259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project z = (*p_arg)->size; 262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project /* because we're little endian, this is what it turns into. */ 264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *p_argv = (void*) argp; 266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project p_argv++; 268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project argp += z; 269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project } 270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return; 272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* How to make a trampoline. */ 275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ 277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ 278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int __fun = (unsigned int)(FUN); \ 279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project unsigned int __ctx = (unsigned int)(CTX); \ 280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ 281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ 282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ 283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int*) &__tramp[12] = __ctx; \ 284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *(unsigned int*) &__tramp[16] = __fun; \ 285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __clear_cache((&__tramp[0]), (&__tramp[19])); \ 286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project }) 287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* the cif must already be prep'ed */ 290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status 292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure, 293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project ffi_cif* cif, 294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void (*fun)(ffi_cif*,void*,void**,void*), 295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *user_data, 296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project void *codeloc) 297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ 298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_ASSERT (cif->abi == FFI_SYSV); 299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ 301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project &ffi_closure_SYSV, \ 302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project codeloc); 303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->cif = cif; 305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->user_data = user_data; 306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project closure->fun = fun; 307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project 308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project return FFI_OK; 309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} 310