diff options
Diffstat (limited to 'ext/ffi_c/libffi/src/bfin')
-rw-r--r-- | ext/ffi_c/libffi/src/bfin/ffi.c | 196 | ||||
-rw-r--r-- | ext/ffi_c/libffi/src/bfin/ffitarget.h | 43 | ||||
-rw-r--r-- | ext/ffi_c/libffi/src/bfin/sysv.S | 179 |
3 files changed, 418 insertions, 0 deletions
diff --git a/ext/ffi_c/libffi/src/bfin/ffi.c b/ext/ffi_c/libffi/src/bfin/ffi.c new file mode 100644 index 0000000..22a2acd --- /dev/null +++ b/ext/ffi_c/libffi/src/bfin/ffi.c @@ -0,0 +1,196 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>, + Paulo Pizarro <paulo.pizarro@gmail.com> + + Blackfin Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> +#include <stdio.h> + +/* Maximum number of GPRs available for argument passing. */ +#define MAX_GPRARGS 3 + +/* + * Return types + */ +#define FFIBFIN_RET_VOID 0 +#define FFIBFIN_RET_BYTE 1 +#define FFIBFIN_RET_HALFWORD 2 +#define FFIBFIN_RET_INT64 3 +#define FFIBFIN_RET_INT32 4 + +/*====================================================================*/ +/* PROTOTYPE * + /*====================================================================*/ +void ffi_prep_args(unsigned char *, extended_cif *); + +/*====================================================================*/ +/* Externals */ +/* (Assembly) */ +/*====================================================================*/ + +extern void ffi_call_SYSV(unsigned, extended_cif *, void(*)(unsigned char *, extended_cif *), unsigned, void *, void(*fn)(void)); + +/*====================================================================*/ +/* Implementation */ +/* */ +/*====================================================================*/ + + +/* + * This function calculates the return type (size) based on type. + */ + +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* --------------------------------------* + * Return handling * + * --------------------------------------*/ + switch (cif->rtype->type) { + case FFI_TYPE_VOID: + cif->flags = FFIBFIN_RET_VOID; + break; + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + cif->flags = FFIBFIN_RET_HALFWORD; + break; + case FFI_TYPE_UINT8: + cif->flags = FFIBFIN_RET_BYTE; + break; + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_FLOAT: + case FFI_TYPE_POINTER: + case FFI_TYPE_SINT8: + cif->flags = FFIBFIN_RET_INT32; + break; + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_DOUBLE: + cif->flags = FFIBFIN_RET_INT64; + break; + case FFI_TYPE_STRUCT: + if (cif->rtype->size <= 4){ + cif->flags = FFIBFIN_RET_INT32; + }else if (cif->rtype->size == 8){ + cif->flags = FFIBFIN_RET_INT64; + }else{ + //it will return via a hidden pointer in P0 + cif->flags = FFIBFIN_RET_VOID; + } + break; + default: + FFI_ASSERT(0); + break; + } + return FFI_OK; +} + +/* + * This will prepare the arguments and will call the assembly routine + * cif = the call interface + * fn = the function to be called + * rvalue = the return value + * avalue = the arguments + */ +void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue) +{ + int ret_type = cif->flags; + extended_cif ecif; + ecif.cif = cif; + ecif.avalue = avalue; + ecif.rvalue = rvalue; + + switch (cif->abi) { + case FFI_SYSV: + ffi_call_SYSV(cif->bytes, &ecif, ffi_prep_args, ret_type, ecif.rvalue, fn); + break; + default: + FFI_ASSERT(0); + break; + } +} + + +/* +* This function prepares the parameters (copies them from the ecif to the stack) +* to call the function (ffi_prep_args is called by the assembly routine in file +* sysv.S, which also calls the actual function) +*/ +void ffi_prep_args(unsigned char *stack, extended_cif *ecif) +{ + register unsigned int i = 0; + void **p_argv; + unsigned char *argp; + ffi_type **p_arg; + argp = stack; + p_argv = ecif->avalue; + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + (i != 0); + i--, p_arg++) { + size_t z; + z = (*p_arg)->size; + if (z < sizeof(int)) { + z = sizeof(int); + switch ((*p_arg)->type) { + case FFI_TYPE_SINT8: { + signed char v = *(SINT8 *)(* p_argv); + signed int t = v; + *(signed int *) argp = t; + } + break; + case FFI_TYPE_UINT8: { + unsigned char v = *(UINT8 *)(* p_argv); + unsigned int t = v; + *(unsigned int *) argp = t; + } + break; + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int) * (SINT16 *)(* p_argv); + break; + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int) * (UINT16 *)(* p_argv); + break; + case FFI_TYPE_STRUCT: + memcpy(argp, *p_argv, (*p_arg)->size); + break; + default: + FFI_ASSERT(0); + break; + } + } else if (z == sizeof(int)) { + *(unsigned int *) argp = (unsigned int) * (UINT32 *)(* p_argv); + } else { + memcpy(argp, *p_argv, z); + } + p_argv++; + argp += z; + } +} + + + diff --git a/ext/ffi_c/libffi/src/bfin/ffitarget.h b/ext/ffi_c/libffi/src/bfin/ffitarget.h new file mode 100644 index 0000000..2175c01 --- /dev/null +++ b/ext/ffi_c/libffi/src/bfin/ffitarget.h @@ -0,0 +1,43 @@ +/* ----------------------------------------------------------------------- + ffitarget.h - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com> + + Blackfin Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_SYSV +} ffi_abi; +#endif + +#endif + diff --git a/ext/ffi_c/libffi/src/bfin/sysv.S b/ext/ffi_c/libffi/src/bfin/sysv.S new file mode 100644 index 0000000..f4278be --- /dev/null +++ b/ext/ffi_c/libffi/src/bfin/sysv.S @@ -0,0 +1,179 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2012 Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>, + Paulo Pizarro <paulo.pizarro@gmail.com> + + Blackfin Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> + +.text +.align 4 + + /* + There is a "feature" in the bfin toolchain that it puts a _ before function names + that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV + */ + .global _ffi_call_SYSV; + .type _ffi_call_SYSV, STT_FUNC; + .func ffi_call_SYSV + + /* + cif->bytes = R0 (fp+8) + &ecif = R1 (fp+12) + ffi_prep_args = R2 (fp+16) + ret_type = stack (fp+20) + ecif.rvalue = stack (fp+24) + fn = stack (fp+28) + got (fp+32) + + There is room for improvement here (we can use temporary registers + instead of saving the values in the memory) + REGS: + P5 => Stack pointer (function arguments) + R5 => cif->bytes + R4 => ret->type + + FP-20 = P3 + FP-16 = SP (parameters area) + FP-12 = SP (temp) + FP-08 = function return part 1 [R0] + FP-04 = function return part 2 [R1] + */ + +_ffi_call_SYSV: +.prologue: + LINK 20; + [FP-20] = P3; + [FP+8] = R0; + [FP+12] = R1; + [FP+16] = R2; + +.allocate_stack: + //alocate cif->bytes into the stack + R1 = [FP+8]; + R0 = SP; + R0 = R0 - R1; + R1 = 4; + R0 = R0 - R1; + [FP-12] = SP; + SP = R0; + [FP-16] = SP; + +.call_prep_args: + //get the addr of prep_args + P0 = [P3 + _ffi_prep_args@FUNCDESC_GOT17M4]; + P1 = [P0]; + P3 = [P0+4]; + R0 = [FP-16];//SP (parameter area) + R1 = [FP+12];//ecif + call (P1); + +.call_user_function: + //ajust SP so as to allow the user function access the parameters on the stack + SP = [FP-16]; //point to function parameters + R0 = [SP]; + R1 = [SP+4]; + R2 = [SP+8]; + //load user function address + P0 = FP; + P0 +=28; + P1 = [P0]; + P1 = [P1]; + P3 = [P0+4]; + /* + For functions returning aggregate values (struct) occupying more than 8 bytes, + the caller allocates the return value object on the stack and the address + of this object is passed to the callee as a hidden argument in register P0. + */ + P0 = [FP+24]; + + call (P1); + SP = [FP-12]; +.compute_return: + P2 = [FP-20]; + [FP-8] = R0; + [FP-4] = R1; + + R0 = [FP+20]; + R1 = R0 << 2; + + R0 = [P2+.rettable@GOT17M4]; + R0 = R1 + R0; + P2 = R0; + R1 = [P2]; + + P2 = [FP+-20]; + R0 = [P2+.rettable@GOT17M4]; + R0 = R1 + R0; + P2 = R0; + R0 = [FP-8]; + R1 = [FP-4]; + jump (P2); + +/* +#define FFIBFIN_RET_VOID 0 +#define FFIBFIN_RET_BYTE 1 +#define FFIBFIN_RET_HALFWORD 2 +#define FFIBFIN_RET_INT64 3 +#define FFIBFIN_RET_INT32 4 +*/ +.align 4 +.align 4 +.rettable: + .dd .epilogue - .rettable + .dd .rbyte - .rettable; + .dd .rhalfword - .rettable; + .dd .rint64 - .rettable; + .dd .rint32 - .rettable; + +.rbyte: + P0 = [FP+24]; + R0 = R0.B (Z); + [P0] = R0; + JUMP .epilogue +.rhalfword: + P0 = [FP+24]; + R0 = R0.L; + [P0] = R0; + JUMP .epilogue +.rint64: + P0 = [FP+24];// &rvalue + [P0] = R0; + [P0+4] = R1; + JUMP .epilogue +.rint32: + P0 = [FP+24]; + [P0] = R0; +.epilogue: + R0 = [FP+8]; + R1 = [FP+12]; + R2 = [FP+16]; + P3 = [FP-20]; + UNLINK; + RTS; + +.size _ffi_call_SYSV,.-_ffi_call_SYSV; +.endfunc |