public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][ARM] FreeBSD ARM support, EABI, v3
@ 2014-12-29 18:45 Andreas Tobler
  2015-01-08 16:27 ` Richard Earnshaw
  0 siblings, 1 reply; 7+ messages in thread
From: Andreas Tobler @ 2014-12-29 18:45 UTC (permalink / raw)
  To: GCC Patches, rearnsha, ramana.gcc

[-- Attachment #1: Type: text/plain, Size: 2288 bytes --]

All,

here is the third attempt to support ARM with FreeBSD.

In the meantime we found another issue in the unwinder where I had to 
adapt some stuff.

The unwind_phase2_forced function in libgcc calls a stop_fn function. 
This stop_fn is in FreeBSD's libthr implementation and is called 
thread_unwind_stop. This thread_unwind_stop is a generic function used 
on all FreeBSD archs.

The issue is now that this thread_unwind_stop expects a double int for 
the exception_class, like on every other arch. For ARM EABI this 
exception_class is an array of char which is passed in one register as 
pointer vs. two registers for a double int.

To solve this issue we defined the exception_class as double integer for 
FreeBSD.

This adaptation reduced the failure count in libstdc++ by about 40 fails.

I build and test this port on a regular basis and I post the results to 
the usual place.

I'd appreciate some feedback and if possible an ACK if ok for trunk.

Thank you,
Andreas

Here the previous posts to this subject:

First version:
https://gcc.gnu.org/ml/gcc-patches/2014-11/msg00029.html

Second version:
https://gcc.gnu.org/ml/gcc-patches/2014-11/msg03427.html


toplevel:

	* configure.ac: Don't add ${libgcj} for arm*-*-freebsd*.
	* configure: Regenerate.
gcc:
	* config.gcc (arm*-*-freebsd*): New configuration.
	* config/arm/freebsd.h: New file.
	* config.host: Add extra components for arm*-*-freebsd*.
	* config/arm/arm.h: Introduce MAX_SYNC_LIBFUNC_SIZE.
	* config/arm/arm.c (arm_init_libfuncs): Use MAX_SYNC_LIBFUNC_SIZE.
	* ginclude/unwind-arm-common.h (_Uwind_Control_Block): Define
	exception_class as double integer for FreeBSD ARM.
	(_Unwind_Exception): Define _Unwind_Exception_Class as double integer
	for FreeBSD ARM.

libgcc:

	* config.host (arm*-*-freebsd*): Add new configuration for
	arm*-*-freebsd*.
	* config/arm/freebsd-atomic.c: New file.
	* config/arm/t-freebsd: Likewise.
	* config/arm/unwind-arm.h: Add __FreeBSD__ to the list of
	'PC-relative indirect' OS's.

libatomic:

	* configure.tgt: Exclude arm*-*-freebsd* from try_ifunc.

libstdc++-v3:

	* configure.host: Add arm*-*-freebsd* port_specific_symbol_files.
	* libsupc++/unwind-cxx.h (__is_gxx_exception_class,
	__is_dependent_exception): Exclude FreeBSD ARM from the
	__ARM_EABI_UNWINDER__ ifdef.

[-- Attachment #2: gcc5_fbsd_arm_20141230-1.diff --]
[-- Type: text/plain, Size: 26097 bytes --]

Index: configure
===================================================================
--- configure	(revision 219100)
+++ configure	(working copy)
@@ -3425,6 +3425,9 @@
   alpha*-*-*vms*)
     noconfigdirs="$noconfigdirs ${libgcj}"
     ;;
+  arm*-*-freebsd*)
+    noconfigdirs="$noconfigdirs ${libgcj}"
+    ;;
   arm-wince-pe)
     noconfigdirs="$noconfigdirs ${libgcj}"
     ;;
Index: configure.ac
===================================================================
--- configure.ac	(revision 219100)
+++ configure.ac	(working copy)
@@ -779,6 +779,9 @@
   alpha*-*-*vms*)
     noconfigdirs="$noconfigdirs ${libgcj}"
     ;;
+  arm*-*-freebsd*)
+    noconfigdirs="$noconfigdirs ${libgcj}"
+    ;;
   arm-wince-pe)
     noconfigdirs="$noconfigdirs ${libgcj}"
     ;;
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 219100)
+++ gcc/config/arm/arm.c	(working copy)
@@ -2160,7 +2160,7 @@
 {
   /* For Linux, we have access to kernel support for atomic operations.  */
   if (arm_abi == ARM_ABI_AAPCS_LINUX)
-    init_sync_libfuncs (2 * UNITS_PER_WORD);
+    init_sync_libfuncs (MAX_SYNC_LIBFUNC_SIZE);
 
   /* There are no special library functions unless we are using the
      ARM BPABI.  */
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	(revision 219100)
+++ gcc/config/arm/arm.h	(working copy)
@@ -766,6 +766,11 @@
 #define PCC_BITFIELD_TYPE_MATTERS TARGET_AAPCS_BASED
 #endif
 
+/* The maximum size of the sync library functions supported.  */
+#ifndef MAX_SYNC_LIBFUNC_SIZE
+#define MAX_SYNC_LIBFUNC_SIZE (2 * UNITS_PER_WORD);
+#endif
+
 \f
 /* Standard register usage.  */
 
Index: gcc/config/arm/freebsd.h
===================================================================
--- gcc/config/arm/freebsd.h	(revision 0)
+++ gcc/config/arm/freebsd.h	(working copy)
@@ -0,0 +1,180 @@
+/* Definitions of target machine for GNU compiler, FreeBSD/arm version.
+   Copyright (C) 2002-2014 Free Software Foundation, Inc.
+   Contributed by Wasabi Systems, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#undef  SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC FBSD_CPP_SPEC
+
+#undef  SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS					\
+  { "subtarget_extra_asm_spec",	SUBTARGET_EXTRA_ASM_SPEC },	\
+  { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC }, 	\
+  { "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }
+
+#undef SUBTARGET_EXTRA_ASM_SPEC
+#define SUBTARGET_EXTRA_ASM_SPEC \
+  "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=5} " TARGET_FIX_V4BX_SPEC " \
+  %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
+
+#undef SUBTARGET_ASM_FLOAT_SPEC
+#ifdef TARGET_FREEBSD_ARM_HARD_FLOAT
+/* Default to full vfp if we build for arm*hf.  */
+#define SUBTARGET_ASM_FLOAT_SPEC "%{!mfpu=*:-mfpu=vfp}"
+#else
+#define SUBTARGET_ASM_FLOAT_SPEC "%{!mfpu=*:-mfpu=softvfp}"
+#endif
+
+#undef	LINK_SPEC
+#define LINK_SPEC "							\
+  %{p:%nconsider using `-pg' instead of `-p' with gprof (1) }		\
+  %{v:-V}								\
+  %{assert*} %{R*} %{rpath*} %{defsym*}					\
+  %{shared:-Bshareable %{h*} %{soname*}}				\
+  %{!shared:								\
+    %{!static:								\
+      %{rdynamic:-export-dynamic}					\
+      %{!dynamic-linker:-dynamic-linker %(fbsd_dynamic_linker) }}	\
+    %{static:-Bstatic}}							\
+  %{!static:--hash-style=both --enable-new-dtags}			\
+  %{symbolic:-Bsymbolic}						\
+  -X %{mbig-endian:-EB} %{mlittle-endian:-EL}"
+
+/* TARGET_BIG_ENDIAN_DEFAULT is set in
+   config.gcc for big endian configurations.  */
+#if TARGET_BIG_ENDIAN_DEFAULT
+#define TARGET_ENDIAN_DEFAULT    MASK_BIG_END
+#define TARGET_ENDIAN_OPTION     "mbig-endian"
+#define TARGET_LINKER_EMULATION  "armelfb_fbsd"
+#else
+#define TARGET_ENDIAN_DEFAULT    0
+#define TARGET_ENDIAN_OPTION     "mlittle-endian"
+#define TARGET_LINKER_EMULATION  "armelf_fbsd"
+#endif
+
+#undef	SUBTARGET_EXTRA_LINK_SPEC
+#define SUBTARGET_EXTRA_LINK_SPEC " -m " TARGET_LINKER_EMULATION " -p"
+
+#undef  TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() 		\
+  do						\
+    {						\
+	FBSD_TARGET_OS_CPP_BUILTINS ();		\
+	TARGET_BPABI_CPP_BUILTINS ();		\
+    }						\
+  while (false)
+
+/* We default to a soft-float ABI so that binaries can run on all
+   target hardware.  */
+#undef TARGET_DEFAULT_FLOAT_ABI
+#ifdef TARGET_FREEBSD_ARM_HARD_FLOAT
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
+#else
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
+#endif
+
+#undef ARM_DEFAULT_ABI
+
+/* AACPS_LINUX has access to kernel atomic ops while we don't.
+   But AACPS defaults to short_enums.  */
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_INTERWORK | TARGET_ENDIAN_DEFAULT)
+
+/* We do not have any MULTILIB_OPTIONS specified, so there are no
+   MULTILIB_DEFAULTS.  */
+#undef  MULTILIB_DEFAULTS
+
+/*  Use the AAPCS type for wchar_t, override the one from config/freebsd.h.  */
+#undef  WCHAR_TYPE
+#define WCHAR_TYPE  "unsigned int"
+
+#undef  WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE BITS_PER_WORD
+
+#if defined (TARGET_FREEBSD_ARMv6)
+#undef  SUBTARGET_CPU_DEFAULT
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm1176jzs
+#else
+#undef  SUBTARGET_CPU_DEFAULT
+#define SUBTARGET_CPU_DEFAULT   TARGET_CPU_arm9
+#endif
+
+#define SUBTARGET_OVERRIDE_OPTIONS		\
+do {						\
+    if (unaligned_access)			\
+	unaligned_access = 0;			\
+} while (0)
+
+#undef MAX_SYNC_LIBFUNC_SIZE
+#define MAX_SYNC_LIBFUNC_SIZE 4 /* UNITS_PER_WORD not defined yet.  */
+
+/* FreeBSD does its profiling differently to the Acorn compiler.  We
+   don't need a word following the mcount call; and to skip it
+   requires either an assembly stub or use of fomit-frame-pointer when
+   compiling the profiling functions.  Since we break Acorn CC
+   compatibility below a little more won't hurt.  */
+
+#undef ARM_FUNCTION_PROFILER
+#define ARM_FUNCTION_PROFILER(STREAM,LABELNO)		\
+{							\
+  asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n");		\
+  asm_fprintf (STREAM, "\tbl\t__mcount%s\n",		\
+	       (TARGET_ARM && NEED_PLT_RELOC)		\
+	       ? "(PLT)" : "");				\
+}
+
+/* Clear the instruction cache from `BEG' to `END'.  This makes a
+   call to the ARM_SYNC_ICACHE architecture specific syscall.  */
+#define CLEAR_INSN_CACHE(BEG, END)					\
+do									\
+  {									\
+    extern int sysarch (int number, void *args);			\
+    struct								\
+      {									\
+	unsigned int addr;						\
+	int          len;						\
+      } s;								\
+    s.addr = (unsigned int) (BEG);					\
+    s.len = (END) - (BEG);						\
+    (void) sysarch (0, &s);						\
+  }									\
+while (0)
+
+/* This is how we tell the assembler that two symbols have the same value.  */
+#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
+  do					   \
+    {					   \
+     assemble_name (FILE, NAME1); 	   \
+     fputs (" = ", FILE);		   \
+     assemble_name (FILE, NAME2);	   \
+     fputc ('\n', FILE);		   \
+    }					   \
+  while (0)
+
+/* Add  .note.GNU-stack.  */
+#undef NEED_INDICATE_EXEC_STACK
+#define NEED_INDICATE_EXEC_STACK 1
+
+#define ARM_TARGET2_DWARF_FORMAT (DW_EH_PE_pcrel | DW_EH_PE_indirect)
+
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 219100)
+++ gcc/config.gcc	(working copy)
@@ -259,7 +259,6 @@
    arm*-wince-pe*			\
  | arm*-*-ecos-elf			\
  | arm*-*-elf				\
- | arm*-*-freebsd*			\
  | arm*-*-linux*			\
  | arm*-*-uclinux*			\
  | i[34567]86-go32-*			\
@@ -1010,6 +1009,27 @@
 	extra_options="${extra_options} arm/vxworks.opt"
 	tmake_file="${tmake_file} arm/t-arm arm/t-vxworks"
 	;;
+arm*-*-freebsd*)                # ARM FreeBSD EABI
+	tm_file="dbxelf.h elfos.h ${fbsd_tm_file} arm/elf.h"
+	case $target in
+	arm*b-*-freebsd*)
+	    tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+	    ;;
+	esac
+	tmake_file="${tmake_file} arm/t-arm arm/t-bpabi"
+	tm_file="${tm_file} arm/bpabi.h arm/freebsd.h arm/aout.h arm/arm.h"
+	case $target in
+	armv6*-*-freebsd*)
+	    tm_defines="${tm_defines} TARGET_FREEBSD_ARMv6=1"
+	    ;;
+	esac
+	case $target in
+	arm*hf-*-freebsd*)
+	    tm_defines="${tm_defines} TARGET_FREEBSD_ARM_HARD_FLOAT=1"
+	    ;;
+	esac
+	with_tls=${with_tls:-gnu}
+	;;
 arm*-*-netbsdelf*)
 	tm_file="dbxelf.h elfos.h netbsd.h netbsd-elf.h arm/elf.h arm/aout.h ${tm_file} arm/netbsd-elf.h"
 	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
Index: gcc/config.host
===================================================================
--- gcc/config.host	(revision 219100)
+++ gcc/config.host	(working copy)
@@ -99,7 +99,7 @@
 esac
 
 case ${host} in
-  arm*-*-linux*)
+  arm*-*-freebsd* | arm*-*-linux*)
     case ${target} in
       arm*-*-*)
 	host_extra_gcc_objs="driver-arm.o"
Index: gcc/ginclude/unwind-arm-common.h
===================================================================
--- gcc/ginclude/unwind-arm-common.h	(revision 219100)
+++ gcc/ginclude/unwind-arm-common.h	(working copy)
@@ -82,7 +82,11 @@
 
   struct _Unwind_Control_Block
     {
+#ifdef __FreeBSD__
+      unsigned exception_class __attribute__((__mode__(__DI__)));
+#else
       char exception_class[8];
+#endif
       void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
       /* Unwinder cache, private fields for the unwinder's use */
       struct
@@ -181,7 +185,11 @@
 
   /* Support functions for the PR.  */
 #define _Unwind_Exception _Unwind_Control_Block
+#ifdef __FreeBSD__
+  typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
+#else
   typedef char _Unwind_Exception_Class[8];
+#endif
 
   void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
   _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
Index: libatomic/configure.tgt
===================================================================
--- libatomic/configure.tgt	(revision 219100)
+++ libatomic/configure.tgt	(working copy)
@@ -37,10 +37,15 @@
 
   arm*)
 	ARCH=arm
-	# ??? Detect when -march=armv7 is already enabled.
-	try_ifunc=yes
-	;;
-
+	case "${target}" in
+            arm*-*-freebsd*)
+                ;;
+            *)
+                # ??? Detect when -march=armv7 is already enabled.
+                try_ifunc=yes
+                ;;
+        esac
+        ;;
   sparc)
 	case " ${CC} ${CFLAGS} " in
 	  *" -m64 "*)
Index: libgcc/config/arm/freebsd-atomic.c
===================================================================
--- libgcc/config/arm/freebsd-atomic.c	(revision 0)
+++ libgcc/config/arm/freebsd-atomic.c	(working copy)
@@ -0,0 +1,224 @@
+/* FreeBSD specific atomic operations for ARM EABI.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+
+#define HIDDEN __attribute__ ((visibility ("hidden")))
+
+#define ARM_VECTORS_HIGH 0xffff0000U
+#define ARM_TP_ADDRESS   (ARM_VECTORS_HIGH + 0x1000)
+#define ARM_RAS_START    (ARM_TP_ADDRESS + 4)
+
+void HIDDEN
+__sync_synchronize (void)
+{
+#if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__)       \
+    || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6T2__)  \
+    || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__)  \
+    || defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
+#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
+    __asm __volatile ("dmb" : : : "memory");
+#else
+    __asm __volatile ("mcr p15, 0, r0, c7, c10, 5" : : : "memory");
+#endif
+#else
+    __asm __volatile ("nop" : : : "memory");
+#endif
+}
+
+#if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__)        \
+    || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6T2__)   \
+    || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__)   \
+    || defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
+
+/* These systems should be supported by the compiler.  */
+
+#else /* __ARM_ARCH_5__  */
+
+#define	SYNC_LOCK_TEST_AND_SET_N(N, TYPE, LDR, STR)			\
+TYPE HIDDEN    								\
+__sync_lock_test_and_set_##N (TYPE *mem, TYPE val)			\
+{									\
+        unsigned int old, temp, ras_start;                              \
+                                                                        \
+        ras_start = ARM_RAS_START;					\
+        __asm volatile (						\
+                /* Set up Restartable Atomic Sequence.  */		\
+                "1:"							\
+                "\tadr   %2, 1b\n"					\
+                "\tstr   %2, [%5]\n"					\
+                "\tadr   %2, 2f\n"					\
+                "\tstr   %2, [%5, #4]\n"				\
+                                                                        \
+                "\t"LDR" %0, %4\n"	/* Load old value.  */		\
+                "\t"STR" %3, %1\n"	/* Store new value.  */		\
+                                                                        \
+                /* Tear down Restartable Atomic Sequence.  */		\
+                "2:"							\
+                "\tmov   %2, #0x00000000\n"				\
+                "\tstr   %2, [%5]\n"					\
+                "\tmov   %2, #0xffffffff\n"				\
+                "\tstr   %2, [%5, #4]\n"				\
+                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
+                : "r" (val), "m" (*mem), "r" (ras_start));		\
+        return (old);							\
+}
+
+#define SYNC_LOCK_RELEASE_N(N, TYPE)					\
+void HIDDEN								\
+__sync_lock_release_##N (TYPE *ptr)     				\
+{					       				\
+    /* All writes before this point must be seen before we release	\
+       the lock itself.  */						\
+    __sync_synchronize ();     						\
+    *ptr = 0;								\
+}
+
+#define	SYNC_VAL_CAS_N(N, TYPE, LDR, STREQ)             		\
+TYPE HIDDEN    								\
+__sync_val_compare_and_swap_##N (TYPE *mem, TYPE expected,		\
+    TYPE desired)							\
+{									\
+        unsigned int old, temp, ras_start;                              \
+                                                                        \
+        ras_start = ARM_RAS_START;					\
+        __asm volatile (						\
+                /* Set up Restartable Atomic Sequence.  */		\
+                "1:"							\
+                "\tadr   %2, 1b\n"					\
+                "\tstr   %2, [%6]\n"					\
+                "\tadr   %2, 2f\n"					\
+                "\tstr   %2, [%6, #4]\n"				\
+                                                                        \
+                "\t"LDR" %0, %5\n"     /* Load old value.  */		\
+                "\tcmp   %0, %3\n"     /* Compare to expected value.  */\
+                "\t"STREQ" %4, %1\n"   /* Store new value.  */		\
+                                                                        \
+                /* Tear down Restartable Atomic Sequence.  */		\
+                "2:"							\
+                "\tmov   %2, #0x00000000\n"				\
+                "\tstr   %2, [%6]\n"					\
+                "\tmov   %2, #0xffffffff\n"				\
+                "\tstr   %2, [%6, #4]\n"				\
+                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
+                : "r" (expected), "r" (desired), "m" (*mem),		\
+                  "r" (ras_start));					\
+        return (old);							\
+}
+
+typedef unsigned char bool;
+
+#define SYNC_BOOL_CAS_N(N, TYPE)                                        \
+bool HIDDEN								\
+__sync_bool_compare_and_swap_##N (TYPE *ptr, TYPE oldval,		\
+                                  TYPE newval)                          \
+{									\
+    TYPE actual_oldval							\
+      = __sync_val_compare_and_swap_##N (ptr, oldval, newval);          \
+    return (oldval == actual_oldval);					\
+}
+
+#define	SYNC_FETCH_AND_OP_N(N, TYPE, LDR, STR, NAME, OP)		\
+TYPE HIDDEN								\
+__sync_fetch_and_##NAME##_##N (TYPE *mem, TYPE val)	       		\
+{									\
+        unsigned int old, temp, ras_start;                              \
+                                                                        \
+        ras_start = ARM_RAS_START;					\
+        __asm volatile (						\
+                /* Set up Restartable Atomic Sequence.  */		\
+                "1:"							\
+                "\tadr   %2, 1b\n"					\
+                "\tstr   %2, [%5]\n"					\
+                "\tadr   %2, 2f\n"					\
+                "\tstr   %2, [%5, #4]\n"				\
+                                                                        \
+                "\t"LDR" %0, %4\n"	/* Load old value.  */		\
+                "\t"OP"  %2, %0, %3\n"	/* Calculate new value.  */	\
+                "\t"STR" %2, %1\n"	/* Store new value.  */		\
+                                                                        \
+                /* Tear down Restartable Atomic Sequence.  */		\
+                "2:"							\
+                "\tmov   %2, #0x00000000\n"				\
+                "\tstr   %2, [%5]\n"					\
+                "\tmov   %2, #0xffffffff\n"				\
+                "\tstr   %2, [%5, #4]\n"				\
+                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
+                : "r" (val), "m" (*mem), "r" (ras_start));		\
+        return (old);							\
+}
+
+#define	SYNC_OP_AND_FETCH_N(N, TYPE, LDR, STR, NAME, OP)		\
+TYPE HIDDEN   								\
+__sync_##NAME##_and_fetch_##N (TYPE *mem, TYPE val)	       		\
+{									\
+        unsigned int old, temp, ras_start;                              \
+                                                                        \
+        ras_start = ARM_RAS_START;					\
+        __asm volatile (						\
+                /* Set up Restartable Atomic Sequence.  */		\
+                "1:"							\
+                "\tadr   %2, 1b\n"					\
+                "\tstr   %2, [%5]\n"					\
+                "\tadr   %2, 2f\n"					\
+                "\tstr   %2, [%5, #4]\n"				\
+                                                                        \
+                "\t"LDR" %0, %4\n"	/* Load old value.  */		\
+                "\t"OP"  %2, %0, %3\n"	/* Calculate new value.  */	\
+                "\t"STR" %2, %1\n"	/* Store new value.  */		\
+                                                                        \
+                /* Tear down Restartable Atomic Sequence.  */		\
+                "2:"							\
+                "\tmov   %2, #0x00000000\n"				\
+                "\tstr   %2, [%5]\n"					\
+                "\tmov   %2, #0xffffffff\n"				\
+                "\tstr   %2, [%5, #4]\n"				\
+                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
+                : "r" (val), "m" (*mem), "r" (ras_start));		\
+        return (old);							\
+}
+
+#define	EMIT_ALL_OPS_N(N, TYPE, LDR, STR, STREQ)			\
+SYNC_LOCK_TEST_AND_SET_N (N, TYPE, LDR, STR)				\
+SYNC_LOCK_RELEASE_N (N, TYPE)                                           \
+SYNC_VAL_CAS_N (N, TYPE, LDR, STREQ)	                		\
+SYNC_BOOL_CAS_N (N, TYPE)                                               \
+SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, add, "add")		        \
+SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, and, "and")		        \
+SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, or, "orr")		        \
+SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, sub, "sub")		        \
+SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, xor, "eor")                     \
+SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, add, "add")		        \
+SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, and, "and")		        \
+SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, or, "orr")		        \
+SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, sub, "sub")		        \
+SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, xor, "eor")
+
+
+
+EMIT_ALL_OPS_N (1, unsigned char, "ldrb", "strb", "streqb")
+EMIT_ALL_OPS_N (2, unsigned short, "ldrh", "strh", "streqh")
+EMIT_ALL_OPS_N (4, unsigned int, "ldr", "str", "streq")
+
+#endif
Index: libgcc/config/arm/t-freebsd
===================================================================
--- libgcc/config/arm/t-freebsd	(revision 0)
+++ libgcc/config/arm/t-freebsd	(working copy)
@@ -0,0 +1,9 @@
+# Just for these, we omit the frame pointer since it makes such a big
+# difference.  It is then pointless adding debugging.
+HOST_LIBGCC2_CFLAGS += -fomit-frame-pointer
+
+LIB2ADD_ST += $(srcdir)/config/arm/freebsd-atomic.c
+
+# Use a version of div0 which raises SIGFPE.
+LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx
+
Index: libgcc/config/arm/unwind-arm.h
===================================================================
--- libgcc/config/arm/unwind-arm.h	(revision 219100)
+++ libgcc/config/arm/unwind-arm.h	(working copy)
@@ -48,7 +48,8 @@
       if (!tmp)
 	return 0;
 
-#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__)
+#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__) \
+    || defined(__FreeBSD__)
       /* Pc-relative indirect.  */
 #define _GLIBCXX_OVERRIDE_TTYPE_ENCODING (DW_EH_PE_pcrel | DW_EH_PE_indirect)
       tmp += ptr;
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 219100)
+++ libgcc/config.host	(working copy)
@@ -366,6 +366,13 @@
 	tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
 	extra_parts="$extra_parts crti.o crtn.o"
 	;;
+arm*-*-freebsd*)                # ARM FreeBSD EABI
+	tmake_file="${tmake_file} arm/t-arm t-fixedpoint-gnu-prefix arm/t-elf"
+	tmake_file="${tmake_file} arm/t-bpabi arm/t-freebsd t-slibgcc-libgcc"
+	tm_file="${tm_file} arm/bpabi-lib.h"
+	unwind_header=config/arm/unwind-arm.h
+	tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+	;;
 arm*-*-netbsdelf*)
 	tmake_file="$tmake_file arm/t-arm arm/t-netbsd t-slibgcc-gld-nover"
 	;;
Index: libstdc++-v3/configure.host
===================================================================
--- libstdc++-v3/configure.host	(revision 219100)
+++ libstdc++-v3/configure.host	(working copy)
@@ -366,6 +366,9 @@
 	;;
     esac
     ;;
+  arm*-*-freebsd*)
+     port_specific_symbol_files="\$(srcdir)/../config/os/gnu-linux/arm-eabi-extra.ver"
+     ;;
   powerpc*-*-darwin*)
     port_specific_symbol_files="\$(srcdir)/../config/os/bsd/darwin/ppc-extra.ver"
     ;;
Index: libstdc++-v3/libsupc++/unwind-cxx.h
===================================================================
--- libstdc++-v3/libsupc++/unwind-cxx.h	(revision 219100)
+++ libstdc++-v3/libsupc++/unwind-cxx.h	(working copy)
@@ -235,7 +235,7 @@
   return reinterpret_cast<__cxa_dependent_exception *>(exc + 1) - 1;
 }
 
-#ifdef __ARM_EABI_UNWINDER__
+#if defined (__ARM_EABI_UNWINDER__) && !defined (__FreeBSD__)
 static inline bool
 __is_gxx_exception_class(_Unwind_Exception_Class c)
 {
@@ -309,13 +309,7 @@
   c[6] = 'R';
   c[7] = '\0';
 }
-
-static inline void*
-__gxx_caught_object(_Unwind_Exception* eo)
-{
-  return (void*)eo->barrier_cache.bitpattern[0];
-}
-#else // !__ARM_EABI_UNWINDER__
+#else // !__ARM_EABI_UNWINDER__ || __FreeBSD__
 // This is the primary exception class we report -- "GNUCC++\0".
 const _Unwind_Exception_Class __gxx_primary_exception_class
 = ((((((((_Unwind_Exception_Class) 'G' 
@@ -339,6 +333,16 @@
     << 8 | (_Unwind_Exception_Class) '+')
    << 8 | (_Unwind_Exception_Class) '\x01');
 
+const _Unwind_Exception_Class __gxx_forced_unwind_class
+= ((((((((_Unwind_Exception_Class) 'G'
+        << 8 | (_Unwind_Exception_Class) 'N')
+       << 8 | (_Unwind_Exception_Class) 'U')
+      << 8 | (_Unwind_Exception_Class) 'C')
+     << 8 | (_Unwind_Exception_Class) 'F')
+    << 8 | (_Unwind_Exception_Class) 'O')
+   << 8 | (_Unwind_Exception_Class) 'R')
+  << 8 | (_Unwind_Exception_Class) '\0');
+
 static inline bool
 __is_gxx_exception_class(_Unwind_Exception_Class c)
 {
@@ -346,6 +350,12 @@
       || c == __gxx_dependent_exception_class;
 }
 
+static inline bool
+__is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
+{
+  return c ==  __gxx_forced_unwind_class;
+}
+
 // Only checks for primary or dependent, but not that it is a C++ exception at
 // all.
 static inline bool
@@ -357,7 +367,18 @@
 #define __GXX_INIT_PRIMARY_EXCEPTION_CLASS(c) c = __gxx_primary_exception_class
 #define __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(c) \
   c = __gxx_dependent_exception_class
+#define __GXX_INIT_FORCED_UNWIND_CLASS(c) c = __gxx_forced_unwind_class
+#endif // __ARM_EABI_UNWINDER__ && !__FreeBSD__
 
+#ifdef __ARM_EABI_UNWINDER__
+static inline void*
+__gxx_caught_object(_Unwind_Exception* eo)
+{
+    return (void*)eo->barrier_cache.bitpattern[0];
+}
+
+#else // !__ARM_EABI_UNWINDER__
+
 // GNU C++ personality routine, Version 0.
 extern "C" _Unwind_Reason_Code __gxx_personality_v0
      (int, _Unwind_Action, _Unwind_Exception_Class,

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][ARM] FreeBSD ARM support, EABI, v3
  2014-12-29 18:45 [PATCH][ARM] FreeBSD ARM support, EABI, v3 Andreas Tobler
@ 2015-01-08 16:27 ` Richard Earnshaw
  2015-01-08 20:51   ` Andreas Tobler
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Earnshaw @ 2015-01-08 16:27 UTC (permalink / raw)
  To: Andreas Tobler, GCC Patches, ramana.gcc

On 29/12/14 18:44, Andreas Tobler wrote:
> All,
> 
> here is the third attempt to support ARM with FreeBSD.
> 
> In the meantime we found another issue in the unwinder where I had to 
> adapt some stuff.
> 
> The unwind_phase2_forced function in libgcc calls a stop_fn function. 
> This stop_fn is in FreeBSD's libthr implementation and is called 
> thread_unwind_stop. This thread_unwind_stop is a generic function used 
> on all FreeBSD archs.
> 
> The issue is now that this thread_unwind_stop expects a double int for 
> the exception_class, like on every other arch. For ARM EABI this 
> exception_class is an array of char which is passed in one register as 
> pointer vs. two registers for a double int.
> 
> To solve this issue we defined the exception_class as double integer for 
> FreeBSD.
> 
> This adaptation reduced the failure count in libstdc++ by about 40 fails.
> 
> I build and test this port on a regular basis and I post the results to 
> the usual place.
> 
> I'd appreciate some feedback and if possible an ACK if ok for trunk.
> 
> Thank you,
> Andreas
> 
> Here the previous posts to this subject:
> 
> First version:
> https://gcc.gnu.org/ml/gcc-patches/2014-11/msg00029.html
> 
> Second version:
> https://gcc.gnu.org/ml/gcc-patches/2014-11/msg03427.html
> 
> 
> toplevel:
> 
> 	* configure.ac: Don't add ${libgcj} for arm*-*-freebsd*.
> 	* configure: Regenerate.
> gcc:
> 	* config.gcc (arm*-*-freebsd*): New configuration.
> 	* config/arm/freebsd.h: New file.
> 	* config.host: Add extra components for arm*-*-freebsd*.
> 	* config/arm/arm.h: Introduce MAX_SYNC_LIBFUNC_SIZE.
> 	* config/arm/arm.c (arm_init_libfuncs): Use MAX_SYNC_LIBFUNC_SIZE.
> 	* ginclude/unwind-arm-common.h (_Uwind_Control_Block): Define
> 	exception_class as double integer for FreeBSD ARM.
> 	(_Unwind_Exception): Define _Unwind_Exception_Class as double integer
> 	for FreeBSD ARM.
> 
> libgcc:
> 
> 	* config.host (arm*-*-freebsd*): Add new configuration for
> 	arm*-*-freebsd*.
> 	* config/arm/freebsd-atomic.c: New file.
> 	* config/arm/t-freebsd: Likewise.
> 	* config/arm/unwind-arm.h: Add __FreeBSD__ to the list of
> 	'PC-relative indirect' OS's.
> 
> libatomic:
> 
> 	* configure.tgt: Exclude arm*-*-freebsd* from try_ifunc.
> 
> libstdc++-v3:
> 
> 	* configure.host: Add arm*-*-freebsd* port_specific_symbol_files.
> 	* libsupc++/unwind-cxx.h (__is_gxx_exception_class,
> 	__is_dependent_exception): Exclude FreeBSD ARM from the
> 	__ARM_EABI_UNWINDER__ ifdef.
> 
> 

Umm, sorry, just seen this update to the previous patch.

The changes to the exception unwinding look a bit more involved.  Could
you separate that out into a separate patch, so that it's easier to see
what you're changing?

R.

> gcc5_fbsd_arm_20141230-1.diff
> 
> 
> Index: configure
> ===================================================================
> --- configure	(revision 219100)
> +++ configure	(working copy)
> @@ -3425,6 +3425,9 @@
>    alpha*-*-*vms*)
>      noconfigdirs="$noconfigdirs ${libgcj}"
>      ;;
> +  arm*-*-freebsd*)
> +    noconfigdirs="$noconfigdirs ${libgcj}"
> +    ;;
>    arm-wince-pe)
>      noconfigdirs="$noconfigdirs ${libgcj}"
>      ;;
> Index: configure.ac
> ===================================================================
> --- configure.ac	(revision 219100)
> +++ configure.ac	(working copy)
> @@ -779,6 +779,9 @@
>    alpha*-*-*vms*)
>      noconfigdirs="$noconfigdirs ${libgcj}"
>      ;;
> +  arm*-*-freebsd*)
> +    noconfigdirs="$noconfigdirs ${libgcj}"
> +    ;;
>    arm-wince-pe)
>      noconfigdirs="$noconfigdirs ${libgcj}"
>      ;;
> Index: gcc/config/arm/arm.c
> ===================================================================
> --- gcc/config/arm/arm.c	(revision 219100)
> +++ gcc/config/arm/arm.c	(working copy)
> @@ -2160,7 +2160,7 @@
>  {
>    /* For Linux, we have access to kernel support for atomic operations.  */
>    if (arm_abi == ARM_ABI_AAPCS_LINUX)
> -    init_sync_libfuncs (2 * UNITS_PER_WORD);
> +    init_sync_libfuncs (MAX_SYNC_LIBFUNC_SIZE);
>  
>    /* There are no special library functions unless we are using the
>       ARM BPABI.  */
> Index: gcc/config/arm/arm.h
> ===================================================================
> --- gcc/config/arm/arm.h	(revision 219100)
> +++ gcc/config/arm/arm.h	(working copy)
> @@ -766,6 +766,11 @@
>  #define PCC_BITFIELD_TYPE_MATTERS TARGET_AAPCS_BASED
>  #endif
>  
> +/* The maximum size of the sync library functions supported.  */
> +#ifndef MAX_SYNC_LIBFUNC_SIZE
> +#define MAX_SYNC_LIBFUNC_SIZE (2 * UNITS_PER_WORD);
> +#endif
> +
>  \f
>  /* Standard register usage.  */
>  
> Index: gcc/config/arm/freebsd.h
> ===================================================================
> --- gcc/config/arm/freebsd.h	(revision 0)
> +++ gcc/config/arm/freebsd.h	(working copy)
> @@ -0,0 +1,180 @@
> +/* Definitions of target machine for GNU compiler, FreeBSD/arm version.
> +   Copyright (C) 2002-2014 Free Software Foundation, Inc.
> +   Contributed by Wasabi Systems, Inc.
> +
> +   This file is part of GCC.
> +
> +   GCC is free software; you can redistribute it and/or modify it
> +   under the terms of the GNU General Public License as published
> +   by the Free Software Foundation; either version 3, or (at your
> +   option) any later version.
> +
> +   GCC is distributed in the hope that it will be useful, but WITHOUT
> +   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> +   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> +   License for more details.
> +
> +   Under Section 7 of GPL version 3, you are granted additional
> +   permissions described in the GCC Runtime Library Exception, version
> +   3.1, as published by the Free Software Foundation.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with GCC; see the file COPYING3.  If not see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#undef  SUBTARGET_CPP_SPEC
> +#define SUBTARGET_CPP_SPEC FBSD_CPP_SPEC
> +
> +#undef  SUBTARGET_EXTRA_SPECS
> +#define SUBTARGET_EXTRA_SPECS					\
> +  { "subtarget_extra_asm_spec",	SUBTARGET_EXTRA_ASM_SPEC },	\
> +  { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC }, 	\
> +  { "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }
> +
> +#undef SUBTARGET_EXTRA_ASM_SPEC
> +#define SUBTARGET_EXTRA_ASM_SPEC \
> +  "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=5} " TARGET_FIX_V4BX_SPEC " \
> +  %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
> +
> +#undef SUBTARGET_ASM_FLOAT_SPEC
> +#ifdef TARGET_FREEBSD_ARM_HARD_FLOAT
> +/* Default to full vfp if we build for arm*hf.  */
> +#define SUBTARGET_ASM_FLOAT_SPEC "%{!mfpu=*:-mfpu=vfp}"
> +#else
> +#define SUBTARGET_ASM_FLOAT_SPEC "%{!mfpu=*:-mfpu=softvfp}"
> +#endif
> +
> +#undef	LINK_SPEC
> +#define LINK_SPEC "							\
> +  %{p:%nconsider using `-pg' instead of `-p' with gprof (1) }		\
> +  %{v:-V}								\
> +  %{assert*} %{R*} %{rpath*} %{defsym*}					\
> +  %{shared:-Bshareable %{h*} %{soname*}}				\
> +  %{!shared:								\
> +    %{!static:								\
> +      %{rdynamic:-export-dynamic}					\
> +      %{!dynamic-linker:-dynamic-linker %(fbsd_dynamic_linker) }}	\
> +    %{static:-Bstatic}}							\
> +  %{!static:--hash-style=both --enable-new-dtags}			\
> +  %{symbolic:-Bsymbolic}						\
> +  -X %{mbig-endian:-EB} %{mlittle-endian:-EL}"
> +
> +/* TARGET_BIG_ENDIAN_DEFAULT is set in
> +   config.gcc for big endian configurations.  */
> +#if TARGET_BIG_ENDIAN_DEFAULT
> +#define TARGET_ENDIAN_DEFAULT    MASK_BIG_END
> +#define TARGET_ENDIAN_OPTION     "mbig-endian"
> +#define TARGET_LINKER_EMULATION  "armelfb_fbsd"
> +#else
> +#define TARGET_ENDIAN_DEFAULT    0
> +#define TARGET_ENDIAN_OPTION     "mlittle-endian"
> +#define TARGET_LINKER_EMULATION  "armelf_fbsd"
> +#endif
> +
> +#undef	SUBTARGET_EXTRA_LINK_SPEC
> +#define SUBTARGET_EXTRA_LINK_SPEC " -m " TARGET_LINKER_EMULATION " -p"
> +
> +#undef  TARGET_OS_CPP_BUILTINS
> +#define TARGET_OS_CPP_BUILTINS() 		\
> +  do						\
> +    {						\
> +	FBSD_TARGET_OS_CPP_BUILTINS ();		\
> +	TARGET_BPABI_CPP_BUILTINS ();		\
> +    }						\
> +  while (false)
> +
> +/* We default to a soft-float ABI so that binaries can run on all
> +   target hardware.  */
> +#undef TARGET_DEFAULT_FLOAT_ABI
> +#ifdef TARGET_FREEBSD_ARM_HARD_FLOAT
> +#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
> +#else
> +#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
> +#endif
> +
> +#undef ARM_DEFAULT_ABI
> +
> +/* AACPS_LINUX has access to kernel atomic ops while we don't.
> +   But AACPS defaults to short_enums.  */
> +#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
> +
> +#undef TARGET_DEFAULT
> +#define TARGET_DEFAULT (MASK_INTERWORK | TARGET_ENDIAN_DEFAULT)
> +
> +/* We do not have any MULTILIB_OPTIONS specified, so there are no
> +   MULTILIB_DEFAULTS.  */
> +#undef  MULTILIB_DEFAULTS
> +
> +/*  Use the AAPCS type for wchar_t, override the one from config/freebsd.h.  */
> +#undef  WCHAR_TYPE
> +#define WCHAR_TYPE  "unsigned int"
> +
> +#undef  WCHAR_TYPE_SIZE
> +#define WCHAR_TYPE_SIZE BITS_PER_WORD
> +
> +#if defined (TARGET_FREEBSD_ARMv6)
> +#undef  SUBTARGET_CPU_DEFAULT
> +#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm1176jzs
> +#else
> +#undef  SUBTARGET_CPU_DEFAULT
> +#define SUBTARGET_CPU_DEFAULT   TARGET_CPU_arm9
> +#endif
> +
> +#define SUBTARGET_OVERRIDE_OPTIONS		\
> +do {						\
> +    if (unaligned_access)			\
> +	unaligned_access = 0;			\
> +} while (0)
> +
> +#undef MAX_SYNC_LIBFUNC_SIZE
> +#define MAX_SYNC_LIBFUNC_SIZE 4 /* UNITS_PER_WORD not defined yet.  */
> +
> +/* FreeBSD does its profiling differently to the Acorn compiler.  We
> +   don't need a word following the mcount call; and to skip it
> +   requires either an assembly stub or use of fomit-frame-pointer when
> +   compiling the profiling functions.  Since we break Acorn CC
> +   compatibility below a little more won't hurt.  */
> +
> +#undef ARM_FUNCTION_PROFILER
> +#define ARM_FUNCTION_PROFILER(STREAM,LABELNO)		\
> +{							\
> +  asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n");		\
> +  asm_fprintf (STREAM, "\tbl\t__mcount%s\n",		\
> +	       (TARGET_ARM && NEED_PLT_RELOC)		\
> +	       ? "(PLT)" : "");				\
> +}
> +
> +/* Clear the instruction cache from `BEG' to `END'.  This makes a
> +   call to the ARM_SYNC_ICACHE architecture specific syscall.  */
> +#define CLEAR_INSN_CACHE(BEG, END)					\
> +do									\
> +  {									\
> +    extern int sysarch (int number, void *args);			\
> +    struct								\
> +      {									\
> +	unsigned int addr;						\
> +	int          len;						\
> +      } s;								\
> +    s.addr = (unsigned int) (BEG);					\
> +    s.len = (END) - (BEG);						\
> +    (void) sysarch (0, &s);						\
> +  }									\
> +while (0)
> +
> +/* This is how we tell the assembler that two symbols have the same value.  */
> +#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
> +  do					   \
> +    {					   \
> +     assemble_name (FILE, NAME1); 	   \
> +     fputs (" = ", FILE);		   \
> +     assemble_name (FILE, NAME2);	   \
> +     fputc ('\n', FILE);		   \
> +    }					   \
> +  while (0)
> +
> +/* Add  .note.GNU-stack.  */
> +#undef NEED_INDICATE_EXEC_STACK
> +#define NEED_INDICATE_EXEC_STACK 1
> +
> +#define ARM_TARGET2_DWARF_FORMAT (DW_EH_PE_pcrel | DW_EH_PE_indirect)
> +
> Index: gcc/config.gcc
> ===================================================================
> --- gcc/config.gcc	(revision 219100)
> +++ gcc/config.gcc	(working copy)
> @@ -259,7 +259,6 @@
>     arm*-wince-pe*			\
>   | arm*-*-ecos-elf			\
>   | arm*-*-elf				\
> - | arm*-*-freebsd*			\
>   | arm*-*-linux*			\
>   | arm*-*-uclinux*			\
>   | i[34567]86-go32-*			\
> @@ -1010,6 +1009,27 @@
>  	extra_options="${extra_options} arm/vxworks.opt"
>  	tmake_file="${tmake_file} arm/t-arm arm/t-vxworks"
>  	;;
> +arm*-*-freebsd*)                # ARM FreeBSD EABI
> +	tm_file="dbxelf.h elfos.h ${fbsd_tm_file} arm/elf.h"
> +	case $target in
> +	arm*b-*-freebsd*)
> +	    tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
> +	    ;;
> +	esac
> +	tmake_file="${tmake_file} arm/t-arm arm/t-bpabi"
> +	tm_file="${tm_file} arm/bpabi.h arm/freebsd.h arm/aout.h arm/arm.h"
> +	case $target in
> +	armv6*-*-freebsd*)
> +	    tm_defines="${tm_defines} TARGET_FREEBSD_ARMv6=1"
> +	    ;;
> +	esac
> +	case $target in
> +	arm*hf-*-freebsd*)
> +	    tm_defines="${tm_defines} TARGET_FREEBSD_ARM_HARD_FLOAT=1"
> +	    ;;
> +	esac
> +	with_tls=${with_tls:-gnu}
> +	;;
>  arm*-*-netbsdelf*)
>  	tm_file="dbxelf.h elfos.h netbsd.h netbsd-elf.h arm/elf.h arm/aout.h ${tm_file} arm/netbsd-elf.h"
>  	extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
> Index: gcc/config.host
> ===================================================================
> --- gcc/config.host	(revision 219100)
> +++ gcc/config.host	(working copy)
> @@ -99,7 +99,7 @@
>  esac
>  
>  case ${host} in
> -  arm*-*-linux*)
> +  arm*-*-freebsd* | arm*-*-linux*)
>      case ${target} in
>        arm*-*-*)
>  	host_extra_gcc_objs="driver-arm.o"
> Index: gcc/ginclude/unwind-arm-common.h
> ===================================================================
> --- gcc/ginclude/unwind-arm-common.h	(revision 219100)
> +++ gcc/ginclude/unwind-arm-common.h	(working copy)
> @@ -82,7 +82,11 @@
>  
>    struct _Unwind_Control_Block
>      {
> +#ifdef __FreeBSD__
> +      unsigned exception_class __attribute__((__mode__(__DI__)));
> +#else
>        char exception_class[8];
> +#endif
>        void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
>        /* Unwinder cache, private fields for the unwinder's use */
>        struct
> @@ -181,7 +185,11 @@
>  
>    /* Support functions for the PR.  */
>  #define _Unwind_Exception _Unwind_Control_Block
> +#ifdef __FreeBSD__
> +  typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
> +#else
>    typedef char _Unwind_Exception_Class[8];
> +#endif
>  
>    void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
>    _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
> Index: libatomic/configure.tgt
> ===================================================================
> --- libatomic/configure.tgt	(revision 219100)
> +++ libatomic/configure.tgt	(working copy)
> @@ -37,10 +37,15 @@
>  
>    arm*)
>  	ARCH=arm
> -	# ??? Detect when -march=armv7 is already enabled.
> -	try_ifunc=yes
> -	;;
> -
> +	case "${target}" in
> +            arm*-*-freebsd*)
> +                ;;
> +            *)
> +                # ??? Detect when -march=armv7 is already enabled.
> +                try_ifunc=yes
> +                ;;
> +        esac
> +        ;;
>    sparc)
>  	case " ${CC} ${CFLAGS} " in
>  	  *" -m64 "*)
> Index: libgcc/config/arm/freebsd-atomic.c
> ===================================================================
> --- libgcc/config/arm/freebsd-atomic.c	(revision 0)
> +++ libgcc/config/arm/freebsd-atomic.c	(working copy)
> @@ -0,0 +1,224 @@
> +/* FreeBSD specific atomic operations for ARM EABI.
> +   Copyright (C) 2014 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#include <sys/types.h>
> +
> +#define HIDDEN __attribute__ ((visibility ("hidden")))
> +
> +#define ARM_VECTORS_HIGH 0xffff0000U
> +#define ARM_TP_ADDRESS   (ARM_VECTORS_HIGH + 0x1000)
> +#define ARM_RAS_START    (ARM_TP_ADDRESS + 4)
> +
> +void HIDDEN
> +__sync_synchronize (void)
> +{
> +#if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__)       \
> +    || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6T2__)  \
> +    || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__)  \
> +    || defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
> +#if defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
> +    __asm __volatile ("dmb" : : : "memory");
> +#else
> +    __asm __volatile ("mcr p15, 0, r0, c7, c10, 5" : : : "memory");
> +#endif
> +#else
> +    __asm __volatile ("nop" : : : "memory");
> +#endif
> +}
> +
> +#if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__)        \
> +    || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6T2__)   \
> +    || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6ZK__)   \
> +    || defined (__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
> +
> +/* These systems should be supported by the compiler.  */
> +
> +#else /* __ARM_ARCH_5__  */
> +
> +#define	SYNC_LOCK_TEST_AND_SET_N(N, TYPE, LDR, STR)			\
> +TYPE HIDDEN    								\
> +__sync_lock_test_and_set_##N (TYPE *mem, TYPE val)			\
> +{									\
> +        unsigned int old, temp, ras_start;                              \
> +                                                                        \
> +        ras_start = ARM_RAS_START;					\
> +        __asm volatile (						\
> +                /* Set up Restartable Atomic Sequence.  */		\
> +                "1:"							\
> +                "\tadr   %2, 1b\n"					\
> +                "\tstr   %2, [%5]\n"					\
> +                "\tadr   %2, 2f\n"					\
> +                "\tstr   %2, [%5, #4]\n"				\
> +                                                                        \
> +                "\t"LDR" %0, %4\n"	/* Load old value.  */		\
> +                "\t"STR" %3, %1\n"	/* Store new value.  */		\
> +                                                                        \
> +                /* Tear down Restartable Atomic Sequence.  */		\
> +                "2:"							\
> +                "\tmov   %2, #0x00000000\n"				\
> +                "\tstr   %2, [%5]\n"					\
> +                "\tmov   %2, #0xffffffff\n"				\
> +                "\tstr   %2, [%5, #4]\n"				\
> +                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
> +                : "r" (val), "m" (*mem), "r" (ras_start));		\
> +        return (old);							\
> +}
> +
> +#define SYNC_LOCK_RELEASE_N(N, TYPE)					\
> +void HIDDEN								\
> +__sync_lock_release_##N (TYPE *ptr)     				\
> +{					       				\
> +    /* All writes before this point must be seen before we release	\
> +       the lock itself.  */						\
> +    __sync_synchronize ();     						\
> +    *ptr = 0;								\
> +}
> +
> +#define	SYNC_VAL_CAS_N(N, TYPE, LDR, STREQ)             		\
> +TYPE HIDDEN    								\
> +__sync_val_compare_and_swap_##N (TYPE *mem, TYPE expected,		\
> +    TYPE desired)							\
> +{									\
> +        unsigned int old, temp, ras_start;                              \
> +                                                                        \
> +        ras_start = ARM_RAS_START;					\
> +        __asm volatile (						\
> +                /* Set up Restartable Atomic Sequence.  */		\
> +                "1:"							\
> +                "\tadr   %2, 1b\n"					\
> +                "\tstr   %2, [%6]\n"					\
> +                "\tadr   %2, 2f\n"					\
> +                "\tstr   %2, [%6, #4]\n"				\
> +                                                                        \
> +                "\t"LDR" %0, %5\n"     /* Load old value.  */		\
> +                "\tcmp   %0, %3\n"     /* Compare to expected value.  */\
> +                "\t"STREQ" %4, %1\n"   /* Store new value.  */		\
> +                                                                        \
> +                /* Tear down Restartable Atomic Sequence.  */		\
> +                "2:"							\
> +                "\tmov   %2, #0x00000000\n"				\
> +                "\tstr   %2, [%6]\n"					\
> +                "\tmov   %2, #0xffffffff\n"				\
> +                "\tstr   %2, [%6, #4]\n"				\
> +                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
> +                : "r" (expected), "r" (desired), "m" (*mem),		\
> +                  "r" (ras_start));					\
> +        return (old);							\
> +}
> +
> +typedef unsigned char bool;
> +
> +#define SYNC_BOOL_CAS_N(N, TYPE)                                        \
> +bool HIDDEN								\
> +__sync_bool_compare_and_swap_##N (TYPE *ptr, TYPE oldval,		\
> +                                  TYPE newval)                          \
> +{									\
> +    TYPE actual_oldval							\
> +      = __sync_val_compare_and_swap_##N (ptr, oldval, newval);          \
> +    return (oldval == actual_oldval);					\
> +}
> +
> +#define	SYNC_FETCH_AND_OP_N(N, TYPE, LDR, STR, NAME, OP)		\
> +TYPE HIDDEN								\
> +__sync_fetch_and_##NAME##_##N (TYPE *mem, TYPE val)	       		\
> +{									\
> +        unsigned int old, temp, ras_start;                              \
> +                                                                        \
> +        ras_start = ARM_RAS_START;					\
> +        __asm volatile (						\
> +                /* Set up Restartable Atomic Sequence.  */		\
> +                "1:"							\
> +                "\tadr   %2, 1b\n"					\
> +                "\tstr   %2, [%5]\n"					\
> +                "\tadr   %2, 2f\n"					\
> +                "\tstr   %2, [%5, #4]\n"				\
> +                                                                        \
> +                "\t"LDR" %0, %4\n"	/* Load old value.  */		\
> +                "\t"OP"  %2, %0, %3\n"	/* Calculate new value.  */	\
> +                "\t"STR" %2, %1\n"	/* Store new value.  */		\
> +                                                                        \
> +                /* Tear down Restartable Atomic Sequence.  */		\
> +                "2:"							\
> +                "\tmov   %2, #0x00000000\n"				\
> +                "\tstr   %2, [%5]\n"					\
> +                "\tmov   %2, #0xffffffff\n"				\
> +                "\tstr   %2, [%5, #4]\n"				\
> +                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
> +                : "r" (val), "m" (*mem), "r" (ras_start));		\
> +        return (old);							\
> +}
> +
> +#define	SYNC_OP_AND_FETCH_N(N, TYPE, LDR, STR, NAME, OP)		\
> +TYPE HIDDEN   								\
> +__sync_##NAME##_and_fetch_##N (TYPE *mem, TYPE val)	       		\
> +{									\
> +        unsigned int old, temp, ras_start;                              \
> +                                                                        \
> +        ras_start = ARM_RAS_START;					\
> +        __asm volatile (						\
> +                /* Set up Restartable Atomic Sequence.  */		\
> +                "1:"							\
> +                "\tadr   %2, 1b\n"					\
> +                "\tstr   %2, [%5]\n"					\
> +                "\tadr   %2, 2f\n"					\
> +                "\tstr   %2, [%5, #4]\n"				\
> +                                                                        \
> +                "\t"LDR" %0, %4\n"	/* Load old value.  */		\
> +                "\t"OP"  %2, %0, %3\n"	/* Calculate new value.  */	\
> +                "\t"STR" %2, %1\n"	/* Store new value.  */		\
> +                                                                        \
> +                /* Tear down Restartable Atomic Sequence.  */		\
> +                "2:"							\
> +                "\tmov   %2, #0x00000000\n"				\
> +                "\tstr   %2, [%5]\n"					\
> +                "\tmov   %2, #0xffffffff\n"				\
> +                "\tstr   %2, [%5, #4]\n"				\
> +                : "=&r" (old), "=m" (*mem), "=&r" (temp)		\
> +                : "r" (val), "m" (*mem), "r" (ras_start));		\
> +        return (old);							\
> +}
> +
> +#define	EMIT_ALL_OPS_N(N, TYPE, LDR, STR, STREQ)			\
> +SYNC_LOCK_TEST_AND_SET_N (N, TYPE, LDR, STR)				\
> +SYNC_LOCK_RELEASE_N (N, TYPE)                                           \
> +SYNC_VAL_CAS_N (N, TYPE, LDR, STREQ)	                		\
> +SYNC_BOOL_CAS_N (N, TYPE)                                               \
> +SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, add, "add")		        \
> +SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, and, "and")		        \
> +SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, or, "orr")		        \
> +SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, sub, "sub")		        \
> +SYNC_FETCH_AND_OP_N (N, TYPE, LDR, STR, xor, "eor")                     \
> +SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, add, "add")		        \
> +SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, and, "and")		        \
> +SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, or, "orr")		        \
> +SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, sub, "sub")		        \
> +SYNC_OP_AND_FETCH_N (N, TYPE, LDR, STR, xor, "eor")
> +
> +
> +
> +EMIT_ALL_OPS_N (1, unsigned char, "ldrb", "strb", "streqb")
> +EMIT_ALL_OPS_N (2, unsigned short, "ldrh", "strh", "streqh")
> +EMIT_ALL_OPS_N (4, unsigned int, "ldr", "str", "streq")
> +
> +#endif
> Index: libgcc/config/arm/t-freebsd
> ===================================================================
> --- libgcc/config/arm/t-freebsd	(revision 0)
> +++ libgcc/config/arm/t-freebsd	(working copy)
> @@ -0,0 +1,9 @@
> +# Just for these, we omit the frame pointer since it makes such a big
> +# difference.  It is then pointless adding debugging.
> +HOST_LIBGCC2_CFLAGS += -fomit-frame-pointer
> +
> +LIB2ADD_ST += $(srcdir)/config/arm/freebsd-atomic.c
> +
> +# Use a version of div0 which raises SIGFPE.
> +LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx
> +
> Index: libgcc/config/arm/unwind-arm.h
> ===================================================================
> --- libgcc/config/arm/unwind-arm.h	(revision 219100)
> +++ libgcc/config/arm/unwind-arm.h	(working copy)
> @@ -48,7 +48,8 @@
>        if (!tmp)
>  	return 0;
>  
> -#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__)
> +#if (defined(linux) && !defined(__uClinux__)) || defined(__NetBSD__) \
> +    || defined(__FreeBSD__)
>        /* Pc-relative indirect.  */
>  #define _GLIBCXX_OVERRIDE_TTYPE_ENCODING (DW_EH_PE_pcrel | DW_EH_PE_indirect)
>        tmp += ptr;
> Index: libgcc/config.host
> ===================================================================
> --- libgcc/config.host	(revision 219100)
> +++ libgcc/config.host	(working copy)
> @@ -366,6 +366,13 @@
>  	tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
>  	extra_parts="$extra_parts crti.o crtn.o"
>  	;;
> +arm*-*-freebsd*)                # ARM FreeBSD EABI
> +	tmake_file="${tmake_file} arm/t-arm t-fixedpoint-gnu-prefix arm/t-elf"
> +	tmake_file="${tmake_file} arm/t-bpabi arm/t-freebsd t-slibgcc-libgcc"
> +	tm_file="${tm_file} arm/bpabi-lib.h"
> +	unwind_header=config/arm/unwind-arm.h
> +	tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
> +	;;
>  arm*-*-netbsdelf*)
>  	tmake_file="$tmake_file arm/t-arm arm/t-netbsd t-slibgcc-gld-nover"
>  	;;
> Index: libstdc++-v3/configure.host
> ===================================================================
> --- libstdc++-v3/configure.host	(revision 219100)
> +++ libstdc++-v3/configure.host	(working copy)
> @@ -366,6 +366,9 @@
>  	;;
>      esac
>      ;;
> +  arm*-*-freebsd*)
> +     port_specific_symbol_files="\$(srcdir)/../config/os/gnu-linux/arm-eabi-extra.ver"
> +     ;;
>    powerpc*-*-darwin*)
>      port_specific_symbol_files="\$(srcdir)/../config/os/bsd/darwin/ppc-extra.ver"
>      ;;
> Index: libstdc++-v3/libsupc++/unwind-cxx.h
> ===================================================================
> --- libstdc++-v3/libsupc++/unwind-cxx.h	(revision 219100)
> +++ libstdc++-v3/libsupc++/unwind-cxx.h	(working copy)
> @@ -235,7 +235,7 @@
>    return reinterpret_cast<__cxa_dependent_exception *>(exc + 1) - 1;
>  }
>  
> -#ifdef __ARM_EABI_UNWINDER__
> +#if defined (__ARM_EABI_UNWINDER__) && !defined (__FreeBSD__)
>  static inline bool
>  __is_gxx_exception_class(_Unwind_Exception_Class c)
>  {
> @@ -309,13 +309,7 @@
>    c[6] = 'R';
>    c[7] = '\0';
>  }
> -
> -static inline void*
> -__gxx_caught_object(_Unwind_Exception* eo)
> -{
> -  return (void*)eo->barrier_cache.bitpattern[0];
> -}
> -#else // !__ARM_EABI_UNWINDER__
> +#else // !__ARM_EABI_UNWINDER__ || __FreeBSD__
>  // This is the primary exception class we report -- "GNUCC++\0".
>  const _Unwind_Exception_Class __gxx_primary_exception_class
>  = ((((((((_Unwind_Exception_Class) 'G' 
> @@ -339,6 +333,16 @@
>      << 8 | (_Unwind_Exception_Class) '+')
>     << 8 | (_Unwind_Exception_Class) '\x01');
>  
> +const _Unwind_Exception_Class __gxx_forced_unwind_class
> += ((((((((_Unwind_Exception_Class) 'G'
> +        << 8 | (_Unwind_Exception_Class) 'N')
> +       << 8 | (_Unwind_Exception_Class) 'U')
> +      << 8 | (_Unwind_Exception_Class) 'C')
> +     << 8 | (_Unwind_Exception_Class) 'F')
> +    << 8 | (_Unwind_Exception_Class) 'O')
> +   << 8 | (_Unwind_Exception_Class) 'R')
> +  << 8 | (_Unwind_Exception_Class) '\0');
> +
>  static inline bool
>  __is_gxx_exception_class(_Unwind_Exception_Class c)
>  {
> @@ -346,6 +350,12 @@
>        || c == __gxx_dependent_exception_class;
>  }
>  
> +static inline bool
> +__is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
> +{
> +  return c ==  __gxx_forced_unwind_class;
> +}
> +
>  // Only checks for primary or dependent, but not that it is a C++ exception at
>  // all.
>  static inline bool
> @@ -357,7 +367,18 @@
>  #define __GXX_INIT_PRIMARY_EXCEPTION_CLASS(c) c = __gxx_primary_exception_class
>  #define __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(c) \
>    c = __gxx_dependent_exception_class
> +#define __GXX_INIT_FORCED_UNWIND_CLASS(c) c = __gxx_forced_unwind_class
> +#endif // __ARM_EABI_UNWINDER__ && !__FreeBSD__
>  
> +#ifdef __ARM_EABI_UNWINDER__
> +static inline void*
> +__gxx_caught_object(_Unwind_Exception* eo)
> +{
> +    return (void*)eo->barrier_cache.bitpattern[0];
> +}
> +
> +#else // !__ARM_EABI_UNWINDER__
> +
>  // GNU C++ personality routine, Version 0.
>  extern "C" _Unwind_Reason_Code __gxx_personality_v0
>       (int, _Unwind_Action, _Unwind_Exception_Class,
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][ARM] FreeBSD ARM support, EABI, v3
  2015-01-08 16:27 ` Richard Earnshaw
@ 2015-01-08 20:51   ` Andreas Tobler
  2015-01-13 10:44     ` Ramana Radhakrishnan
  0 siblings, 1 reply; 7+ messages in thread
From: Andreas Tobler @ 2015-01-08 20:51 UTC (permalink / raw)
  To: Richard Earnshaw, GCC Patches, ramana.gcc

[-- Attachment #1: Type: text/plain, Size: 1756 bytes --]

On 08.01.15 17:27, Richard Earnshaw wrote:
> On 29/12/14 18:44, Andreas Tobler wrote:
>> All,
>>
>> here is the third attempt to support ARM with FreeBSD.
>>
>> In the meantime we found another issue in the unwinder where I had to
>> adapt some stuff.
>>
>> The unwind_phase2_forced function in libgcc calls a stop_fn function.
>> This stop_fn is in FreeBSD's libthr implementation and is called
>> thread_unwind_stop. This thread_unwind_stop is a generic function used
>> on all FreeBSD archs.
>>
>> The issue is now that this thread_unwind_stop expects a double int for
>> the exception_class, like on every other arch. For ARM EABI this
>> exception_class is an array of char which is passed in one register as
>> pointer vs. two registers for a double int.
>>
>> To solve this issue we defined the exception_class as double integer for
>> FreeBSD.
>>
>> This adaptation reduced the failure count in libstdc++ by about 40 fails.
>>
>> I build and test this port on a regular basis and I post the results to
>> the usual place.

...

> Umm, sorry, just seen this update to the previous patch.
>
> The changes to the exception unwinding look a bit more involved.  Could
> you separate that out into a separate patch, so that it's easier to see
> what you're changing?

Ok, here the mentioned part as separate diff. The comments are above. 
The CL below :)

Thank you very much!

Andreas

gcc:

	* ginclude/unwind-arm-common.h (_Uwind_Control_Block): Define
	exception_class as double integer for FreeBSD ARM.
	(_Unwind_Exception): Define _Unwind_Exception_Class as double integer
	for FreeBSD ARM.

libstc++-v3:

	* libsupc++/unwind-cxx.h (__is_gxx_exception_class,
	__is_dependent_exception): Exclude FreeBSD ARM from the
	__ARM_EABI_UNWINDER__ ifdef.



[-- Attachment #2: gcc5_arm_unwind_20150108.diff --]
[-- Type: text/plain, Size: 3443 bytes --]

Index: gcc/ginclude/unwind-arm-common.h
===================================================================
--- gcc/ginclude/unwind-arm-common.h	(revision 219357)
+++ gcc/ginclude/unwind-arm-common.h	(working copy)
@@ -82,7 +82,11 @@
 
   struct _Unwind_Control_Block
     {
+#ifdef __FreeBSD__
+      unsigned exception_class __attribute__((__mode__(__DI__)));
+#else
       char exception_class[8];
+#endif
       void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
       /* Unwinder cache, private fields for the unwinder's use */
       struct
@@ -181,7 +185,11 @@
 
   /* Support functions for the PR.  */
 #define _Unwind_Exception _Unwind_Control_Block
+#ifdef __FreeBSD__
+  typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
+#else
   typedef char _Unwind_Exception_Class[8];
+#endif
 
   void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
   _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
Index: libstdc++-v3/libsupc++/unwind-cxx.h
===================================================================
--- libstdc++-v3/libsupc++/unwind-cxx.h	(revision 219357)
+++ libstdc++-v3/libsupc++/unwind-cxx.h	(working copy)
@@ -235,7 +235,7 @@
   return reinterpret_cast<__cxa_dependent_exception *>(exc + 1) - 1;
 }
 
-#ifdef __ARM_EABI_UNWINDER__
+#if defined (__ARM_EABI_UNWINDER__) && !defined (__FreeBSD__)
 static inline bool
 __is_gxx_exception_class(_Unwind_Exception_Class c)
 {
@@ -309,13 +309,7 @@
   c[6] = 'R';
   c[7] = '\0';
 }
-
-static inline void*
-__gxx_caught_object(_Unwind_Exception* eo)
-{
-  return (void*)eo->barrier_cache.bitpattern[0];
-}
-#else // !__ARM_EABI_UNWINDER__
+#else // !__ARM_EABI_UNWINDER__ || __FreeBSD__
 // This is the primary exception class we report -- "GNUCC++\0".
 const _Unwind_Exception_Class __gxx_primary_exception_class
 = ((((((((_Unwind_Exception_Class) 'G' 
@@ -339,6 +333,16 @@
     << 8 | (_Unwind_Exception_Class) '+')
    << 8 | (_Unwind_Exception_Class) '\x01');
 
+const _Unwind_Exception_Class __gxx_forced_unwind_class
+= ((((((((_Unwind_Exception_Class) 'G'
+        << 8 | (_Unwind_Exception_Class) 'N')
+       << 8 | (_Unwind_Exception_Class) 'U')
+      << 8 | (_Unwind_Exception_Class) 'C')
+     << 8 | (_Unwind_Exception_Class) 'F')
+    << 8 | (_Unwind_Exception_Class) 'O')
+   << 8 | (_Unwind_Exception_Class) 'R')
+  << 8 | (_Unwind_Exception_Class) '\0');
+
 static inline bool
 __is_gxx_exception_class(_Unwind_Exception_Class c)
 {
@@ -346,6 +350,12 @@
       || c == __gxx_dependent_exception_class;
 }
 
+static inline bool
+__is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
+{
+  return c ==  __gxx_forced_unwind_class;
+}
+
 // Only checks for primary or dependent, but not that it is a C++ exception at
 // all.
 static inline bool
@@ -357,7 +367,18 @@
 #define __GXX_INIT_PRIMARY_EXCEPTION_CLASS(c) c = __gxx_primary_exception_class
 #define __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(c) \
   c = __gxx_dependent_exception_class
+#define __GXX_INIT_FORCED_UNWIND_CLASS(c) c = __gxx_forced_unwind_class
+#endif // __ARM_EABI_UNWINDER__ && !__FreeBSD__
 
+#ifdef __ARM_EABI_UNWINDER__
+static inline void*
+__gxx_caught_object(_Unwind_Exception* eo)
+{
+    return (void*)eo->barrier_cache.bitpattern[0];
+}
+
+#else // !__ARM_EABI_UNWINDER__
+
 // GNU C++ personality routine, Version 0.
 extern "C" _Unwind_Reason_Code __gxx_personality_v0
      (int, _Unwind_Action, _Unwind_Exception_Class,

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][ARM] FreeBSD ARM support, EABI, v3
  2015-01-08 20:51   ` Andreas Tobler
@ 2015-01-13 10:44     ` Ramana Radhakrishnan
  2015-01-13 21:11       ` Andreas Tobler
  0 siblings, 1 reply; 7+ messages in thread
From: Ramana Radhakrishnan @ 2015-01-13 10:44 UTC (permalink / raw)
  To: Andreas Tobler; +Cc: Richard Earnshaw, GCC Patches

On Thu, Jan 8, 2015 at 8:51 PM, Andreas Tobler <andreast-list@fgznet.ch> wrote:
> On 08.01.15 17:27, Richard Earnshaw wrote:
>>
>> On 29/12/14 18:44, Andreas Tobler wrote:
>>>
>>> All,
>>>
>>> here is the third attempt to support ARM with FreeBSD.
>>>
>>> In the meantime we found another issue in the unwinder where I had to
>>> adapt some stuff.
>>>
>>> The unwind_phase2_forced function in libgcc calls a stop_fn function.
>>> This stop_fn is in FreeBSD's libthr implementation and is called
>>> thread_unwind_stop. This thread_unwind_stop is a generic function used
>>> on all FreeBSD archs.
>>>
>>> The issue is now that this thread_unwind_stop expects a double int for
>>> the exception_class, like on every other arch. For ARM EABI this
>>> exception_class is an array of char which is passed in one register as
>>> pointer vs. two registers for a double int.
>>>
>>> To solve this issue we defined the exception_class as double integer for
>>> FreeBSD.

My apologies for the slow response, some other work and then holidays
intervened.

From my understanding of the ABI document the implementation is
currently as mandated by the ABI. Also this isn't a part of the ABI
that's available for the platform (here FreeBSD to manipulate and
change as per it's wishes). ARM EHABI is special for software, making
FreeBSD more "special" for ARM appears to be counter intuitive from my
point of view. A number of exception unwinding libraries. for e.g.
libobjc , libstdc++ all use this implementation of exception_class.
Therefore this creates a divergence for the FreeBSD port which is
different from everything else. I expect that a number of language run
time support libraries that supported the ARM EHABI would be using
such an implementation, therefore you need to fix every single
implementation of this in every unwinder that supports the ARM EHABI
which I expect to have been ported to in a number of libraries
already. (I already see this in libobjc and libstdc++ in the GCC tree)

I would rather fix the thread_unwind_stop implementation in libthr for
ARM EHABI rather than make this change.


>>>
>>> This adaptation reduced the failure count in libstdc++ by about 40 fails.
>>>
>>> I build and test this port on a regular basis and I post the results to
>>> the usual place.

Thanks for doing this. I'm really glad that FreeBSD is finally moving to EABI.


regards
Ramana

>
>
> ...
>
>> Umm, sorry, just seen this update to the previous patch.
>>
>> The changes to the exception unwinding look a bit more involved.  Could
>> you separate that out into a separate patch, so that it's easier to see
>> what you're changing?
>
>
> Ok, here the mentioned part as separate diff. The comments are above. The CL
> below :)
>
> Thank you very much!
>
> Andreas
>
> gcc:
>
>         * ginclude/unwind-arm-common.h (_Uwind_Control_Block): Define
>         exception_class as double integer for FreeBSD ARM.
>         (_Unwind_Exception): Define _Unwind_Exception_Class as double
> integer
>         for FreeBSD ARM.
>
> libstc++-v3:
>
>
>         * libsupc++/unwind-cxx.h (__is_gxx_exception_class,
>         __is_dependent_exception): Exclude FreeBSD ARM from the
>         __ARM_EABI_UNWINDER__ ifdef.
>
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][ARM] FreeBSD ARM support, EABI, v3
  2015-01-13 10:44     ` Ramana Radhakrishnan
@ 2015-01-13 21:11       ` Andreas Tobler
  2015-01-14  9:54         ` Richard Earnshaw
  0 siblings, 1 reply; 7+ messages in thread
From: Andreas Tobler @ 2015-01-13 21:11 UTC (permalink / raw)
  To: ramrad01; +Cc: Richard Earnshaw, GCC Patches

On 13.01.15 11:25, Ramana Radhakrishnan wrote:
> On Thu, Jan 8, 2015 at 8:51 PM, Andreas Tobler <andreast-list@fgznet.ch> wrote:
>> On 08.01.15 17:27, Richard Earnshaw wrote:
>>>
>>> On 29/12/14 18:44, Andreas Tobler wrote:
>>>>
>>>> All,
>>>>
>>>> here is the third attempt to support ARM with FreeBSD.
>>>>
>>>> In the meantime we found another issue in the unwinder where I had to
>>>> adapt some stuff.
>>>>
>>>> The unwind_phase2_forced function in libgcc calls a stop_fn function.
>>>> This stop_fn is in FreeBSD's libthr implementation and is called
>>>> thread_unwind_stop. This thread_unwind_stop is a generic function used
>>>> on all FreeBSD archs.
>>>>
>>>> The issue is now that this thread_unwind_stop expects a double int for
>>>> the exception_class, like on every other arch. For ARM EABI this
>>>> exception_class is an array of char which is passed in one register as
>>>> pointer vs. two registers for a double int.
>>>>
>>>> To solve this issue we defined the exception_class as double integer for
>>>> FreeBSD.
>
> My apologies for the slow response, some other work and then holidays
> intervened.

Np, the only issue which made me hurry was the stage 4 entering this week.

>From my understanding of the ABI document the implementation is
> currently as mandated by the ABI. Also this isn't a part of the ABI
> that's available for the platform (here FreeBSD to manipulate and
> change as per it's wishes). ARM EHABI is special for software, making
> FreeBSD more "special" for ARM appears to be counter intuitive from my
> point of view. A number of exception unwinding libraries. for e.g.
> libobjc , libstdc++ all use this implementation of exception_class.
> Therefore this creates a divergence for the FreeBSD port which is
> different from everything else. I expect that a number of language run
> time support libraries that supported the ARM EHABI would be using
> such an implementation, therefore you need to fix every single
> implementation of this in every unwinder that supports the ARM EHABI
> which I expect to have been ported to in a number of libraries
> already. (I already see this in libobjc and libstdc++ in the GCC tree)

Grr ;) I didn't want to hear this answer, but I expected it somehow.
My proposal was the least effort for me.
The other way round is going to be very hard. Maybe impossible.

It is not only FreeBSD which is affected but also llvm and friends. They 
use for exception_class uint64_t.

I have to take a picture how the effort is and if it would be possible 
to do such a change in FreeBSD and more important in llvm etc.

> I would rather fix the thread_unwind_stop implementation in libthr for
> ARM EHABI rather than make this change.

It wouldn't be a 'fix' but more a wrapper I think.

>>>> This adaptation reduced the failure count in libstdc++ by about 40 fails.
>>>>
>>>> I build and test this port on a regular basis and I post the results to
>>>> the usual place.
>
> Thanks for doing this. I'm really glad that FreeBSD is finally moving to EABI.

Thanks for the review and the feedback.

Gruss,
Andreas

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][ARM] FreeBSD ARM support, EABI, v3
  2015-01-13 21:11       ` Andreas Tobler
@ 2015-01-14  9:54         ` Richard Earnshaw
  2015-01-15 23:01           ` Andreas Tobler
  0 siblings, 1 reply; 7+ messages in thread
From: Richard Earnshaw @ 2015-01-14  9:54 UTC (permalink / raw)
  To: Andreas Tobler, Ramana Radhakrishnan; +Cc: GCC Patches

On 13/01/15 21:08, Andreas Tobler wrote:
> On 13.01.15 11:25, Ramana Radhakrishnan wrote:
>> On Thu, Jan 8, 2015 at 8:51 PM, Andreas Tobler <andreast-list@fgznet.ch> wrote:
>>> On 08.01.15 17:27, Richard Earnshaw wrote:
>>>>
>>>> On 29/12/14 18:44, Andreas Tobler wrote:
>>>>>
>>>>> All,
>>>>>
>>>>> here is the third attempt to support ARM with FreeBSD.
>>>>>
>>>>> In the meantime we found another issue in the unwinder where I had to
>>>>> adapt some stuff.
>>>>>
>>>>> The unwind_phase2_forced function in libgcc calls a stop_fn function.
>>>>> This stop_fn is in FreeBSD's libthr implementation and is called
>>>>> thread_unwind_stop. This thread_unwind_stop is a generic function used
>>>>> on all FreeBSD archs.
>>>>>
>>>>> The issue is now that this thread_unwind_stop expects a double int for
>>>>> the exception_class, like on every other arch. For ARM EABI this
>>>>> exception_class is an array of char which is passed in one register as
>>>>> pointer vs. two registers for a double int.
>>>>>
>>>>> To solve this issue we defined the exception_class as double integer for
>>>>> FreeBSD.
>>
>> My apologies for the slow response, some other work and then holidays
>> intervened.
> 
> Np, the only issue which made me hurry was the stage 4 entering this week.
> 
>> >From my understanding of the ABI document the implementation is
>> currently as mandated by the ABI. Also this isn't a part of the ABI
>> that's available for the platform (here FreeBSD to manipulate and
>> change as per it's wishes). ARM EHABI is special for software, making
>> FreeBSD more "special" for ARM appears to be counter intuitive from my
>> point of view. A number of exception unwinding libraries. for e.g.
>> libobjc , libstdc++ all use this implementation of exception_class.
>> Therefore this creates a divergence for the FreeBSD port which is
>> different from everything else. I expect that a number of language run
>> time support libraries that supported the ARM EHABI would be using
>> such an implementation, therefore you need to fix every single
>> implementation of this in every unwinder that supports the ARM EHABI
>> which I expect to have been ported to in a number of libraries
>> already. (I already see this in libobjc and libstdc++ in the GCC tree)
> 
> Grr ;) I didn't want to hear this answer, but I expected it somehow.
> My proposal was the least effort for me.
> The other way round is going to be very hard. Maybe impossible.
> 
> It is not only FreeBSD which is affected but also llvm and friends. They 
> use for exception_class uint64_t.
> 
> I have to take a picture how the effort is and if it would be possible 
> to do such a change in FreeBSD and more important in llvm etc.
> 
>> I would rather fix the thread_unwind_stop implementation in libthr for
>> ARM EHABI rather than make this change.
> 
> It wouldn't be a 'fix' but more a wrapper I think.
> 
>>>>> This adaptation reduced the failure count in libstdc++ by about 40 fails.
>>>>>
>>>>> I build and test this port on a regular basis and I post the results to
>>>>> the usual place.
>>
>> Thanks for doing this. I'm really glad that FreeBSD is finally moving to EABI.
> 

I agree with Ramana on this one, I feel that FreeBSD trying to plough a
slightly different furrow is just going to cause major problems for
everyone.

I don't believe a claim that LLVM can't be made to work with the
standard EHABI data structures.  It can do this on Linux, so I can't
conceive of any reason why it cannot also do so on FreeBSD.

R.

> Thanks for the review and the feedback.
> 
> Gruss,
> Andreas
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][ARM] FreeBSD ARM support, EABI, v3
  2015-01-14  9:54         ` Richard Earnshaw
@ 2015-01-15 23:01           ` Andreas Tobler
  0 siblings, 0 replies; 7+ messages in thread
From: Andreas Tobler @ 2015-01-15 23:01 UTC (permalink / raw)
  To: Richard Earnshaw, Ramana Radhakrishnan; +Cc: GCC Patches

On 14.01.15 10:43, Richard Earnshaw wrote:
> On 13/01/15 21:08, Andreas Tobler wrote:
>> On 13.01.15 11:25, Ramana Radhakrishnan wrote:
>>> On Thu, Jan 8, 2015 at 8:51 PM, Andreas Tobler <andreast-list@fgznet.ch> wrote:
>>>> On 08.01.15 17:27, Richard Earnshaw wrote:
>>>>>
>>>>> On 29/12/14 18:44, Andreas Tobler wrote:
>>>>>>
>>>>>> All,
>>>>>>
>>>>>> here is the third attempt to support ARM with FreeBSD.
>>>>>>
>>>>>> In the meantime we found another issue in the unwinder where I had to
>>>>>> adapt some stuff.
>>>>>>
>>>>>> The unwind_phase2_forced function in libgcc calls a stop_fn function.
>>>>>> This stop_fn is in FreeBSD's libthr implementation and is called
>>>>>> thread_unwind_stop. This thread_unwind_stop is a generic function used
>>>>>> on all FreeBSD archs.
>>>>>>
>>>>>> The issue is now that this thread_unwind_stop expects a double int for
>>>>>> the exception_class, like on every other arch. For ARM EABI this
>>>>>> exception_class is an array of char which is passed in one register as
>>>>>> pointer vs. two registers for a double int.
>>>>>>
>>>>>> To solve this issue we defined the exception_class as double integer for
>>>>>> FreeBSD.
>>>
>>> My apologies for the slow response, some other work and then holidays
>>> intervened.
>>
>> Np, the only issue which made me hurry was the stage 4 entering this week.
>>
>>> >From my understanding of the ABI document the implementation is
>>> currently as mandated by the ABI. Also this isn't a part of the ABI
>>> that's available for the platform (here FreeBSD to manipulate and
>>> change as per it's wishes). ARM EHABI is special for software, making
>>> FreeBSD more "special" for ARM appears to be counter intuitive from my
>>> point of view. A number of exception unwinding libraries. for e.g.
>>> libobjc , libstdc++ all use this implementation of exception_class.
>>> Therefore this creates a divergence for the FreeBSD port which is
>>> different from everything else. I expect that a number of language run
>>> time support libraries that supported the ARM EHABI would be using
>>> such an implementation, therefore you need to fix every single
>>> implementation of this in every unwinder that supports the ARM EHABI
>>> which I expect to have been ported to in a number of libraries
>>> already. (I already see this in libobjc and libstdc++ in the GCC tree)
>>
>> Grr ;) I didn't want to hear this answer, but I expected it somehow.
>> My proposal was the least effort for me.
>> The other way round is going to be very hard. Maybe impossible.
>>
>> It is not only FreeBSD which is affected but also llvm and friends. They
>> use for exception_class uint64_t.
>>
>> I have to take a picture how the effort is and if it would be possible
>> to do such a change in FreeBSD and more important in llvm etc.
>>
>>> I would rather fix the thread_unwind_stop implementation in libthr for
>>> ARM EHABI rather than make this change.
>>
>> It wouldn't be a 'fix' but more a wrapper I think.
>>
>>>>>> This adaptation reduced the failure count in libstdc++ by about 40 fails.
>>>>>>
>>>>>> I build and test this port on a regular basis and I post the results to
>>>>>> the usual place.
>>>
>>> Thanks for doing this. I'm really glad that FreeBSD is finally moving to EABI.
>>
>
> I agree with Ramana on this one, I feel that FreeBSD trying to plough a
> slightly different furrow is just going to cause major problems for
> everyone.
>
> I don't believe a claim that LLVM can't be made to work with the
> standard EHABI data structures.  It can do this on Linux, so I can't
> conceive of any reason why it cannot also do so on FreeBSD.

Thanks for the feedback, both! I'm busy to get a picture and I come back 
as soon I have a plan.

It is not a technical problem, it is, from my point of view, a 
distribution issue. Iow, we 'shipped' ABI/API X and we want/have to 
change to ABI/API Y.
So it takes a while till I get the plan :)

Andreas

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-01-15 22:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-29 18:45 [PATCH][ARM] FreeBSD ARM support, EABI, v3 Andreas Tobler
2015-01-08 16:27 ` Richard Earnshaw
2015-01-08 20:51   ` Andreas Tobler
2015-01-13 10:44     ` Ramana Radhakrishnan
2015-01-13 21:11       ` Andreas Tobler
2015-01-14  9:54         ` Richard Earnshaw
2015-01-15 23:01           ` Andreas Tobler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).