This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch 3.4/3.5] libffi & libjava port for hppa-linux


Thanks to Randolph Chung for the port of libffi and libjava for the
hppa-linux platform. Updated the patches from the initial 3.3 based
patches.

Test results

for 3.5: http://gcc.gnu.org/ml/gcc-testresults/2004-03/msg00669.html
for 3.4: http://gcc.gnu.org/ml/gcc-testresults/2004-03/msg00670.html
for 3.3: http://gcc.gnu.org/ml/gcc-testresults/2004-02/msg00905.html

Ok to checkin?


libjava:
2004-02-10  Randolph Chung  <tausq@debian.org>
 
        * configure.in: Build java for hppa target.
        * libjava/configure.host (hppa-*): Add target.
        * libjava/sysdeps/pa/lock.h: New file.


libffi:
2004-03-13  Matthias Klose  <doko@debian.org>

	* Makefile.am: Update 
	* Makefile.in: Regenerate.
	* src/pa/ffi.h.in: Remove.
	* src/pa/ffitarget.h: New file.

2004-02-10  Randolph Chung  <tausq@debian.org>

	* Makefile.am: Add PA support.
	* Makefile.in: Regenerate.
	* include/Makefile.in: Regenerate.
	* configure.in: Add PA target.
	* configure: Regenerate.
	* src/pa/ffi.c: New file.
	* src/pa/ffi.h.in: Add PA support.
	* src/pa/linux.S: New file.
	* prep_cif.c: Add PA support.

toplevel:
2004-03-13  Matthias Klose  <doko@debian.org>

	* configure.in: For hppa-linux enable libgcj and dependent libs.
	* configure: Regenerate.




--- configure.in~	2004-02-22 16:12:01.000000000 +0100
+++ configure.in	2004-02-22 16:22:19.000000000 +0100
@@ -482,8 +482,9 @@
     # headers, crt*.o, etc., all of which are needed by these.
     noconfigdirs="$noconfigdirs target-zlib"
     ;;
+  parisc*-*-linux* | hppa*-*-linux*)
+    ;;
   hppa*-*-*elf* | \
-  parisc*-*-linux* | hppa*-*-linux* | \
   hppa*-*-lites* | \
   hppa*-*-openbsd* | \
   hppa*64*-*-*)


diff -uNr src.orig/libjava/configure.host src/libjava/configure.host
--- src.orig/libjava/configure.host	2004-02-11 21:34:26.638618512 -0800
+++ src/libjava/configure.host	2004-02-11 21:38:59.687108832 -0800
@@ -115,6 +115,11 @@
 	enable_hash_synchronization_default=yes
 	IEEESPEC=-mieee
 	;;
+  hppa-*)
+	sysdeps_dir=pa
+	libgcj_interpreter=yes
+	enable_hash_synchronization_default=yes
+	;;
   powerpc64*-*)
 	sysdeps_dir=powerpc
 	libgcj_interpreter=yes
diff -uNr src.orig/libjava/sysdep/pa/locks.h src/libjava/sysdep/pa/locks.h
--- src.orig/libjava/sysdep/pa/locks.h	1969-12-31 16:00:00.000000000 -0800
+++ src/libjava/sysdep/pa/locks.h	2004-02-11 21:40:03.542401352 -0800
@@ -0,0 +1,78 @@
+// locks.h - Thread synchronization primitives. PARISC implementation.
+
+/* Copyright (C) 2002  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+#ifndef __SYSDEP_LOCKS_H__
+#define __SYSDEP_LOCKS_H__
+
+typedef size_t obj_addr_t;	/* Integer type big enough for object	*/
+				/* address.				*/
+
+// Atomically replace *addr by new_val if it was initially equal to old.
+// Return true if the comparison succeeded.
+// Assumed to have acquire semantics, i.e. later memory operations
+// cannot execute before the compare_and_swap finishes.
+inline static bool
+compare_and_swap(volatile obj_addr_t *addr,
+	 	 obj_addr_t old,
+		 obj_addr_t new_val) 
+{
+  /* FIXME: not atomic */
+  obj_addr_t prev;
+
+  if ((prev = *addr) == old)
+    {
+      *addr = new_val;
+      return true;
+    }
+  else
+    {
+      return false;
+    }
+}
+
+// Set *addr to new_val with release semantics, i.e. making sure
+// that prior loads and stores complete before this
+// assignment.
+inline static void
+release_set(volatile obj_addr_t *addr, obj_addr_t new_val)
+{
+  __asm__ __volatile__(" " : : : "memory");
+  *(addr) = new_val;
+}
+
+// Compare_and_swap with release semantics instead of acquire semantics.
+// On many architecture, the operation makes both guarantees, so the
+// implementation can be the same.
+inline static bool
+compare_and_swap_release(volatile obj_addr_t *addr,
+	 				             obj_addr_t old,
+						     obj_addr_t new_val) 
+{
+  return compare_and_swap(addr, old, new_val);
+}
+
+// Ensure that subsequent instructions do not execute on stale
+// data that was loaded from memory before the barrier.
+inline static void
+read_barrier()
+{
+  __asm__ __volatile__(" " : : : "memory");
+}
+
+// Ensure that prior stores to memory are completed with respect to other
+// processors.
+inline static void
+write_barrier()
+{
+  __asm__ __volatile__(" " : : : "memory");
+}
+
+#endif
+


diff -urN libffi.old/Makefile.am libffi/Makefile.am
--- libffi.old/Makefile.am	2004-03-12 05:52:09.000000000 +0100
+++ libffi/Makefile.am	2004-03-12 06:14:43.000000000 +0100
@@ -22,7 +22,8 @@
 	src/sparc/v8.S src/sparc/v9.S src/sparc/ffitarget.h \
 	src/sparc/ffi.c \
 	src/x86/ffi.c src/x86/sysv.S src/x86/win32.S \
-	src/x86/ffi64.c src/x86/unix64.S src/x86/ffitarget.h
+	src/x86/ffi64.c src/x86/unix64.S src/x86/ffitarget.h \
+	src/pa/ffi.c src/pa/linux.S
 
 ## ################################################################
 
@@ -135,6 +136,9 @@
 if SH64
 nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
 endif
+if PA
+nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
+endif
 
 libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
 nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
diff -urN libffi.old/configure.in libffi/configure.in
--- libffi.old/configure.in	2004-01-15 17:21:48.000000000 +0100
+++ libffi/configure.in	2004-02-21 14:18:26.000000000 +0100
@@ -85,6 +85,7 @@
 x86_64-*-linux*) TARGET=X86_64; TARGETDIR=x86;;
 sh-*-linux* | sh[[34]]*-*-linux*) TARGET=SH; TARGETDIR=sh;;
 sh64-*-linux* | sh5*-*-linux*) TARGET=SH64; TARGETDIR=sh64;;
+hppa-*-linux* | parisc-*-linux*) TARGET=PA; TARGETDIR=pa;;
 esac
 
 AC_SUBST(AM_RUNTESTFLAGS)
@@ -109,6 +110,7 @@
 AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
 AM_CONDITIONAL(SH, test x$TARGET = xSH)
 AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
+AM_CONDITIONAL(PA, test x$TARGET = xPA)
 
 case x$TARGET in
   xMIPS*) TARGET=MIPS ;;
diff -urN libffi.old/src/pa/ffi.c libffi/src/pa/ffi.c
--- libffi.old/src/pa/ffi.c	1970-01-01 01:00:00.000000000 +0100
+++ libffi/src/pa/ffi.c	2004-02-21 14:15:37.000000000 +0100
@@ -0,0 +1,608 @@
+/* -----------------------------------------------------------------------
+   ffi.c - (c) 2003 Randolph Chung <tausq@debian.org>
+
+   HPPA 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 CYGNUS SOLUTIONS 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>
+
+#define ROUND_UP(v, a)  (((size_t)(v) + (a) - 1) & ~((a) - 1))
+#define ROUND_DOWN(v, a)  (((size_t)(v) - (a) + 1) & ~((a) - 1))
+#define MIN_STACK_SIZE  64
+#define FIRST_ARG_SLOT  9
+#define DEBUG_LEVEL   0
+
+#define fldw(addr, fpreg) asm volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
+#define fstw(fpreg, addr) asm volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
+#define fldd(addr, fpreg) asm volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
+#define fstd(fpreg, addr) asm volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
+
+#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
+
+static inline int ffi_struct_type(ffi_type *t)
+{
+  size_t sz = t->size;
+
+  /* Small structure results are passed in registers,
+   * larger ones are passed by pointer.
+   */
+
+  if (sz <= 1)
+    return FFI_TYPE_UINT8;
+  else if (sz == 2)
+    return FFI_TYPE_UINT16;
+  else if (sz == 3)
+    return FFI_TYPE_SMALL_STRUCT1;
+  else if (sz == 4)
+    return FFI_TYPE_UINT32;
+  else if (sz <= 6)
+    return FFI_TYPE_SMALL_STRUCT2;
+  else if (sz <= 8)
+    return FFI_TYPE_UINT64;
+  else
+    return FFI_TYPE_STRUCT; /* else, we pass it by pointer.. */
+}
+
+/* PA has a downward growing stack, which looks like this:
+ *
+ * Offset
+ *      [ Variable args ]
+ * SP = (4*(n+9))       arg word N
+ * ...
+ * SP-52                arg word 4
+ *      [ Fixed args ]
+ * SP-48                arg word 3
+ * SP-44                arg word 2
+ * SP-40                arg word 1
+ * SP-36                arg word 0
+ *      [ Frame marker ]
+ * ...
+ * SP-20                RP
+ * SP-4                 previous SP
+ *
+ * First 4 non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23
+ * First 2 non-FP 64-bit args are passed in register pairs, starting
+ *   on an even numbered register (i.e. r26/r25 and r24+r23)
+ * First 4 FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L
+ * First 2 FP 64-bit arguments are passed in fr5 and fr7
+ * The rest are passed on the stack starting at SP-52, but 64-bit
+ *   arguments need to be aligned to an 8-byte boundary
+ *
+ * This means we can have holes either in the register allocation,
+ * or in the stack.
+ */
+
+/* ffi_prep_args is called by the assembly routine once stack space
+ * has been allocated for the function's arguments
+ *
+ * The following code will put everything into the stack frame
+ * (which was allocated by the asm routine), and on return
+ * the asm routine will load the arguments that should be
+ * passed by register into the appropriate registers
+ *
+ * NOTE: We load floating point args in this function... that means we
+ * assume gcc will not mess with fp regs in here.
+ */
+
+/*@-exportheader@*/
+void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register ffi_type **p_arg;
+  register void **p_argv;
+  unsigned int slot = FIRST_ARG_SLOT - 1;
+  char *dest_cpy;
+
+  debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, ecif, bytes);
+
+  p_arg = ecif->cif->arg_types;
+  p_argv = ecif->avalue;
+
+  for (i = 0; i < ecif->cif->nargs; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+	{
+	case FFI_TYPE_SINT8:
+	  slot++;
+	  *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT8:
+	  slot++;
+	  *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_SINT16:
+	  slot++;
+	  *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT16:
+	  slot++;
+	  *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_POINTER:
+	  slot++;
+	  debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), slot);
+	  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+	  break;
+
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  slot += 2;
+	  if (slot & 1)
+	    slot++;
+
+	  *(UINT32 *)(stack - slot) = (*(UINT64 *)(*p_argv)) >> 32;
+	  *(UINT32 *)(stack - slot + 1) = (*(UINT64 *)(*p_argv)) & 0xffffffffUL;
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  /* First 4 args go in fr4L - fr7L */
+	  slot++;
+	  switch (slot - FIRST_ARG_SLOT)
+	    {
+	    case 0: fldw(*p_argv, fr4); break;
+	    case 1: fldw(*p_argv, fr5); break;
+	    case 2: fldw(*p_argv, fr6); break;
+	    case 3: fldw(*p_argv, fr7); break;
+	    default:
+	      /* other ones are just passed on the stack */
+	      debug(3, "Storing UINT32(float) in slot %u\n", slot);
+	      *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
+	      break;
+	    }
+	    break;
+
+	case FFI_TYPE_DOUBLE:
+	  slot += 2;
+	  if (slot & 1)
+	    slot++;
+	  switch (slot - FIRST_ARG_SLOT + 1)
+	    {
+	      /* First 2 args go in fr5, fr7 */
+	    case 2: fldd(*p_argv, fr5); break;
+	    case 4: fldd(*p_argv, fr7); break;
+	    default:
+	      debug(3, "Storing UINT64(double) at slot %u\n", slot);
+	      *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
+	      break;
+	    }
+	  break;
+
+	case FFI_TYPE_STRUCT:
+
+	  /* Structs smaller or equal than 4 bytes are passed in one
+	     register. Structs smaller or equal 8 bytes are passed in two
+	     registers. Larger structures are passed by pointer.  */
+
+	  if((*p_arg)->size <= 4) {
+	    slot++;
+	    dest_cpy = (char *)(stack - slot);
+	    dest_cpy += 4 - (*p_arg)->size;
+	    memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
+	  } else if ((*p_arg)->size <= 8) {
+	    slot += 2;
+	    if (slot & 1)
+	      slot++;
+	    dest_cpy = (char *)(stack - slot);
+	    dest_cpy += 8 - (*p_arg)->size;
+	    memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
+	  } else {
+	    slot++;
+	    *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
+	  }
+	  break;
+
+	default:
+	  FFI_ASSERT(0);
+	}
+
+      p_arg++;
+      p_argv++;
+    }
+
+  /* Make sure we didn't mess up and scribble on the stack */
+#if 1
+  {
+    int n;
+
+    debug(5, "Stack setup:\n");
+    for (n = 0; n < (bytes + 3) / 4; n++)
+      {
+	if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
+	debug(5, "%08x ", *(stack - n));
+      }
+    debug(5, "\n");
+  }
+#endif
+
+  FFI_ASSERT(slot * 4 <= bytes);
+
+  return;
+}
+
+static void ffi_size_stack_LINUX(ffi_cif *cif)
+{
+  ffi_type **ptr;
+  int i;
+  int z = 0; /* # stack slots */
+
+  for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
+    {
+      int type = (*ptr)->type;
+
+      switch (type)
+	{
+	case FFI_TYPE_DOUBLE:
+	case FFI_TYPE_UINT64:
+	case FFI_TYPE_SINT64:
+	  z += 2 + (z & 1); /* must start on even regs, so we may waste one */
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  z += 1; /* pass by ptr, callee will copy */
+	  break;
+
+	default: /* <= 32-bit values */
+	  z++;
+	}
+    }
+
+  /* We can fit up to 6 args in the default 64-byte stack frame,
+   * if we need more, we need more stack
+   */
+  if (z <= 6)
+    cif->bytes = MIN_STACK_SIZE; /* min stack size */
+  else
+    cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
+
+  debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
+}
+
+/* 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:
+    case FFI_TYPE_FLOAT:
+    case FFI_TYPE_DOUBLE:
+      cif->flags = (unsigned) cif->rtype->type;
+      break;
+
+    case FFI_TYPE_STRUCT:
+      /* For the return type we have to check the size of the structures.
+	 If the size is smaller or equal 4 bytes, the result is given back
+	 in one register. If the size is smaller or equal 8 bytes than we
+	 return the result in two registers. But if the size is bigger than
+	 8 bytes, we work with pointers.  */
+      cif->flags = ffi_struct_type(cif->rtype);
+      break;
+
+    case FFI_TYPE_UINT64:
+    case FFI_TYPE_SINT64:
+      cif->flags = FFI_TYPE_UINT64;
+      break;
+
+    default:
+      cif->flags = FFI_TYPE_INT;
+      break;
+    }
+
+  /* Lucky us, because of the weird PA ABI we get to do our
+   * own stack sizing....
+   */
+  switch (cif->abi)
+    {
+    case FFI_LINUX:
+      ffi_size_stack_LINUX(cif);
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+
+  return FFI_OK;
+}
+
+/*@-declundef@*/
+/*@-exportheader@*/
+extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned),
+			   /*@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_LINUX:
+      /*@-usedef@*/
+      debug(2, "Calling ffi_call_LINUX: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
+      ffi_call_LINUX(ffi_prep_args_LINUX, &ecif, cif->bytes,
+		     cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+
+    default:
+      FFI_ASSERT(0);
+      break;
+    }
+}
+
+#if FFI_CLOSURES
+/*
+ * This is more-or-less an inverse of ffi_call -- we have arguments on
+ * the stack, and we need to fill them into a cif structure and invoke
+ * the user function. This really ought to be in asm to make sure
+ * the compiler doesn't do things we don't expect...
+ */
+UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
+{
+  ffi_cif *cif;
+  void **avalue;
+  void *rvalue;
+  UINT32 ret[2]; /* function can return up to 64-bits in registers */
+  ffi_type **p_arg;
+  char *tmp;
+  int i, avn, slot = FIRST_ARG_SLOT - 1;
+  register UINT32 r28 asm("r28");
+
+  cif = closure->cif;
+
+  /* if returning via structure, callee will write to our pointer */
+  if (cif->flags == FFI_TYPE_STRUCT)
+    rvalue = (void *)r28;
+  else
+    rvalue = &ret[0];
+
+  avalue = (void **)alloca(cif->nargs * sizeof(void *));
+  avn = cif->nargs;
+  p_arg = cif->arg_types;
+
+  for (i = 0; i < avn; i++)
+    {
+      int type = (*p_arg)->type;
+
+      switch (type)
+	{
+	case FFI_TYPE_SINT8:
+	case FFI_TYPE_UINT8:
+	case FFI_TYPE_SINT16:
+	case FFI_TYPE_UINT16:
+	case FFI_TYPE_SINT32:
+	case FFI_TYPE_UINT32:
+	case FFI_TYPE_POINTER:
+	  slot++;
+	  avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
+	  break;
+
+	case FFI_TYPE_SINT64:
+	case FFI_TYPE_UINT64:
+	  slot += 2;
+	  if (slot & 1)
+	    slot++;
+	  avalue[i] = (void *)(stack - slot);
+	  break;
+
+	case FFI_TYPE_FLOAT:
+	  slot++;
+	  switch (slot - FIRST_ARG_SLOT)
+	    {
+	    case 0: fstw(fr4, (void *)(stack - slot)); break;
+	    case 1: fstw(fr5, (void *)(stack - slot)); break;
+	    case 2: fstw(fr6, (void *)(stack - slot)); break;
+	    case 3: fstw(fr7, (void *)(stack - slot)); break;
+	    }
+	  avalue[i] = (void *)(stack - slot);
+	  break;
+
+	case FFI_TYPE_DOUBLE:
+	  slot += 2;
+	  if (slot & 1)
+	    slot++;
+	  switch (slot - FIRST_ARG_SLOT + 1)
+	    {
+	    case 2: fstd(fr5, (void *)(stack - slot)); break;
+	    case 4: fstd(fr7, (void *)(stack - slot)); break;
+	    }
+	  avalue[i] = (void *)(stack - slot);
+	  break;
+
+	case FFI_TYPE_STRUCT:
+	  /* Structs smaller or equal than 4 bytes are passed in one
+	     register. Structs smaller or equal 8 bytes are passed in two
+	     registers. Larger structures are passed by pointer.  */
+	  if((*p_arg)->size <= 4) {
+	    slot++;
+	    avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
+	      (*p_arg)->size;
+	  } else if ((*p_arg)->size <= 8) {
+	    slot += 2;
+	    if (slot & 1)
+	      slot++;
+	    avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
+	      (*p_arg)->size;
+	  } else {
+	    slot++;
+	    avalue[i] = (void *) *(stack - slot);
+	  }
+	  break;
+
+	default:
+	  FFI_ASSERT(0);
+	}
+
+      p_arg++;
+    }
+
+  /* Invoke the closure.  */
+  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+
+  debug(3, "after calling function, ret[0] = %d, ret[1] = %d\n", ret[0], ret[1]);
+
+  /* Store the result */
+  switch (cif->flags)
+    {
+    case FFI_TYPE_UINT8:
+      *(stack - FIRST_ARG_SLOT) = *(UINT8 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT8:
+      *(stack - FIRST_ARG_SLOT) = *(SINT8 *)&ret[0];
+      break;
+    case FFI_TYPE_UINT16:
+      *(stack - FIRST_ARG_SLOT) = *(UINT16 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT16:
+      *(stack - FIRST_ARG_SLOT) = *(SINT16 *)&ret[0];
+      break;
+    case FFI_TYPE_INT:
+    case FFI_TYPE_UINT32:
+      *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT32:
+      *(stack - FIRST_ARG_SLOT) = *(SINT32 *)&ret[0];
+      break;
+    case FFI_TYPE_SINT64:
+    case FFI_TYPE_UINT64:
+      *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = *(UINT32 *)&ret[1];
+      break;
+
+    case FFI_TYPE_DOUBLE:
+      fldd(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_FLOAT:
+      fldw(rvalue, fr4);
+      break;
+
+    case FFI_TYPE_STRUCT:
+      /* Don't need a return value, done by caller.  */
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT1:
+      tmp = (void*)(stack -  FIRST_ARG_SLOT);
+      tmp += 4 - cif->rtype->size;
+      memcpy((void*)tmp, &ret[0], cif->rtype->size);
+      break;
+
+    case FFI_TYPE_SMALL_STRUCT2:
+      *(stack - FIRST_ARG_SLOT) = ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
+      break;
+
+    case FFI_TYPE_POINTER:
+    case FFI_TYPE_VOID:
+      break;
+
+    default:
+      debug(0, "assert with cif->flags: %d\n",cif->flags);
+      FFI_ASSERT(0);
+      break;
+    }
+  return FFI_OK;
+}
+
+/* Fill in a closure to refer to the specified fun and user_data.  */
+/* cif specifies the argument and result types for fun.  */
+/* the cif must already be prep'ed */
+
+void ffi_closure_LINUX(void);
+
+ffi_status
+ffi_prep_closure (ffi_closure* closure,
+		  ffi_cif* cif,
+		  void (*fun)(ffi_cif*,void*,void**,void*),
+		  void *user_data)
+{
+  UINT32 *tramp = (UINT32 *)(closure->tramp);
+
+  FFI_ASSERT (cif->abi == FFI_LINUX);
+
+  /* Make a small trampoline that will branch to our
+   * handler function. Use PC-relative addressing.
+   */
+  tramp[0] = 0xeaa00000; /* b,l .+8, %r21     ; %r21 <- pc+8             */
+  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21  ; mask priv bits           */
+  tramp[2] = 0x4aa10028; /* ldw  20(%r21),%r1 ; load plabel              */
+  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr         */
+  tramp[4] = 0x0c201096; /* ldw  0(%r1),%r22  ; address of handler       */
+  tramp[5] = 0xeac0c000; /* bv	 %r0(%r22)    ; branch to handler        */
+  tramp[6] = 0x0c281093; /* ldw  4(%r1),%r19  ; GP of handler            */
+  tramp[7] = ((UINT32)(ffi_closure_LINUX) & ~2);
+
+  /* Flush d/icache -- have to flush up 2 two lines because of
+   * alignment
+   */
+  asm volatile (
+		"fdc 0(%0)\n"
+		"fdc %1(%0)\n"
+		"fic 0(%%sr4, %0)\n"
+		"fic %1(%%sr4, %0)\n"
+		: : "r"((unsigned long)tramp & ~31), "r"(32 /* stride */));
+
+  closure->cif  = cif;
+  closure->user_data = user_data;
+  closure->fun  = fun;
+
+  return FFI_OK;
+}
+#endif
+
diff -urN libffi.old/src/pa/ffitarget.h libffi/src/pa/ffitarget.h
--- libffi.old/src/pa/ffitarget.h	1970-01-01 01:00:00.000000000 +0100
+++ libffi/src/pa/ffitarget.h	2004-02-21 14:32:46.000000000 +0100
@@ -0,0 +1,51 @@
+/* -----------------------------------------------------------------*-C-*-
+   ffitarget.h - Copyright (c) 2003 Randolph Chung <tausq@debian.org>
+   Target configuration macros for PARISC.
+
+   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 CYGNUS SOLUTIONS 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_LINUX,
+  FFI_DEFAULT_ABI = FFI_LINUX,
+  FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
+} ffi_abi;
+#endif
+
+/* ---- Definitions for closures ----------------------------------------- */
+
+#define FFI_CLOSURES 1
+#define FFI_NATIVE_RAW_API 0
+
+#define FFI_TRAMPOLINE_SIZE 32
+
+#define FFI_TYPE_SMALL_STRUCT1 -1
+#define FFI_TYPE_SMALL_STRUCT2 -2
+
+#endif
diff -urN libffi.old/src/pa/linux.S libffi/src/pa/linux.S
--- libffi.old/src/pa/linux.S	1970-01-01 01:00:00.000000000 +0100
+++ libffi/src/pa/linux.S	2004-02-21 14:15:37.000000000 +0100
@@ -0,0 +1,310 @@
+/* -----------------------------------------------------------------------
+   linux.S - (c) 2003 Randolph Chung <tausq@debian.org>
+
+   HPPA 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 CYGNUS SOLUTIONS 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>
+
+#define FFI_TYPE_SMALL_STRUCT1 -1
+#define FFI_TYPE_SMALL_STRUCT2 -2
+
+	.text
+	.align 4
+
+	/* void ffi_call_LINUX(void (*)(char *, extended_cif *),
+			       extended_cif *ecif,
+			       unsigned bytes,
+			       unsigned flags,
+			       unsigned *rvalue,
+			       void (*fn)());
+	 */
+
+	.export ffi_call_LINUX,code
+	.import ffi_prep_args_LINUX,code
+
+	.type ffi_call_LINUX, @function
+.LFB1:
+ffi_call_LINUX:
+	.proc
+	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
+	.entry
+	stw %rp, -20(%sp)
+	copy %r3, %r1
+.LCFI11:
+
+	copy %sp, %r3
+.LCFI12:
+
+	/* Setup the stack for calling prep_args...
+	   We want the stack to look like this:
+
+	   [ Previous stack                            ] <- %r3
+
+	   [ 64-bytes register save area               ] <- %r4
+
+	   [ Stack space for actual call, passed as    ] <- %arg0
+	   [     arg0 to ffi_prep_args_LINUX           ]
+
+	   [ Stack for calling prep_args               ] <- %sp
+	 */
+
+	stwm %r1, 64(%sp)
+	stw %r4, 12(%r3)
+.LCFI13:
+	copy %sp, %r4
+
+	addl %arg2, %r4, %arg0                  /* arg stack */
+	stw %arg3, -48(%r3)                     /* save flags; we need it later */
+
+	/* Call prep_args:
+	   %arg0(stack) -- set up above
+	   %arg1(ecif) -- same as incoming param
+	   %arg2(bytes) -- same as incoming param */
+	bl ffi_prep_args_LINUX,%r2
+	ldo 64(%arg0), %sp
+	ldo -64(%sp), %sp
+
+	/* now %sp should point where %arg0 was pointing */
+
+	/* Load the arguments that should be passed in registers */
+	/* The fp args were loaded by the prep_args function */
+	ldw -36(%sp), %arg0
+	ldw -40(%sp), %arg1
+	ldw -44(%sp), %arg2
+	ldw -48(%sp), %arg3
+
+	/* in case the function is going to return a structure
+	 * we need to give it a place to put the result...
+	 */
+	ldw -52(%r3), %ret0                     /* %ret0 <- rvalue */
+	ldw -56(%r3), %r22                      /* %r22 <- function to call */
+	bl $$dyncall, %r31                      /* Call the user function */
+	copy %r31, %rp
+
+	/* Prepare to store the result; we need to recover flags and rvalue */
+	ldw -48(%r3), %r21                      /* r21 <- flags */
+	ldw -52(%r3), %r20                      /* r20 <- rvalue */
+
+	/* Store the result according to the return type... */
+
+checksmst1:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT1, %r21, checksmst2
+	/* There is maybe a better way to handle 3 byte structs.  */
+	SH2ADD %ret0,0,%ret0
+	SH2ADD %ret0,0,%ret0
+	SH2ADD %ret0,0,%ret0
+	SH2ADD %ret0,0,%ret0
+	b done
+	stw %ret0, 0(%r20)
+
+checksmst2:
+	comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, checkint8
+	/* Up to now I don't have a way to handle 6/7 byte structs.
+	   The values are left bounded in the registers. In the struct
+	   itself they are left bounded.  */
+	stw %ret0, 0(%r20)
+	b done
+	stw %ret1, 4(%r20)
+
+checkint8:
+	comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
+	b done
+	stb %ret0, 0(%r20)
+
+checkint16:
+	comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
+	b done
+	sth %ret0, 0(%r20)
+
+checkint32:
+	comib,<>,n FFI_TYPE_UINT32, %r21, checkint
+	b done
+	stw %ret0, 0(%r20)
+
+checkint:
+	comib,<>,n FFI_TYPE_INT, %r21, checkll
+	b done
+	stw %ret0, 0(%r20)
+
+checkll:
+	comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
+	stw %ret0, 0(%r20)
+	b done
+	stw %ret1, 4(%r20)
+
+checkdbl:
+	comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
+	b done
+	fstd %fr4,0(%r20)
+
+checkfloat:
+	comib,<>,n FFI_TYPE_FLOAT, %r21, done
+	fstw %fr4L,0(%r20)
+
+	/* structure returns are either handled by one of the
+	 * INT/UINT64 cases above, or, if passed by pointer,
+	 * is handled by the callee
+	 */
+
+done:
+	/* all done, return */
+	copy %r4, %sp                           /* pop arg stack */
+	ldw 12(%r3), %r4
+	ldwm -64(%sp), %r3                      /* .. and pop stack */
+	ldw -20(%sp), %rp
+	bv %r0(%rp)
+	nop
+	.exit
+	.procend
+.LFE1:
+
+	/* void ffi_closure_LINUX(void);
+	 * Called with closure argument in %r21
+	 */
+	.export ffi_closure_LINUX,code
+	.import ffi_closure_inner_LINUX,code
+
+	.type ffi_closure_LINUX, @function
+.LFB2:
+ffi_closure_LINUX:
+	.proc
+	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
+	.entry
+
+	stw %rp, -20(%sp)
+.LCFI20:
+	copy %r3, %r1
+.LCFI21:
+	copy %sp, %r3
+.LCFI22:
+	stwm %r1, 64(%sp)
+
+	/* Put arguments onto the stack and call ffi_closure_inner */
+	stw %arg0, -36(%r3)
+	stw %arg1, -40(%r3)
+	stw %arg2, -44(%r3)
+	stw %arg3, -48(%r3)
+
+	copy %r21, %arg0
+	bl ffi_closure_inner_LINUX, %r2
+	copy %r3, %arg1
+
+	ldwm -64(%sp), %r3
+	ldw -20(%sp), %rp
+	ldw -36(%sp), %ret0
+	bv %r0(%r2)
+	ldw -40(%sp), %ret1
+
+	.exit
+	.procend
+.LFE2:
+
+	.section        ".eh_frame",EH_FRAME_FLAGS,@progbits
+.Lframe1:
+	.word   .LECIE1-.LSCIE1 ;# Length of Common Information Entry
+.LSCIE1:
+	.word   0x0     ;# CIE Identifier Tag
+	.byte   0x1     ;# CIE Version
+#if 0 // defined _RELOCATABLE || defined __PIC__
+	.ascii "zR\0"   ;# CIE Augmentation
+#else
+	.ascii "\0"     ;# CIE Augmentation
+#endif
+	.uleb128 0x1    ;# CIE Code Alignment Factor
+	.sleb128 4      ;# CIE Data Alignment Factor
+	.byte   0x2     ;# CIE RA Column
+#if 0 // defined _RELOCATABLE || defined __PIC__
+	.uleb128  0x1   ;# Augmentation size
+	.byte	0x1b    ;# FDE Encoding (pcrel sdata4)
+#endif
+	.byte   0xc     ;# DW_CFA_def_cfa
+	.uleb128 0x1e
+	.uleb128 0x0
+	.align 4
+.LECIE1:
+.LSFDE1:
+	.word   .LEFDE1-.LASFDE1        ;# FDE Length
+.LASFDE1:
+	.word   .LASFDE1-.Lframe1       ;# FDE CIE offset
+#if 0 // defined _RELOCATABLE || defined __PIC__
+	.word   .LFB1-. ;# FDE initial location
+#else
+	.word   .LFB1   ;# FDE initial location
+#endif
+	.word   .LFE1-.LFB1     ;# FDE address range
+#if 0 // defined _RELOCATABLE || defined __PIC__
+	.uleb128 0x0    ;# Augmentation size
+#endif
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI11-.LFB1
+	.byte	0x83	;# DW_CFA_offset, column 0x3
+	.uleb128 0x0
+	.byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
+	.uleb128 0x2
+	.sleb128 -5
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI12-.LCFI11
+	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
+	.uleb128 0x3
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI13-.LCFI12
+	.byte	0x84	;# DW_CFA_offset, column 0x4
+	.uleb128 0x3
+
+	.align 4
+.LEFDE1:
+
+.LSFDE2:
+	.word   .LEFDE2-.LASFDE2        ;# FDE Length
+.LASFDE2:
+	.word   .LASFDE2-.Lframe1       ;# FDE CIE offset
+#if 0 // defined _RELOCATABLE || defined __PIC__
+	.word   .LFB2-. ;# FDE initial location
+#else
+	.word   .LFB2   ;# FDE initial location
+#endif
+	.word   .LFE2-.LFB2     ;# FDE address range
+#if 0 // defined _RELOCATABLE || defined __PIC__
+	.uleb128 0x0    ;# Augmentation size
+#endif
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI21-.LFB2
+	.byte   0x83    ;# DW_CFA_offset, column 0x3
+	.uleb128 0x0
+	.byte   0x11    ;# DW_CFA_offset_extended_sf
+	.uleb128 0x2
+	.sleb128 -5
+
+	.byte   0x4     ;# DW_CFA_advance_loc4
+	.word   .LCFI12-.LCFI11
+	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
+	.uleb128 0x3
+
+	.align 4
+.LEFDE2:
+
diff -urN libffi.old/src/prep_cif.c libffi/src/prep_cif.c
--- libffi.old/src/prep_cif.c	2003-11-07 09:57:46.000000000 +0100
+++ libffi/src/prep_cif.c	2004-02-21 14:15:37.000000000 +0100
@@ -113,7 +113,7 @@
   FFI_ASSERT_VALID_TYPE(cif->rtype);
 
   /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
-#if !defined M68K && !defined __x86_64__ && !defined S390
+#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
   /* Make space for the return structure pointer */
   if (cif->rtype->type == FFI_TYPE_STRUCT
 #ifdef SPARC
@@ -134,7 +134,7 @@
 	 check after the initialization.  */
       FFI_ASSERT_VALID_TYPE(*ptr);
 
-#if !defined __x86_64__ && !defined S390
+#if !defined __x86_64__ && !defined S390 && !defined PA
 #ifdef SPARC
       if (((*ptr)->type == FFI_TYPE_STRUCT
 	   && ((*ptr)->size > 16 || cif->abi != FFI_V9))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]