summaryrefslogtreecommitdiff
path: root/Modules/_ctypes/libffi/src/microblaze/ffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_ctypes/libffi/src/microblaze/ffi.c')
-rw-r--r--Modules/_ctypes/libffi/src/microblaze/ffi.c321
1 files changed, 0 insertions, 321 deletions
diff --git a/Modules/_ctypes/libffi/src/microblaze/ffi.c b/Modules/_ctypes/libffi/src/microblaze/ffi.c
deleted file mode 100644
index ea962ea483..0000000000
--- a/Modules/_ctypes/libffi/src/microblaze/ffi.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 2012, 2013 Xilinx, Inc
-
- MicroBlaze 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>
-
-extern void ffi_call_SYSV(void (*)(void*, extended_cif*), extended_cif*,
- unsigned int, unsigned int, unsigned int*, void (*fn)(void),
- unsigned int, unsigned int);
-
-extern void ffi_closure_SYSV(void);
-
-#define WORD_SIZE sizeof(unsigned int)
-#define ARGS_REGISTER_SIZE (WORD_SIZE * 6)
-#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE)
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
-void ffi_prep_args(void* stack, extended_cif* ecif)
-{
- unsigned int i;
- ffi_type** p_arg;
- void** p_argv;
- void* stack_args_p = stack;
-
- p_argv = ecif->avalue;
-
- if (ecif == NULL || ecif->cif == NULL) {
- return; /* no description to prepare */
- }
-
- if ((ecif->cif->rtype != NULL) &&
- (ecif->cif->rtype->type == FFI_TYPE_STRUCT))
- {
- /* if return type is a struct which is referenced on the stack/reg5,
- * by a pointer. Stored the return value pointer in r5.
- */
- char* addr = stack_args_p;
- memcpy(addr, &(ecif->rvalue), WORD_SIZE);
- stack_args_p += WORD_SIZE;
- }
-
- if (ecif->avalue == NULL) {
- return; /* no arguments to prepare */
- }
-
- for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
- i++, p_arg++)
- {
- size_t size = (*p_arg)->size;
- int type = (*p_arg)->type;
- void* value = p_argv[i];
- char* addr = stack_args_p;
- int aligned_size = WORD_ALIGN(size);
-
- /* force word alignment on the stack */
- stack_args_p += aligned_size;
-
- switch (type)
- {
- case FFI_TYPE_UINT8:
- *(unsigned int *)addr = (unsigned int)*(UINT8*)(value);
- break;
- case FFI_TYPE_SINT8:
- *(signed int *)addr = (signed int)*(SINT8*)(value);
- break;
- case FFI_TYPE_UINT16:
- *(unsigned int *)addr = (unsigned int)*(UINT16*)(value);
- break;
- case FFI_TYPE_SINT16:
- *(signed int *)addr = (signed int)*(SINT16*)(value);
- break;
- case FFI_TYPE_STRUCT:
-#if __BIG_ENDIAN__
- /*
- * MicroBlaze toolchain appears to emit:
- * bsrli r5, r5, 8 (caller)
- * ...
- * <branch to callee>
- * ...
- * bslli r5, r5, 8 (callee)
- *
- * For structs like "struct a { uint8_t a[3]; };", when passed
- * by value.
- *
- * Structs like "struct b { uint16_t a; };" are also expected
- * to be packed strangely in registers.
- *
- * This appears to be because the microblaze toolchain expects
- * "struct b == uint16_t", which is only any issue for big
- * endian.
- *
- * The following is a work around for big-endian only, for the
- * above mentioned case, it will re-align the contents of a
- * <= 3-byte struct value.
- */
- if (size < WORD_SIZE)
- {
- memcpy (addr + (WORD_SIZE - size), value, size);
- break;
- }
-#endif
- case FFI_TYPE_SINT32:
- case FFI_TYPE_UINT32:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- case FFI_TYPE_DOUBLE:
- default:
- memcpy(addr, value, aligned_size);
- }
- }
-}
-
-ffi_status ffi_prep_cif_machdep(ffi_cif* cif)
-{
- /* check ABI */
- switch (cif->abi)
- {
- case FFI_SYSV:
- break;
- default:
- return FFI_BAD_ABI;
- }
- return FFI_OK;
-}
-
-void ffi_call(ffi_cif* cif, void (*fn)(void), void* rvalue, void** avalue)
-{
- extended_cif ecif;
- ecif.cif = cif;
- ecif.avalue = avalue;
-
- /* If the return value is a struct and we don't have a return */
- /* value address then we need to make one */
- if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
- ecif.rvalue = alloca(cif->rtype->size);
- } else {
- ecif.rvalue = rvalue;
- }
-
- switch (cif->abi)
- {
- case FFI_SYSV:
- ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags,
- ecif.rvalue, fn, cif->rtype->type, cif->rtype->size);
- break;
- default:
- FFI_ASSERT(0);
- break;
- }
-}
-
-void ffi_closure_call_SYSV(void* register_args, void* stack_args,
- ffi_closure* closure, void* rvalue,
- unsigned int* rtype, unsigned int* rsize)
-{
- /* prepare arguments for closure call */
- ffi_cif* cif = closure->cif;
- ffi_type** arg_types = cif->arg_types;
-
- /* re-allocate data for the args. This needs to be done in order to keep
- * multi-word objects (e.g. structs) in contiguous memory. Callers are not
- * required to store the value of args in the lower 6 words in the stack
- * (although they are allocated in the stack).
- */
- char* stackclone = alloca(cif->bytes);
- void** avalue = alloca(cif->nargs * sizeof(void*));
- void* struct_rvalue = NULL;
- char* ptr = stackclone;
- int i;
-
- /* copy registers into stack clone */
- int registers_used = cif->bytes;
- if (registers_used > ARGS_REGISTER_SIZE) {
- registers_used = ARGS_REGISTER_SIZE;
- }
- memcpy(stackclone, register_args, registers_used);
-
- /* copy stack allocated args into stack clone */
- if (cif->bytes > ARGS_REGISTER_SIZE) {
- int stack_used = cif->bytes - ARGS_REGISTER_SIZE;
- memcpy(stackclone + ARGS_REGISTER_SIZE, stack_args, stack_used);
- }
-
- /* preserve struct type return pointer passing */
- if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
- struct_rvalue = *((void**)ptr);
- ptr += WORD_SIZE;
- }
-
- /* populate arg pointer list */
- for (i = 0; i < cif->nargs; i++)
- {
- switch (arg_types[i]->type)
- {
- case FFI_TYPE_SINT8:
- case FFI_TYPE_UINT8:
-#ifdef __BIG_ENDIAN__
- avalue[i] = ptr + 3;
-#else
- avalue[i] = ptr;
-#endif
- break;
- case FFI_TYPE_SINT16:
- case FFI_TYPE_UINT16:
-#ifdef __BIG_ENDIAN__
- avalue[i] = ptr + 2;
-#else
- avalue[i] = ptr;
-#endif
- break;
- case FFI_TYPE_STRUCT:
-#if __BIG_ENDIAN__
- /*
- * Work around strange ABI behaviour.
- * (see info in ffi_prep_args)
- */
- if (arg_types[i]->size < WORD_SIZE)
- {
- memcpy (ptr, ptr + (WORD_SIZE - arg_types[i]->size), arg_types[i]->size);
- }
-#endif
- avalue[i] = (void*)ptr;
- break;
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_DOUBLE:
- avalue[i] = ptr;
- break;
- case FFI_TYPE_SINT32:
- case FFI_TYPE_UINT32:
- case FFI_TYPE_FLOAT:
- default:
- /* default 4-byte argument */
- avalue[i] = ptr;
- break;
- }
- ptr += WORD_ALIGN(arg_types[i]->size);
- }
-
- /* set the return type info passed back to the wrapper */
- *rsize = cif->rtype->size;
- *rtype = cif->rtype->type;
- if (struct_rvalue != NULL) {
- closure->fun(cif, struct_rvalue, avalue, closure->user_data);
- /* copy struct return pointer value into function return value */
- *((void**)rvalue) = struct_rvalue;
- } else {
- closure->fun(cif, rvalue, avalue, closure->user_data);
- }
-}
-
-ffi_status ffi_prep_closure_loc(
- ffi_closure* closure, ffi_cif* cif,
- void (*fun)(ffi_cif*, void*, void**, void*),
- void* user_data, void* codeloc)
-{
- unsigned long* tramp = (unsigned long*)&(closure->tramp[0]);
- unsigned long cls = (unsigned long)codeloc;
- unsigned long fn = 0;
- unsigned long fn_closure_call_sysv = (unsigned long)ffi_closure_call_SYSV;
-
- closure->cif = cif;
- closure->fun = fun;
- closure->user_data = user_data;
-
- switch (cif->abi)
- {
- case FFI_SYSV:
- fn = (unsigned long)ffi_closure_SYSV;
-
- /* load r11 (temp) with fn */
- /* imm fn(upper) */
- tramp[0] = 0xb0000000 | ((fn >> 16) & 0xffff);
- /* addik r11, r0, fn(lower) */
- tramp[1] = 0x31600000 | (fn & 0xffff);
-
- /* load r12 (temp) with cls */
- /* imm cls(upper) */
- tramp[2] = 0xb0000000 | ((cls >> 16) & 0xffff);
- /* addik r12, r0, cls(lower) */
- tramp[3] = 0x31800000 | (cls & 0xffff);
-
- /* load r3 (temp) with ffi_closure_call_SYSV */
- /* imm fn_closure_call_sysv(upper) */
- tramp[4] = 0xb0000000 | ((fn_closure_call_sysv >> 16) & 0xffff);
- /* addik r3, r0, fn_closure_call_sysv(lower) */
- tramp[5] = 0x30600000 | (fn_closure_call_sysv & 0xffff);
- /* branch/jump to address stored in r11 (fn) */
- tramp[6] = 0x98085800; /* bra r11 */
-
- break;
- default:
- return FFI_BAD_ABI;
- }
- return FFI_OK;
-}