aboutsummaryrefslogtreecommitdiff
path: root/libffi/src
diff options
context:
space:
mode:
authorKazuhiro Inaoka <inaoka.kazuhiro@renesas.com>2004-10-13 17:20:24 +0000
committerNick Clifton <nickc@gcc.gnu.org>2004-10-13 17:20:24 +0000
commita472e9d4e6d12ae7f7eff034d88261d4c2f477e7 (patch)
tree3576ed3b489940f5b378fafbd25ec3a8d2f7c4d3 /libffi/src
parentbcd46a7c659cd5e4883a54f491ba09e04934fefa (diff)
downloadgcc-a472e9d4e6d12ae7f7eff034d88261d4c2f477e7.tar.gz
gcc-a472e9d4e6d12ae7f7eff034d88261d4c2f477e7.tar.bz2
gcc-a472e9d4e6d12ae7f7eff034d88261d4c2f477e7.zip
Makefile.am: Add m32r support.
* Makefile.am: Add m32r support. * configure.ac: Likewise. * Makefile.in: Regenerate. * confiugre: Regenerate. * src/types.c: Add m32r port to FFI_INTERNAL_TYPEDEF (uint64, sint64, double, longdouble) * src/m32r: New directory. * src/m32r/ffi.c: New file. * src/m32r/sysv.S: Likewise. * src/m32r/ffitarget.h: Likewise. From-SVN: r88993
Diffstat (limited to 'libffi/src')
-rw-r--r--libffi/src/m32r/ffi.c247
-rw-r--r--libffi/src/m32r/ffitarget.h48
-rw-r--r--libffi/src/m32r/sysv.S121
-rw-r--r--libffi/src/types.c2
4 files changed, 417 insertions, 1 deletions
diff --git a/libffi/src/m32r/ffi.c b/libffi/src/m32r/ffi.c
new file mode 100644
index 00000000000..9a3b5509539
--- /dev/null
+++ b/libffi/src/m32r/ffi.c
@@ -0,0 +1,247 @@
+/* -----------------------------------------------------------------------
+ ffi.c - Copyright (c) 2004 Renesas Technology
+
+ M32R 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 RENESAS TECHNOLOGY 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>
+
+/* ffi_prep_args is called by the assembly routine once stack
+ space has been allocated for the function's arguments. */
+
+/*@-exportheader@*/
+void ffi_prep_args(char *stack, extended_cif *ecif)
+/*@=exportheader@*/
+{
+ unsigned int i;
+ int tmp;
+ unsigned int avn;
+ void **p_argv;
+ char *argp;
+ ffi_type **p_arg;
+
+ tmp = 0;
+ argp = stack;
+
+ if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
+ {
+ *(void **) argp = ecif->rvalue;
+ argp += 4;
+ }
+
+ avn = ecif->cif->nargs;
+ p_argv = ecif->avalue;
+
+ for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
+ (i != 0) && (avn != 0);
+ i--, p_arg++)
+ {
+ size_t z;
+
+ /* Align if necessary. */
+ if (((*p_arg)->alignment - 1) & (unsigned) argp)
+ argp = (char *) ALIGN (argp, (*p_arg)->alignment);
+
+ if (avn != 0)
+ {
+ avn--;
+ z = (*p_arg)->size;
+ if (z < sizeof (int))
+ {
+ z = sizeof (int);
+
+ switch ((*p_arg)->type)
+ {
+ case FFI_TYPE_SINT8:
+ *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
+ break;
+
+ case FFI_TYPE_UINT8:
+ *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
+ 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:
+ z = (*p_arg)->size;
+ if ((*p_arg)->alignment != 1)
+ memcpy (argp, *p_argv, z);
+ else
+ memcpy (argp + 4 - z, *p_argv, z);
+ z = sizeof (int);
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ }
+ }
+ else if (z == sizeof (int))
+ {
+ *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+ }
+ else
+ {
+ if ((*p_arg)->type == FFI_TYPE_STRUCT)
+ {
+ if (z > 8)
+ {
+ *(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
+ z = sizeof(void *);
+ }
+ else
+ {
+ memcpy(argp, *p_argv, z);
+ z = 8;
+ }
+ }
+ else
+ {
+ /* Double or long long 64bit. */
+ memcpy (argp, *p_argv, z);
+ }
+ }
+ p_argv++;
+ argp += z;
+ }
+ }
+
+ return;
+}
+
+/* Perform machine dependent cif processing. */
+ffi_status
+ffi_prep_cif_machdep(ffi_cif *cif)
+{
+ /* Set the return type flag. */
+ switch (cif->rtype->type)
+ {
+ case FFI_TYPE_VOID:
+ cif->flags = (unsigned) cif->rtype->type;
+ break;
+
+ case FFI_TYPE_STRUCT:
+ if (cif->rtype->size <= 4)
+ cif->flags = FFI_TYPE_INT;
+
+ else if (cif->rtype->size <= 8)
+ cif->flags = FFI_TYPE_DOUBLE;
+
+ else
+ cif->flags = (unsigned) cif->rtype->type;
+ break;
+
+ case FFI_TYPE_SINT64:
+ case FFI_TYPE_UINT64:
+ case FFI_TYPE_DOUBLE:
+ cif->flags = FFI_TYPE_DOUBLE;
+ break;
+
+ case FFI_TYPE_FLOAT:
+ default:
+ cif->flags = FFI_TYPE_INT;
+ break;
+ }
+
+ return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_SYSV(void (*)(char *, extended_cif *),
+ /*@out@*/ extended_cif *,
+ unsigned, unsigned,
+ /*@out@*/ unsigned *,
+ void (*fn)());
+/*@=declundef@*/
+/*@=exportheader@*/
+
+void ffi_call(/*@dependent@*/ ffi_cif *cif,
+ void (*fn)(),
+ /*@out@*/ void *rvalue,
+ /*@dependent@*/ 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))
+ {
+ /*@-sysunrecog@*/
+ ecif.rvalue = alloca (cif->rtype->size);
+ /*@=sysunrecog@*/
+ }
+ else
+ ecif.rvalue = rvalue;
+
+ switch (cif->abi)
+ {
+ case FFI_SYSV:
+ /*@-usedef@*/
+ ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
+ cif->flags, ecif.rvalue, fn);
+ if (cif->rtype->type == FFI_TYPE_STRUCT)
+ {
+ int size = cif->rtype->size;
+ int align = cif->rtype->alignment;
+
+ if (size < 4)
+ {
+ if (align == 1)
+ *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
+ }
+ else if (4 < size && size < 8)
+ {
+ if (align == 1)
+ {
+ memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
+ }
+ else if (align == 2)
+ {
+ if (size & 1)
+ size += 1;
+
+ if (size != 8)
+ memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
+ }
+ }
+ }
+ /*@=usedef@*/
+ break;
+
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+}
diff --git a/libffi/src/m32r/ffitarget.h b/libffi/src/m32r/ffitarget.h
new file mode 100644
index 00000000000..478a8db69a6
--- /dev/null
+++ b/libffi/src/m32r/ffitarget.h
@@ -0,0 +1,48 @@
+/* -----------------------------------------------------------------*-C-*-
+ ffitarget.h - Copyright (c) 2004 Renesas Technology.
+ Target configuration macros for M32R.
+
+ 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 RENESAS TECHNOLOGY 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
+
+/* ---- Generic type definitions ----------------------------------------- */
+
+#ifndef LIBFFI_ASM
+typedef unsigned long ffi_arg;
+typedef signed long ffi_sarg;
+
+typedef enum ffi_abi
+ {
+ FFI_FIRST_ABI = 0,
+ FFI_SYSV,
+ FFI_DEFAULT_ABI = FFI_SYSV,
+ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+ } ffi_abi;
+#endif
+
+#define FFI_CLOSURES 1
+#define FFI_TRAMPOLINE_SIZE 24
+#define FFI_NATIVE_RAW_API 0
+
+#endif
diff --git a/libffi/src/m32r/sysv.S b/libffi/src/m32r/sysv.S
new file mode 100644
index 00000000000..06b75c22634
--- /dev/null
+++ b/libffi/src/m32r/sysv.S
@@ -0,0 +1,121 @@
+/* -----------------------------------------------------------------------
+ sysv.S - Copyright (c) 2004 Renesas Technology
+
+ M32R 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 RENESAS TECHNOLOGY 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>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x)! .type CNAME(x),%function! CNAME(x):
+#endif
+
+.text
+
+ /* R0: ffi_prep_args */
+ /* R1: &ecif */
+ /* R2: cif->bytes */
+ /* R3: fig->flags */
+ /* sp+0: ecif.rvalue */
+ /* sp+4: fn */
+
+ /* This assumes we are using gas. */
+ENTRY(ffi_call_SYSV)
+ /* Save registers. */
+ push fp
+ push lr
+ push r3
+ push r2
+ push r1
+ push r0
+ mv fp, sp
+
+ /* Make room for all of the new args. */
+ sub sp, r2
+
+ /* Place all of the ffi_prep_args in position. */
+ mv lr, r0
+ mv r0, sp
+ /* R1 already set. */
+
+ /* And call. */
+ jl lr
+
+ /* Move first 4 parameters in registers... */
+ ld r0, @(0,sp)
+ ld r1, @(4,sp)
+ ld r2, @(8,sp)
+ ld r3, @(12,sp)
+
+ /* ...and adjust the stack. */
+ ld lr, @(8,fp)
+ cmpi lr, #16
+ bc adjust_stack
+ ldi lr, #16
+adjust_stack:
+ add sp, lr
+
+ /* Call the function. */
+ ld lr, @(28,fp)
+ jl lr
+
+ /* Remove the space we pushed for the args. */
+ mv sp, fp
+
+ /* Load R2 with the pointer to storage for the return value. */
+ ld r2, @(24,sp)
+
+ /* Load R3 with the return type code. */
+ ld r3, @(12,sp)
+
+ /* If the return value pointer is NULL, assume no return value. */
+ beqz r2, epilogue
+
+ /* Return INT. */
+ ldi r4, #FFI_TYPE_INT
+ bne r3, r4, return_double
+ st r0, @r2
+ bra epilogue
+
+return_double:
+ /* Return DOUBLE or LONGDOUBLE. */
+ ldi r4, #FFI_TYPE_DOUBLE
+ bne r3, r4, epilogue
+ st r0, @r2
+ st r1, @(4,r2)
+
+epilogue:
+ pop r0
+ pop r1
+ pop r2
+ pop r3
+ pop lr
+ pop fp
+ jmp lr
+
+.ffi_call_SYSV_end:
+ .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
diff --git a/libffi/src/types.c b/libffi/src/types.c
index 09863c076b5..47ee65637e6 100644
--- a/libffi/src/types.c
+++ b/libffi/src/types.c
@@ -80,7 +80,7 @@ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
#endif
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-#elif defined ARM || defined SH || defined POWERPC_AIX
+#elif defined ARM || defined SH || defined POWERPC_AIX || defined M32R
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);