1baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com/* ----------------------------------------------------------------------- 2baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_linux64.c - Copyright (C) 2013 IBM 3baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com Copyright (C) 2011 Anthony Green 4baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com Copyright (C) 2011 Kyle Moffett 5baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com Copyright (C) 2008 Red Hat, Inc 6baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com Copyright (C) 2007, 2008 Free Software Foundation, Inc 7baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com Copyright (c) 1998 Geoffrey Keating 8baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 9baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com PowerPC Foreign Function Interface 10baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 11baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com Permission is hereby granted, free of charge, to any person obtaining 12baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com a copy of this software and associated documentation files (the 13baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ``Software''), to deal in the Software without restriction, including 14baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com without limitation the rights to use, copy, modify, merge, publish, 15baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com distribute, sublicense, and/or sell copies of the Software, and to 16baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com permit persons to whom the Software is furnished to do so, subject to 17baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com the following conditions: 18baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 19baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com The above copyright notice and this permission notice shall be included 20baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com in all copies or substantial portions of the Software. 21baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 22baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 23baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR 26baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com OTHER DEALINGS IN THE SOFTWARE. 29baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ----------------------------------------------------------------------- */ 30baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 31baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#include "ffi.h" 32baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 33baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#ifdef POWERPC64 34baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#include "ffi_common.h" 35baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#include "ffi_powerpc.h" 36baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 37baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 38baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com/* About the LINUX64 ABI. */ 39baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comenum { 40baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com NUM_GPR_ARG_REGISTERS64 = 8, 41baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com NUM_FPR_ARG_REGISTERS64 = 13 42baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com}; 43baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comenum { ASM_NEEDS_REGISTERS64 = 4 }; 44baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 45baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 46baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 47baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com/* Adjust size of ffi_type_longdouble. */ 48baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comvoid FFI_HIDDEN 49baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_prep_types_linux64 (ffi_abi abi) 50baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 51baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((abi & (FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128)) == FFI_LINUX) 52baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 53baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type_longdouble.size = 8; 54baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type_longdouble.alignment = 8; 55baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 56baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 57baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 58baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type_longdouble.size = 16; 59baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type_longdouble.alignment = 16; 60baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 61baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 62baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 63baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 64baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 65baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 66baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comstatic unsigned int 67baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comdiscover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) 68baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 69baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com switch (t->type) 70baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 71baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_FLOAT: 72baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_DOUBLE: 73baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *elnum = 1; 74baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return (int) t->type; 75baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 76baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_STRUCT:; 77baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 78baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int base_elt = 0, total_elnum = 0; 79baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type **el = t->elements; 80baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com while (*el) 81baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 82baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int el_elt, el_elnum = 0; 83baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com el_elt = discover_homogeneous_aggregate (*el, &el_elnum); 84baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (el_elt == 0 85baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com || (base_elt && base_elt != el_elt)) 86baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return 0; 87baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com base_elt = el_elt; 88baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com total_elnum += el_elnum; 89baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (total_elnum > 8) 90baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return 0; 91baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com el++; 92baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 93baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *elnum = total_elnum; 94baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return base_elt; 95baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 96baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 97baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com default: 98baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return 0; 99baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 100baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 101baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 102baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 103baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 104baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com/* Perform machine dependent cif processing */ 105baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comstatic ffi_status 106baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_prep_cif_linux64_core (ffi_cif *cif) 107baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 108baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type **ptr; 109baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned bytes; 110baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned i, fparg_count = 0, intarg_count = 0; 111baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned flags = cif->flags; 112baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 113baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int elt, elnum; 114baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 115baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 116baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE 117baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* If compiled without long double support.. */ 118baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) 119baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_BAD_ABI; 120baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 121baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 122baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* The machine-independent calculation of cif->bytes doesn't work 123baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com for us. Redo the calculation. */ 124baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 125baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Space for backchain, CR, LR, TOC and the asm's temp regs. */ 126baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes = (4 + ASM_NEEDS_REGISTERS64) * sizeof (long); 127baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 128baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Space for the general registers. */ 129baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes += NUM_GPR_ARG_REGISTERS64 * sizeof (long); 130baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#else 131baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp 132baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com regs. */ 133baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long); 134baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 135baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Space for the mandatory parm save area and general registers. */ 136baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long); 137baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 138baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 139baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Return value handling. */ 140baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com switch (cif->rtype->type) 141baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 142baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 143baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_LONGDOUBLE: 144baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) 145baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_128BITS; 146baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Fall through. */ 147baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 148baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_DOUBLE: 149baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_64BITS; 150baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Fall through. */ 151baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_FLOAT: 152baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_FP; 153baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 154baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 155baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT128: 156baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_128BITS; 157baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Fall through. */ 158baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT64: 159baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT64: 160baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_64BITS; 161baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 162baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 163baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_STRUCT: 164baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 165baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com elt = discover_homogeneous_aggregate (cif->rtype, &elnum); 166baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (elt) 167baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 168baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (elt == FFI_TYPE_DOUBLE) 169baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_64BITS; 170baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST; 171baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 172baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 173baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (cif->rtype->size <= 16) 174baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 175baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_SMST; 176baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 177baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 178baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 179baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com intarg_count++; 180baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETVAL_REFERENCE; 181baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Fall through. */ 182baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_VOID: 183baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_RETURNS_NOTHING; 184baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 185baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 186baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com default: 187baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Returns 32-bit integer, or similar. Nothing to do here. */ 188baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 189baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 190baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 191baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) 192baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 193baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int align; 194baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 195baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com switch ((*ptr)->type) 196baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 197baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 198baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_LONGDOUBLE: 199baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) 200baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 201baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 202baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com intarg_count++; 203baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 204baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Fall through. */ 205baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 206baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_DOUBLE: 207baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_FLOAT: 208baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 209baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com intarg_count++; 210baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count > NUM_FPR_ARG_REGISTERS64) 211baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_ARG_NEEDS_PSAVE; 212baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 213baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 214baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_STRUCT: 215baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0) 216baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 217baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com align = (*ptr)->alignment; 218baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (align > 16) 219baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com align = 16; 220baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com align = align / 8; 221baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (align > 1) 222baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com intarg_count = ALIGN (intarg_count, align); 223baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 224baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com intarg_count += ((*ptr)->size + 7) / 8; 225baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 226baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com elt = discover_homogeneous_aggregate (*ptr, &elnum); 227baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (elt) 228baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 229baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count += elnum; 230baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count > NUM_FPR_ARG_REGISTERS64) 231baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_ARG_NEEDS_PSAVE; 232baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 233baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 234baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 235baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 236baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (intarg_count > NUM_GPR_ARG_REGISTERS64) 237baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_ARG_NEEDS_PSAVE; 238baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 239baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 240baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 241baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_POINTER: 242baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT64: 243baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT64: 244baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_INT: 245baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT32: 246baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT32: 247baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT16: 248baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT16: 249baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT8: 250baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT8: 251baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Everything else is passed as a 8-byte word in a GPR, either 252baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com the object itself or a pointer to it. */ 253baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com intarg_count++; 254baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (intarg_count > NUM_GPR_ARG_REGISTERS64) 255baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_ARG_NEEDS_PSAVE; 256baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 257baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com default: 258baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (0); 259baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 260baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 261baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 262baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count != 0) 263baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_FP_ARGUMENTS; 264baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (intarg_count > 4) 265baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flags |= FLAG_4_GPR_ARGUMENTS; 266baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 267baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Space for the FPR registers, if needed. */ 268baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count != 0) 269baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double); 270baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 271baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Stack space. */ 272baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 273baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((flags & FLAG_ARG_NEEDS_PSAVE) != 0) 274baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes += intarg_count * sizeof (long); 275baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#else 276baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (intarg_count > NUM_GPR_ARG_REGISTERS64) 277baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long); 278baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 279baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 280baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* The stack space allocated needs to be a multiple of 16 bytes. */ 281baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com bytes = (bytes + 15) & ~0xF; 282baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 283baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->flags = flags; 284baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->bytes = bytes; 285baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 286baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_OK; 287baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 288baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 289baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_status FFI_HIDDEN 290baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_prep_cif_linux64 (ffi_cif *cif) 291baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 292baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX) != 0) 293baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->nfixedargs = cif->nargs; 294baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF != 2 295baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else if (cif->abi == FFI_COMPAT_LINUX64) 296baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 297baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* This call is from old code. Don't touch cif->nfixedargs 298baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com since old code will be using a smaller cif. */ 299baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->flags |= FLAG_COMPAT; 300baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Translate to new abi value. */ 301baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128; 302baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 303baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 304baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 305baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_BAD_ABI; 306baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return ffi_prep_cif_linux64_core (cif); 307baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 308baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 309baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_status FFI_HIDDEN 310baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_prep_cif_linux64_var (ffi_cif *cif, 311baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int nfixedargs, 312baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int ntotalargs MAYBE_UNUSED) 313baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 314baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX) != 0) 315baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->nfixedargs = nfixedargs; 316baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF != 2 317baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else if (cif->abi == FFI_COMPAT_LINUX64) 318baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 319baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* This call is from old code. Don't touch cif->nfixedargs 320baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com since old code will be using a smaller cif. */ 321baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->flags |= FLAG_COMPAT; 322baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Translate to new abi value. */ 323baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128; 324baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 325baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 326baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 327baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_BAD_ABI; 328baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 329baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif->flags |= FLAG_ARG_NEEDS_PSAVE; 330baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 331baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return ffi_prep_cif_linux64_core (cif); 332baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 333baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 334baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 335baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com/* ffi_prep_args64 is called by the assembly routine once stack space 336baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com has been allocated for the function's arguments. 337baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 338baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com The stack layout we want looks like this: 339baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 340baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Ret addr from ffi_call_LINUX64 8bytes | higher addresses 341baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| 342baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | CR save area 8bytes | 343baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| 344baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Previous backchain pointer 8 | stack pointer here 345baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------|<+ <<< on entry to 346baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Saved r28-r31 4*8 | | ffi_call_LINUX64 347baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | 348baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | GPR registers r3-r10 8*8 | | 349baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | 350baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | FPR registers f1-f13 (optional) 13*8 | | 351baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | 352baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Parameter save area | | 353baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | 354baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | TOC save area 8 | | 355baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | stack | 356baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Linker doubleword 8 | | grows | 357baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | down V 358baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Compiler doubleword 8 | | 359baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | lower addresses 360baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Space for callee's LR 8 | | 361baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | 362baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | CR save area 8 | | 363baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| | stack pointer here 364baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com | Current backchain pointer 8 |-/ during 365baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com |--------------------------------------------| <<< ffi_call_LINUX64 366baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 367baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com*/ 368baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 369baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comvoid FFI_HIDDEN 370baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) 371baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 372baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com const unsigned long bytes = ecif->cif->bytes; 373baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com const unsigned long flags = ecif->cif->flags; 374baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 375baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com typedef union 376baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 377baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com char *c; 378baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long *ul; 379baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com float *f; 380baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double *d; 381baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com size_t p; 382baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } valp; 383baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 384baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* 'stacktop' points at the previous backchain pointer. */ 385baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com valp stacktop; 386baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 387baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* 'next_arg' points at the space for gpr3, and grows upwards as 388baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com we use GPR registers, then continues at rest. */ 389baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com valp gpr_base; 390baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com valp gpr_end; 391baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com valp rest; 392baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com valp next_arg; 393baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 394baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* 'fpr_base' points at the space for fpr3, and grows upwards as 395baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com we use FPR registers. */ 396baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com valp fpr_base; 397baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int fparg_count; 398baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 399baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int i, words, nargs, nfixedargs; 400baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type **ptr; 401baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double double_tmp; 402baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com union 403baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 404baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void **v; 405baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com char **c; 406baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com signed char **sc; 407baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned char **uc; 408baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com signed short **ss; 409baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned short **us; 410baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com signed int **si; 411baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int **ui; 412baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long **ul; 413baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com float **f; 414baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double **d; 415baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } p_argv; 416baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long gprvalue; 417baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long align; 418baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 419baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com stacktop.c = (char *) stack + bytes; 420baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64; 421baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64; 422baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 423baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com rest.ul = stack + 4 + NUM_GPR_ARG_REGISTERS64; 424baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#else 425baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64; 426baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 427baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64; 428baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count = 0; 429baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul = gpr_base.ul; 430baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 431baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Check that everything starts aligned properly. */ 432baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0); 433baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0); 434baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT ((bytes & 0xF) == 0); 435baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 436baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Deal with return values that are actually pass-by-reference. */ 437baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (flags & FLAG_RETVAL_REFERENCE) 438baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue; 439baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 440baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Now for the arguments. */ 441baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com p_argv.v = ecif->avalue; 442baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com nargs = ecif->cif->nargs; 443baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF != 2 444baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com nfixedargs = (unsigned) -1; 445baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((flags & FLAG_COMPAT) == 0) 446baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 447baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com nfixedargs = ecif->cif->nfixedargs; 448baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com for (ptr = ecif->cif->arg_types, i = 0; 449baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com i < nargs; 450baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com i++, ptr++, p_argv.v++) 451baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 452baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 453baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int elt, elnum; 454baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 455baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 456baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com switch ((*ptr)->type) 457baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 458baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 459baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_LONGDOUBLE: 460baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) 461baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 462baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double_tmp = (*p_argv.d)[0]; 463baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) 464baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 465baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *fpr_base.d++ = double_tmp; 466baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com# if _CALL_ELF != 2 467baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((flags & FLAG_COMPAT) != 0) 468baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.d = double_tmp; 469baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com# endif 470baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 471baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 472baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.d = double_tmp; 473baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (++next_arg.ul == gpr_end.ul) 474baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul = rest.ul; 475baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 476baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double_tmp = (*p_argv.d)[1]; 477baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) 478baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 479baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *fpr_base.d++ = double_tmp; 480baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com# if _CALL_ELF != 2 481baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((flags & FLAG_COMPAT) != 0) 482baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.d = double_tmp; 483baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com# endif 484baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 485baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 486baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.d = double_tmp; 487baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (++next_arg.ul == gpr_end.ul) 488baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul = rest.ul; 489baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 490baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (__LDBL_MANT_DIG__ == 106); 491baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); 492baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 493baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 494baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Fall through. */ 495baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 496baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_DOUBLE: 497baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double_tmp = **p_argv.d; 498baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) 499baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 500baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *fpr_base.d++ = double_tmp; 501baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF != 2 502baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((flags & FLAG_COMPAT) != 0) 503baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.d = double_tmp; 504baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 505baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 506baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 507baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.d = double_tmp; 508baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (++next_arg.ul == gpr_end.ul) 509baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul = rest.ul; 510baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 511baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); 512baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 513baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 514baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_FLOAT: 515baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double_tmp = **p_argv.f; 516baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) 517baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 518baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *fpr_base.d++ = double_tmp; 519baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF != 2 520baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((flags & FLAG_COMPAT) != 0) 521baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.f = (float) double_tmp; 522baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 523baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 524baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 525baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.f = (float) double_tmp; 526baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (++next_arg.ul == gpr_end.ul) 527baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul = rest.ul; 528baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 529baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); 530baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 531baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 532baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_STRUCT: 533baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((ecif->cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0) 534baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 535baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com align = (*ptr)->alignment; 536baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (align > 16) 537baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com align = 16; 538baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (align > 1) 539baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.p = ALIGN (next_arg.p, align); 540baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 541baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 542baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com elt = discover_homogeneous_aggregate (*ptr, &elnum); 543baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (elt) 544baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 545baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com union { 546baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void *v; 547baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com float *f; 548baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double *d; 549baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } arg; 550baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 551baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com arg.v = *p_argv.v; 552baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (elt == FFI_TYPE_FLOAT) 553baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 554baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com do 555baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 556baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double_tmp = *arg.f++; 557baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count < NUM_FPR_ARG_REGISTERS64 558baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com && i < nfixedargs) 559baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *fpr_base.d++ = double_tmp; 560baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 561baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.f = (float) double_tmp; 562baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (++next_arg.f == gpr_end.f) 563baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.f = rest.f; 564baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 565baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 566baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com while (--elnum != 0); 567baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((next_arg.p & 3) != 0) 568baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 569baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (++next_arg.f == gpr_end.f) 570baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.f = rest.f; 571baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 572baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 573baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 574baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com do 575baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 576baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double_tmp = *arg.d++; 577baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) 578baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *fpr_base.d++ = double_tmp; 579baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 580baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.d = double_tmp; 581baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (++next_arg.d == gpr_end.d) 582baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.d = rest.d; 583baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com fparg_count++; 584baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 585baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com while (--elnum != 0); 586baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 587baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 588baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 589baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 590baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com words = ((*ptr)->size + 7) / 8; 591baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) 592baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 593baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com size_t first = gpr_end.c - next_arg.c; 594baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com memcpy (next_arg.c, *p_argv.c, first); 595baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first); 596baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.c = rest.c + words * 8 - first; 597baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 598baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 599baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 600baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com char *where = next_arg.c; 601baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 602baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#ifndef __LITTLE_ENDIAN__ 603baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Structures with size less than eight bytes are passed 604baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com left-padded. */ 605baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((*ptr)->size < 8) 606baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com where += 8 - (*ptr)->size; 607baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 608baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com memcpy (where, *p_argv.c, (*ptr)->size); 609baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul += words; 610baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (next_arg.ul == gpr_end.ul) 611baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul = rest.ul; 612baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 613baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 614baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 615baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 616baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT8: 617baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gprvalue = **p_argv.uc; 618baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com goto putgpr; 619baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT8: 620baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gprvalue = **p_argv.sc; 621baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com goto putgpr; 622baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT16: 623baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gprvalue = **p_argv.us; 624baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com goto putgpr; 625baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT16: 626baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gprvalue = **p_argv.ss; 627baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com goto putgpr; 628baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT32: 629baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gprvalue = **p_argv.ui; 630baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com goto putgpr; 631baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_INT: 632baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT32: 633baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gprvalue = **p_argv.si; 634baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com goto putgpr; 635baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 636baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT64: 637baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT64: 638baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_POINTER: 639baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com gprvalue = **p_argv.ul; 640baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com putgpr: 641baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *next_arg.ul++ = gprvalue; 642baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (next_arg.ul == gpr_end.ul) 643baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com next_arg.ul = rest.ul; 644baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 645baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 646baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 647baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 648baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS 649baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com || (next_arg.ul >= gpr_base.ul 650baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com && next_arg.ul <= gpr_base.ul + 4)); 651baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 652baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 653baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 654baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 655baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#define MIN_CACHE_LINE_SIZE 8 656baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 657baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comstatic void 658baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comflush_icache (char *wraddr, char *xaddr, int size) 659baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 660baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com int i; 661baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) 662baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" 663baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com : : "r" (xaddr + i), "r" (wraddr + i) : "memory"); 664baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;" 665baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com : : "r"(xaddr + size - 1), "r"(wraddr + size - 1) 666baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com : "memory"); 667baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 668baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 669baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 670baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_status 671baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_prep_closure_loc_linux64 (ffi_closure *closure, 672baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_cif *cif, 673baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void (*fun) (ffi_cif *, void *, void **, void *), 674baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void *user_data, 675baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void *codeloc) 676baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 677baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 678baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int *tramp = (unsigned int *) &closure->tramp[0]; 679baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 680baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI) 681baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_BAD_ABI; 682baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 683baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com tramp[0] = 0xe96c0018; /* 0: ld 11,2f-0b(12) */ 684baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com tramp[1] = 0xe98c0010; /* ld 12,1f-0b(12) */ 685baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com tramp[2] = 0x7d8903a6; /* mtctr 12 */ 686baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com tramp[3] = 0x4e800420; /* bctr */ 687baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* 1: .quad function_addr */ 688baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* 2: .quad context */ 689baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *(void **) &tramp[4] = (void *) ffi_closure_LINUX64; 690baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *(void **) &tramp[6] = codeloc; 691baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); 692baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#else 693baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void **tramp = (void **) &closure->tramp[0]; 694baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 695baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI) 696baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_BAD_ABI; 697baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 698baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Copy function address and TOC from ffi_closure_LINUX64. */ 699baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com memcpy (tramp, (char *) ffi_closure_LINUX64, 16); 700baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com tramp[2] = tramp[1]; 701baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com tramp[1] = codeloc; 702baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 703baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 704baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com closure->cif = cif; 705baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com closure->fun = fun; 706baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com closure->user_data = user_data; 707baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 708baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_OK; 709baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 710baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 711baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 712baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comint FFI_HIDDEN 713baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.comffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, 714baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long *pst, ffi_dblfl *pfr) 715baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com{ 716baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* rvalue is the pointer to space for return value in closure assembly */ 717baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* pst is the pointer to parameter save area 718baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */ 719baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */ 720baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 721baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void **avalue; 722baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_type **arg_types; 723baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long i, avn, nfixedargs; 724baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_cif *cif; 725baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; 726baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long align; 727baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 728baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com cif = closure->cif; 729baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue = alloca (cif->nargs * sizeof (void *)); 730baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 731baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Copy the caller's structure return value address so that the 732baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com closure returns the data directly to the caller. */ 733baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (cif->rtype->type == FFI_TYPE_STRUCT 734baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com && (cif->flags & FLAG_RETURNS_SMST) == 0) 735baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 736baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com rvalue = (void *) *pst; 737baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst++; 738baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 739baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 740baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com i = 0; 741baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avn = cif->nargs; 742baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF != 2 743baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com nfixedargs = (unsigned) -1; 744baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->flags & FLAG_COMPAT) == 0) 745baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 746baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com nfixedargs = cif->nfixedargs; 747baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com arg_types = cif->arg_types; 748baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 749baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Grab the addresses of the arguments from the stack frame. */ 750baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com while (i < avn) 751baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 752baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned int elt, elnum; 753baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 754baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com switch (arg_types[i]->type) 755baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 756baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT8: 757baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT8: 758baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#ifndef __LITTLE_ENDIAN__ 759baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = (char *) pst + 7; 760baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst++; 761baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 762baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 763baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 764baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT16: 765baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT16: 766baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#ifndef __LITTLE_ENDIAN__ 767baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = (char *) pst + 6; 768baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst++; 769baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 770baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 771baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 772baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT32: 773baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT32: 774baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#ifndef __LITTLE_ENDIAN__ 775baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = (char *) pst + 4; 776baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst++; 777baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 778baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 779baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 780baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_SINT64: 781baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_UINT64: 782baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_POINTER: 783baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pst; 784baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst++; 785baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 786baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 787baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_STRUCT: 788baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0) 789baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 790baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com align = arg_types[i]->alignment; 791baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (align > 16) 792baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com align = 16; 793baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (align > 1) 794baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst = (unsigned long *) ALIGN ((size_t) pst, align); 795baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 796baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com elt = 0; 797baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if _CALL_ELF == 2 798baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com elt = discover_homogeneous_aggregate (arg_types[i], &elnum); 799baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 800baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (elt) 801baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 802baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com union { 803baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com void *v; 804baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com unsigned long *ul; 805baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com float *f; 806baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com double *d; 807baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com size_t p; 808baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } to, from; 809baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 810baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Repackage the aggregate from its parts. The 811baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com aggregate size is not greater than the space taken by 812baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com the registers so store back to the register/parameter 813baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com save arrays. */ 814baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (pfr + elnum <= end_pfr) 815baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com to.v = pfr; 816baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 817baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com to.v = pst; 818baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 819baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = to.v; 820baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com from.ul = pst; 821baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (elt == FFI_TYPE_FLOAT) 822baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 823baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com do 824baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 825baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (pfr < end_pfr && i < nfixedargs) 826baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 827baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *to.f = (float) pfr->d; 828baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pfr++; 829baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 830baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 831baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *to.f = *from.f; 832baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com to.f++; 833baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com from.f++; 834baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 835baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com while (--elnum != 0); 836baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 837baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 838baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 839baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com do 840baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 841baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (pfr < end_pfr && i < nfixedargs) 842baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 843baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *to.d = pfr->d; 844baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pfr++; 845baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 846baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 847baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *to.d = *from.d; 848baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com to.d++; 849baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com from.d++; 850baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 851baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com while (--elnum != 0); 852baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 853baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 854baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 855baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 856baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#ifndef __LITTLE_ENDIAN__ 857baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Structures with size less than eight bytes are passed 858baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com left-padded. */ 859baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (arg_types[i]->size < 8) 860baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = (char *) pst + 8 - arg_types[i]->size; 861baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 862baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 863baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pst; 864baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 865baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst += (arg_types[i]->size + 7) / 8; 866baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 867baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 868baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 869baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_LONGDOUBLE: 870baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) 871baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 872baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (pfr + 1 < end_pfr && i + 1 < nfixedargs) 873baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 874baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pfr; 875baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pfr += 2; 876baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 877baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 878baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 879baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (pfr < end_pfr && i < nfixedargs) 880baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 881baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Passed partly in f13 and partly on the stack. 882baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com Move it all to the stack. */ 883baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com *pst = *(unsigned long *) pfr; 884baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pfr++; 885baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 886baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pst; 887baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 888baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst += 2; 889baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 890baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 891baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Fall through. */ 892baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 893baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_DOUBLE: 894baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* On the outgoing stack all values are aligned to 8 */ 895baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* there are 13 64bit floating point registers */ 896baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 897baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (pfr < end_pfr && i < nfixedargs) 898baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 899baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pfr; 900baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pfr++; 901baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 902baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 903baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pst; 904baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst++; 905baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 906baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 907baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com case FFI_TYPE_FLOAT: 908baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if (pfr < end_pfr && i < nfixedargs) 909baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 910baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Float values are stored as doubles in the 911baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com ffi_closure_LINUX64 code. Fix them here. */ 912baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pfr->f = (float) pfr->d; 913baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pfr; 914baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pfr++; 915baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 916baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 917baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com avalue[i] = pst; 918baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com pst++; 919baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com break; 920baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 921baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com default: 922baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com FFI_ASSERT (0); 923baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 924baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 925baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com i++; 926baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 927baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 928baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 929baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com (closure->fun) (cif, rvalue, avalue, closure->user_data); 930baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com 931baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com /* Tell ffi_closure_LINUX64 how to perform return type promotions. */ 932baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->flags & FLAG_RETURNS_SMST) != 0) 933baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com { 934baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com if ((cif->flags & FLAG_RETURNS_FP) == 0) 935baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1; 936baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else if ((cif->flags & FLAG_RETURNS_64BITS) != 0) 937baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_V2_TYPE_DOUBLE_HOMOG; 938baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com else 939baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return FFI_V2_TYPE_FLOAT_HOMOG; 940baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com } 941baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com return cif->rtype->type; 942baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com} 943baa84b827b80380ff181757e2997e5648e69b1e4doko@ubuntu.com#endif 944