1457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* ----------------------------------------------------------------------- 2457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>, 3457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Paulo Pizarro <paulo.pizarro@gmail.com> 4457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 5457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Blackfin Foreign Function Interface 6457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 7457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique Permission is hereby granted, free of charge, to any person obtaining 8457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique a copy of this software and associated documentation files (the 9457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ``Software''), to deal in the Software without restriction, including 10457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique without limitation the rights to use, copy, modify, merge, publish, 11457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique distribute, sublicense, and/or sell copies of the Software, and to 12457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique permit persons to whom the Software is furnished to do so, subject to 13457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique the following conditions: 14457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 15457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique The above copyright notice and this permission notice shall be included 16457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique in all copies or substantial portions of the Software. 17457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 18457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique DEALINGS IN THE SOFTWARE. 26457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ----------------------------------------------------------------------- */ 27457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi.h> 28457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi_common.h> 29457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 30457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdlib.h> 31457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdio.h> 32457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 33457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Maximum number of GPRs available for argument passing. */ 34457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define MAX_GPRARGS 3 35457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 36457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* 37457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * Return types 38457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique */ 39457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define FFIBFIN_RET_VOID 0 40457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define FFIBFIN_RET_BYTE 1 41457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define FFIBFIN_RET_HALFWORD 2 42457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define FFIBFIN_RET_INT64 3 43457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define FFIBFIN_RET_INT32 4 44457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 45457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/*====================================================================*/ 46457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* PROTOTYPE * 47457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /*====================================================================*/ 48457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid ffi_prep_args(unsigned char *, extended_cif *); 49457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 50457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/*====================================================================*/ 51457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Externals */ 52457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* (Assembly) */ 53457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/*====================================================================*/ 54457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 55457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void ffi_call_SYSV(unsigned, extended_cif *, void(*)(unsigned char *, extended_cif *), unsigned, void *, void(*fn)(void)); 56457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 57457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/*====================================================================*/ 58457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Implementation */ 59457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* */ 60457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/*====================================================================*/ 61457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 62457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 63457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* 64457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * This function calculates the return type (size) based on type. 65457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique */ 66457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 67457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status ffi_prep_cif_machdep(ffi_cif *cif) 68457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 69457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique /* --------------------------------------* 70457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * Return handling * 71457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * --------------------------------------*/ 72457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (cif->rtype->type) { 73457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_VOID: 74457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_VOID; 75457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 76457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 77457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 78457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_HALFWORD; 79457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 80457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: 81457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_BYTE; 82457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 83457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_INT: 84457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT32: 85457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT32: 86457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_FLOAT: 87457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_POINTER: 88457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: 89457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_INT32; 90457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 91457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT64: 92457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT64: 93457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_DOUBLE: 94457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_INT64; 95457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 96457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 97457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (cif->rtype->size <= 4){ 98457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_INT32; 99457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique }else if (cif->rtype->size == 8){ 100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_INT64; 101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique }else{ 102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique //it will return via a hidden pointer in P0 103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique cif->flags = FFIBFIN_RET_VOID; 104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT(0); 108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique return FFI_OK; 111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* 114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * This will prepare the arguments and will call the assembly routine 115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * cif = the call interface 116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * fn = the function to be called 117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * rvalue = the return value 118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique * avalue = the arguments 119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique */ 120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue) 121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique int ret_type = cif->flags; 123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique extended_cif ecif; 124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.cif = cif; 125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.avalue = avalue; 126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ecif.rvalue = rvalue; 127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch (cif->abi) { 129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_SYSV: 130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_call_SYSV(cif->bytes, &ecif, ffi_prep_args, ret_type, ecif.rvalue, fn); 131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT(0); 134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* 140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique* This function prepares the parameters (copies them from the ecif to the stack) 141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique* to call the function (ffi_prep_args is called by the assembly routine in file 142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique* sysv.S, which also calls the actual function) 143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique*/ 144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid ffi_prep_args(unsigned char *stack, extended_cif *ecif) 145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique register unsigned int i = 0; 147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique void **p_argv; 148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned char *argp; 149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique ffi_type **p_arg; 150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique argp = stack; 151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique p_argv = ecif->avalue; 152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; 153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique (i != 0); 154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique i--, p_arg++) { 155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique size_t z; 156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique z = (*p_arg)->size; 157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique if (z < sizeof(int)) { 158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique z = sizeof(int); 159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique switch ((*p_arg)->type) { 160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT8: { 161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique signed char v = *(SINT8 *)(* p_argv); 162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique signed int t = v; 163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(signed int *) argp = t; 164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT8: { 167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned char v = *(UINT8 *)(* p_argv); 168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique unsigned int t = v; 169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(unsigned int *) argp = t; 170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_SINT16: 173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(signed int *) argp = (signed int) * (SINT16 *)(* p_argv); 174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_UINT16: 176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(unsigned int *) argp = (unsigned int) * (UINT16 *)(* p_argv); 177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique case FFI_TYPE_STRUCT: 179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy(argp, *p_argv, (*p_arg)->size); 180457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 181457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique default: 182457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique FFI_ASSERT(0); 183457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique break; 184457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 185457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } else if (z == sizeof(int)) { 186457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique *(unsigned int *) argp = (unsigned int) * (UINT32 *)(* p_argv); 187457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } else { 188457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique memcpy(argp, *p_argv, z); 189457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 190457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique p_argv++; 191457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique argp += z; 192457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique } 193457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique} 194457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 195457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 196457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique 197