1457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* ----------------------------------------------------------------------- 2457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi.c - Copyright (c) 2014 Sebastian Macke <sebastian@macke.de> 3457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 4457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique OpenRISC Foreign Function Interface 5457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 6457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Permission is hereby granted, free of charge, to any person obtaining 7457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique a copy of this software and associated documentation files (the 8457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ``Software''), to deal in the Software without restriction, including 9457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique without limitation the rights to use, copy, modify, merge, publish, 10457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique distribute, sublicense, and/or sell copies of the Software, and to 11457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique permit persons to whom the Software is furnished to do so, subject to 12457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the following conditions: 13457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 14457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique The above copyright notice and this permission notice shall be included 15457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique in all copies or substantial portions of the Software. 16457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 17457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 18457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique DEALINGS IN THE SOFTWARE. 25457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ----------------------------------------------------------------------- */ 26457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 27457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi.h> 28457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include "ffi_common.h" 29457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 30457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* ffi_prep_args is called by the assembly routine once stack space 31457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique has been allocated for the function's arguments */ 32457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 33457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid* ffi_prep_args(char *stack, extended_cif *ecif) 34457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 35457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique char *stacktemp = stack; 36457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int i, s; 37457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type **arg; 38457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int count = 0; 39457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int nfixedargs; 40457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 41457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique nfixedargs = ecif->cif->nfixedargs; 42457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique arg = ecif->cif->arg_types; 43457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void **argv = ecif->avalue; 44457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 45457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) 46457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 47457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(void **) stack = ecif->rvalue; 48457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack += 4; 49457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count = 4; 50457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 51457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for(i=0; i<ecif->cif->nargs; i++) 52457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 53457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 54457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* variadic args are saved on stack */ 55457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if ((nfixedargs == 0) && (count < 24)) 56457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 57457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count = 24; 58457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack = stacktemp + 24; 59457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 60457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique nfixedargs--; 61457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 62457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique s = 4; 63457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch((*arg)->type) 64457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 65457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 66457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(void **)stack = *argv; 67457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 68457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 69457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 70457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(signed int *) stack = (signed int)*(SINT8 *)(* argv); 71457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 72457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 73457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 74457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(unsigned int *) stack = (unsigned int)*(UINT8 *)(* argv); 75457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 76457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 77457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 78457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(signed int *) stack = (signed int)*(SINT16 *)(* argv); 79457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 80457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 81457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 82457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(unsigned int *) stack = (unsigned int)*(UINT16 *)(* argv); 83457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 84457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 85457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 86457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 87457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 88457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 89457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(int *)stack = *(int*)(*argv); 90457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 91457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 92457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: /* 8 byte types */ 93457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (count == 20) /* never split arguments */ 94457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 95457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack += 4; 96457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count += 4; 97457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 98457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique s = (*arg)->size; 99457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy(stack, *argv, s); 100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique stack += s; 104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count += s; 105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique argv++; 106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique arg++; 107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return stacktemp + ((count>24)?24:0); 109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void ffi_call_SYSV(unsigned, 112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique extended_cif *, 113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *(*)(int *, extended_cif *), 114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned *, 115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void (*fn)(void), 116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned); 117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) 120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int i; 122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int size; 123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type **arg; 124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Calculate size to allocate on stack */ 126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for(i = 0, arg = cif->arg_types, size=0; i < cif->nargs; i++, arg++) 128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if ((*arg)->type == FFI_TYPE_STRUCT) 130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size += 4; 131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if ((*arg)->size <= 4) 133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size += 4; 134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size += 8; 136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* for variadic functions more space is needed on the stack */ 139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->nargs != cif->nfixedargs) 140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size += 24; 141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->rtype->type == FFI_TYPE_STRUCT) 143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size += 4; 144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique extended_cif ecif; 147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.cif = cif; 148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.avalue = avalue; 149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.rvalue = rvalue; 150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (cif->abi) 152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_SYSV: 154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_call_SYSV(size, &ecif, ffi_prep_args, rvalue, fn, cif->flags); 155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT(0); 158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid ffi_closure_SYSV(unsigned long r3, unsigned long r4, unsigned long r5, 164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned long r6, unsigned long r7, unsigned long r8) 165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique register int *sp __asm__ ("r17"); 167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique register int *r13 __asm__ ("r13"); 168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_closure* closure = (ffi_closure*) r13; 170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique char *stack_args = sp; 171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Lay the register arguments down in a continuous chunk of memory. */ 173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned register_args[6] = 174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { r3, r4, r5, r6, r7, r8 }; 175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Pointer to a struct return value. */ 177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *struct_rvalue = (void *) r3; 178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_cif *cif = closure->cif; 180457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type **arg_types = cif->arg_types; 181457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void **avalue = alloca (cif->nargs * sizeof(void *)); 182457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique char *ptr = (char *) register_args; 183457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int count = 0; 184457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int nfixedargs = cif->nfixedargs; 185457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int i; 186457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 187457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* preserve struct type return pointer passing */ 188457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 189457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) 190457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 191457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ptr += 4; 192457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count = 4; 193457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 194457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 195457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* Find the address of each argument. */ 196457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = 0; i < cif->nargs; i++) 197457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 198457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 199457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* variadic args are saved on stack */ 200457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if ((nfixedargs == 0) && (count < 24)) 201457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 202457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ptr = stack_args; 203457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count = 24; 204457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 205457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique nfixedargs--; 206457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 207457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (arg_types[i]->type) 208457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 209457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 210457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 211457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = ptr + 3; 212457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 213457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 214457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 215457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 216457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = ptr + 2; 217457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 218457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 219457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 220457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 221457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 222457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 223457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = ptr; 224457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 225457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 226457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 227457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = *(void**)ptr; 228457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 229457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 230457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 231457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* 8-byte values */ 232457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 233457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* arguments are never splitted */ 234457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (ptr == ®ister_args[5]) 235457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ptr = stack_args; 236457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique avalue[i] = ptr; 237457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ptr += 4; 238457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count += 4; 239457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 240457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 241457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ptr += 4; 242457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique count += 4; 243457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 244457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* If we've handled more arguments than fit in registers, 245457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique start looking at the those passed on the stack. */ 246457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 247457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (count == 24) 248457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ptr = stack_args; 249457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 250457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 251457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT)) 252457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 253457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique (closure->fun) (cif, struct_rvalue, avalue, closure->user_data); 254457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } else 255457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique { 256457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique long long rvalue; 257457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique (closure->fun) (cif, &rvalue, avalue, closure->user_data); 258457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->rtype) 259457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique asm ("l.ori r12, %0, 0x0\n l.lwz r11, 0(r12)\n l.lwz r12, 4(r12)" : : "r" (&rvalue)); 260457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 261457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 262457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 263457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 264457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status 265457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_prep_closure_loc (ffi_closure* closure, 266457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_cif* cif, 267457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void (*fun)(ffi_cif*,void*,void**,void*), 268457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *user_data, 269457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void *codeloc) 270457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 271457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned short *tramp = (unsigned short *) closure->tramp; 272457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned long fn = (unsigned long) ffi_closure_SYSV; 273457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned long cls = (unsigned long) codeloc; 274457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 275457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->abi != FFI_SYSV) 276457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_BAD_ABI; 277457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 278457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->cif = cif; 279457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->user_data = user_data; 280457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique closure->fun = fun; 281457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 282457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* write pointers to temporary registers */ 283457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[0] = (0x6 << 10) | (13 << 5); /* l.movhi r13, ... */ 284457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[1] = cls >> 16; 285457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[2] = (0x2a << 10) | (13 << 5) | 13; /* l.ori r13, r13, ... */ 286457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[3] = cls & 0xFFFF; 287457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 288457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[4] = (0x6 << 10) | (15 << 5); /* l.movhi r15, ... */ 289457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[5] = fn >> 16; 290457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[6] = (0x2a << 10) | (15 << 5) | 15; /* l.ori r15, r15 ... */ 291457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[7] = fn & 0xFFFF; 292457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 293457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[8] = (0x11 << 10); /* l.jr r15 */ 294457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[9] = 15 << 11; 295457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 296457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[10] = (0x2a << 10) | (17 << 5) | 1; /* l.ori r17, r1, ... */ 297457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique tramp[11] = 0x0; 298457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 299457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_OK; 300457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 301457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 302457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 303457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status ffi_prep_cif_machdep (ffi_cif *cif) 304457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 305457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = 0; 306457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 307457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* structures are returned as pointers */ 308457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->rtype->type == FFI_TYPE_STRUCT) 309457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFI_TYPE_STRUCT; 310457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique else 311457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->rtype->size > 4) 312457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFI_TYPE_UINT64; 313457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 314457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->nfixedargs = cif->nargs; 315457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 316457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_OK; 317457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 318457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 319457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 320457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, 321457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned int nfixedargs, unsigned int ntotalargs) 322457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 323457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_status status; 324457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 325457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique status = ffi_prep_cif_machdep (cif); 326457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->nfixedargs = nfixedargs; 327457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return status; 328457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 329