From d7f68a672e8e03eb7fd9fb0a9dce83558d6c5724 Mon Sep 17 00:00:00 2001
From: Andreas Tobler <a.tobler@schweiz.org>
Date: Mon, 25 Aug 2008 18:35:20 +0000
Subject: [PATCH] ffitarget.h (ffi_abi): Add FFI_LINUX and FFI_LINUX_SOFT_FLOAT
 to the POWERPC_FREEBSD enum.

2008-08-25  Andreas Tobler  <a.tobler@schweiz.org>

	* src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and
	FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum.
	Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT.
	Adjust copyright notice.
	* src/powerpc/ffi.c: Add two new flags to indicate if we have one
	register or two register to use for FFI_SYSV structs.
	(ffi_prep_cif_machdep): Pass the right register flag introduced above.
	(ffi_closure_helper_SYSV): Fix the return type for
	FFI_SYSV_TYPE_SMALL_STRUCT. Comment.
	Adjust copyright notice.

From-SVN: r139567
---
 libffi/ChangeLog               | 13 +++++++++++++
 libffi/src/powerpc/ffi.c       | 19 ++++++++++++++-----
 libffi/src/powerpc/ffitarget.h |  8 ++++++--
 3 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 850bbd4b35b9..cffc4d25ff58 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,16 @@
+2008-08-25  Andreas Tobler  <a.tobler@schweiz.org>
+
+	* src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and
+	FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum.
+	Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT.
+	Adjust copyright notice.
+	* src/powerpc/ffi.c: Add two new flags to indicate if we have one
+	register or two register to use for FFI_SYSV structs.
+	(ffi_prep_cif_machdep): Pass the right register flag introduced above.
+	(ffi_closure_helper_SYSV): Fix the return type for
+	FFI_SYSV_TYPE_SMALL_STRUCT. Comment.
+	Adjust copyright notice.
+
 2008-07-16  Kaz Kojima  <kkojima@gcc.gnu.org>
 
 	* src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned
diff --git a/libffi/src/powerpc/ffi.c b/libffi/src/powerpc/ffi.c
index e6b869f8737c..73c1dd207669 100644
--- a/libffi/src/powerpc/ffi.c
+++ b/libffi/src/powerpc/ffi.c
@@ -1,6 +1,6 @@
 /* -----------------------------------------------------------------------
    ffi.c - Copyright (c) 1998 Geoffrey Keating
-   Copyright (C) 2007 Free Software Foundation, Inc
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc
 
    PowerPC Foreign Function Interface
 
@@ -43,6 +43,10 @@ enum {
 
   FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
 
+  FLAG_SYSV_SMST_R4     = 1 << (31-16), /* cr4, use r4 for FFI_SYSV 8 byte
+					   structs.  */
+  FLAG_SYSV_SMST_R3     = 1 << (31-15), /* cr3, use r3 for FFI_SYSV 4 byte
+					   structs.  */
   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
   FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
@@ -679,14 +683,14 @@ ffi_prep_cif_machdep (ffi_cif *cif)
 		 The same applies for the structs returned in r3/r4.  */
 	      if (size <= 4)
 		{
-		  flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 1);
+		  flags |= FLAG_SYSV_SMST_R3;
 		  flags |= 8 * (4 - size) << 4;
 		  break;
 		}
 	      /* These structs are returned in r3 and r4. See above.   */
 	      if  (size <= 8)
 		{
-		  flags |= 1 << (31 - FFI_SYSV_TYPE_SMALL_STRUCT - 2);
+		  flags |= FLAG_SYSV_SMST_R4;
 		  flags |= 8 * (8 - size) << 4;
 		  break;
 		}
@@ -1248,10 +1252,15 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
 
   /* Tell ffi_closure_SYSV how to perform return type promotions.
      Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
-     we have to tell ffi_closure_SYSV how to treat them.  */
+     we have to tell ffi_closure_SYSV how to treat them. We combine the base
+     type FFI_SYSV_TYPE_SMALL_STRUCT - 1  with the size of the struct.
+     So a one byte struct gets the return type 16. Return type 1 to 15 are
+     already used and we never have a struct with size zero. That is the reason
+     for the subtraction of 1. See the comment in ffitarget.h about ordering.
+  */
   if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
       && size <= 8)
-    return FFI_SYSV_TYPE_SMALL_STRUCT + size;
+    return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
   else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
 	   && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
diff --git a/libffi/src/powerpc/ffitarget.h b/libffi/src/powerpc/ffitarget.h
index e3fa30be6b55..a39a62671661 100644
--- a/libffi/src/powerpc/ffitarget.h
+++ b/libffi/src/powerpc/ffitarget.h
@@ -1,6 +1,6 @@
 /* -----------------------------------------------------------------*-C-*-
    ffitarget.h - Copyright (c) 1996-2003  Red Hat, Inc.
-   Copyright (C) 2007 Free Software Foundation, Inc
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc
    Target configuration macros for PowerPC.
 
    Permission is hereby granted, free of charge, to any person obtaining
@@ -77,6 +77,8 @@ typedef enum ffi_abi {
   FFI_SYSV,
   FFI_GCC_SYSV,
   FFI_LINUX64,
+  FFI_LINUX,
+  FFI_LINUX_SOFT_FLOAT,
   FFI_DEFAULT_ABI = FFI_SYSV,
 #endif
 
@@ -95,7 +97,9 @@ typedef enum ffi_abi {
 /* Needed for soft-float long-double-128 support.  */
 #define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1)
 
-/* Needed for FFI_SYSV small structure returns.  */
+/* Needed for FFI_SYSV small structure returns.
+   We use two flag bits, (FLAG_SYSV_SMST_R3, FLAG_SYSV_SMST_R4) which are
+   defined in ffi.c, to determine the exact return type and its size.  */
 #define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
 
 #if defined(POWERPC64) || defined(POWERPC_AIX)
-- 
GitLab