diff options
author | Anthony Green <green@moxielogic.com> | 2013-02-11 14:25:13 -0500 |
---|---|---|
committer | Anthony Green <green@moxielogic.com> | 2013-02-11 14:25:13 -0500 |
commit | f308faf1eabaf8dc24966ab17fbf94368f46b9c7 (patch) | |
tree | 786be282c827050317989bf8c612ad60be0796bb /src/moxie | |
parent | 4ea22e54e3b143fe05c413f6dddd236af6bcbfb2 (diff) | |
download | libffi-f308faf1eabaf8dc24966ab17fbf94368f46b9c7.tar.gz |
Add moxie support. Release 3.0.12.v3.0.12
Diffstat (limited to 'src/moxie')
-rw-r--r-- | src/moxie/eabi.S | 57 | ||||
-rw-r--r-- | src/moxie/ffi.c | 64 | ||||
-rw-r--r-- | src/moxie/ffitarget.h | 10 |
3 files changed, 88 insertions, 43 deletions
diff --git a/src/moxie/eabi.S b/src/moxie/eabi.S index 7e2143b..ac7aceb 100644 --- a/src/moxie/eabi.S +++ b/src/moxie/eabi.S @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------- - eabi.S - Copyright (c) 2012 Anthony Green + eabi.S - Copyright (c) 2012, 2013 Anthony Green Moxie Assembly glue. @@ -41,24 +41,61 @@ # $r4 : ecif.rvalue # $r5 : fn -ffi_call_EABI: +ffi_call_EABI: + push $sp, $r6 + push $sp, $r7 + push $sp, $r8 dec $sp, 24 /* Store incoming args on stack. */ - sto.l 0($sp), $r0 - sto.l 4($sp), $r1 - sto.l 8($sp), $r2 - sto.l 12($sp), $r3 - sto.l 16($sp), $r4 - sto.l 20($sp), $r5 + sto.l 0($sp), $r0 /* ffi_prep_args */ + sto.l 4($sp), $r1 /* ecif */ + sto.l 8($sp), $r2 /* bytes */ + sto.l 12($sp), $r3 /* flags */ + sto.l 16($sp), $r4 /* &rvalue */ + sto.l 20($sp), $r5 /* fn */ /* Call ffi_prep_args. */ - jsr $r0 + mov $r6, $r4 /* Save result buffer */ + mov $r7, $r5 /* Save the target fn */ + mov $r8, $r3 /* Save the flags */ + sub.l $sp, $r2 /* Allocate stack space */ + mov $r0, $sp /* We can stomp over $r0 */ + /* $r1 is already set up */ + jsra ffi_prep_args + /* Load register arguments. */ + ldo.l $r0, 0($sp) + ldo.l $r1, 4($sp) + ldo.l $r2, 8($sp) + ldo.l $r3, 12($sp) + ldo.l $r4, 16($sp) + ldo.l $r5, 20($sp) + /* Call the target function. */ - jsr $r5 + jsr $r7 + + ldi.l $r7, 0xffffffff + cmp $r8, $r7 + beq retstruct + + ldi.l $r7, 4 + cmp $r8, $r7 + bgt ret2reg + + st.l ($r6), $r0 + jmpa retdone + +ret2reg: + st.l ($r6), $r0 + sto.l 4($r6), $r1 +retstruct: +retdone: /* Return. */ + ldo.l $r6, -4($fp) + ldo.l $r7, -8($fp) + ldo.l $r8, -12($fp) ret .size ffi_call_EABI, .-ffi_call_EABI diff --git a/src/moxie/ffi.c b/src/moxie/ffi.c index 11abb00..540a042 100644 --- a/src/moxie/ffi.c +++ b/src/moxie/ffi.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (C) 2012 Anthony Green + ffi.c - Copyright (C) 2012, 2013 Anthony Green Moxie Foreign Function Interface @@ -43,6 +43,12 @@ void *ffi_prep_args(char *stack, extended_cif *ecif) p_argv = ecif->avalue; argp = stack; + if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) + { + *(void **) argp = ecif->rvalue; + argp += 4; + } + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++) @@ -136,8 +142,7 @@ void ffi_call(ffi_cif *cif, } else ecif.rvalue = rvalue; - - + switch (cif->abi) { case FFI_EABI: @@ -154,19 +159,25 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, unsigned arg5, unsigned arg6) { /* This function is called by a trampoline. The trampoline stows a - pointer to the ffi_closure object in gr7. We must save this + pointer to the ffi_closure object in $r7. We must save this pointer in a place that will persist while we do our work. */ - register ffi_closure *creg __asm__ ("$r7"); + register ffi_closure *creg __asm__ ("$r12"); ffi_closure *closure = creg; /* Arguments that don't fit in registers are found on the stack at a fixed offset above the current frame pointer. */ register char *frame_pointer __asm__ ("$fp"); - char *stack_args = frame_pointer + 16; + + /* Pointer to a struct return value. */ + void *struct_rvalue = (void *) arg1; + + /* 6 words reserved for register args + 3 words from jsr */ + char *stack_args = frame_pointer + 9*4; /* Lay the register arguments down in a continuous chunk of memory. */ unsigned register_args[6] = { arg1, arg2, arg3, arg4, arg5, arg6 }; + char *register_args_ptr = (char *) register_args; ffi_cif *cif = closure->cif; ffi_type **arg_types = cif->arg_types; @@ -174,6 +185,12 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, char *ptr = (char *) register_args; int i; + /* preserve struct type return pointer passing */ + if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) { + ptr += 4; + register_args_ptr = (char *)®ister_args[1]; + } + /* Find the address of each argument. */ for (i = 0; i < cif->nargs; i++) { @@ -190,6 +207,7 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: case FFI_TYPE_FLOAT: + case FFI_TYPE_POINTER: avalue[i] = ptr; break; case FFI_TYPE_STRUCT: @@ -205,30 +223,21 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, /* If we've handled more arguments than fit in registers, start looking at the those passed on the stack. */ - if (ptr == ((char *)register_args + (6*4))) + if (ptr == ®ister_args[6]) ptr = stack_args; } /* Invoke the closure. */ - if (cif->rtype->type == FFI_TYPE_STRUCT) + if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT)) { - /* The caller allocates space for the return structure, and - passes a pointer to this space in gr3. Use this value directly - as the return value. */ - register void *return_struct_ptr __asm__("$r0"); - (closure->fun) (cif, return_struct_ptr, avalue, closure->user_data); + (closure->fun) (cif, struct_rvalue, avalue, closure->user_data); } else { /* Allocate space for the return value and call the function. */ long long rvalue; (closure->fun) (cif, &rvalue, avalue, closure->user_data); - - /* Functions return 4-byte or smaller results in gr8. 8-byte - values also use gr9. We fill the both, even for small return - values, just to avoid a branch. */ /* - asm ("ldi @(%0, #0), gr8" : : "r" (&rvalue)); - asm ("ldi @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1])); */ + asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue)); } } @@ -239,18 +248,21 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { - unsigned int *tramp = (unsigned int *) &closure->tramp[0]; + unsigned short *tramp = (unsigned short *) &closure->tramp[0]; unsigned long fn = (long) ffi_closure_eabi; unsigned long cls = (long) codeloc; - int i; + + if (cif->abi != FFI_EABI) + return FFI_BAD_ABI; fn = (unsigned long) ffi_closure_eabi; - tramp[0] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */ - tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */ - tramp[2] = 0x8cf80000 + (fn >> 16); /* sethi hi(fn), gr6 */ - tramp[3] = 0x8ef80000 + (cls >> 16); /* sethi hi(cls), gr7 */ - tramp[4] = 0x80300006; /* jmpl @(gr0, gr6) */ + tramp[0] = 0x01e0; /* ldi.l $r7, .... */ + tramp[1] = cls >> 16; + tramp[2] = cls & 0xffff; + tramp[3] = 0x1a00; /* jmpa .... */ + tramp[4] = fn >> 16; + tramp[5] = fn & 0xffff; closure->cif = cif; closure->fun = fun; diff --git a/src/moxie/ffitarget.h b/src/moxie/ffitarget.h index 93fae39..623e3ec 100644 --- a/src/moxie/ffitarget.h +++ b/src/moxie/ffitarget.h @@ -1,5 +1,5 @@ /* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green + ffitarget.h - Copyright (c) 2012, 2013 Anthony Green Target configuration macros for Moxie Permission is hereby granted, free of charge, to any person obtaining @@ -35,12 +35,8 @@ typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, - -#ifdef MOXIE FFI_EABI, FFI_DEFAULT_ABI = FFI_EABI, -#endif - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif @@ -50,7 +46,7 @@ typedef enum ffi_abi { #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 -/* Trampolines are 5 4-byte instructions long. */ -#define FFI_TRAMPOLINE_SIZE (5*4) +/* Trampolines are 12-bytes long. See ffi_prep_closure_loc. */ +#define FFI_TRAMPOLINE_SIZE (12) #endif |