Forráskód Böngészése

m68k: add fenv support from glibc

Waldemar Brodkorb 3 hete
szülő
commit
d69c496886

+ 1 - 0
extra/Configs/Config.in.arch

@@ -166,6 +166,7 @@ config UCLIBC_HAS_FENV
 	depends on TARGET_i386 || \
 		   TARGET_aarch64 || \
 		   TARGET_arm || \
+		   TARGET_m68k || \
 		   TARGET_metag || \
 		   TARGET_mips || \
 		   TARGET_nds32 || \

+ 74 - 24
libc/sysdeps/linux/m68k/bits/fenv.h

@@ -1,5 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+/* Copyright (C) 1997-2025 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -12,31 +11,38 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
 
 #ifndef _FENV_H
 # error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
 #endif
 
 
+#if defined __HAVE_68881__ || defined __HAVE_FPU__ || defined __mcffpu__
+
 /* Define bits representing the exception.  We use the bit positions of
    the appropriate bits in the FPSR Accrued Exception Byte.  */
 enum
   {
-    FE_INEXACT = 1 << 3,
-#define FE_INEXACT	FE_INEXACT
-    FE_DIVBYZERO = 1 << 4,
-#define FE_DIVBYZERO	FE_DIVBYZERO
-    FE_UNDERFLOW = 1 << 5,
-#define FE_UNDERFLOW	FE_UNDERFLOW
-    FE_OVERFLOW = 1 << 6,
-#define FE_OVERFLOW	FE_OVERFLOW
-    FE_INVALID = 1 << 7
-#define FE_INVALID	FE_INVALID
+    FE_INEXACT =
+# define FE_INEXACT	(1 << 3)
+      FE_INEXACT,
+    FE_DIVBYZERO =
+# define FE_DIVBYZERO	(1 << 4)
+      FE_DIVBYZERO,
+    FE_UNDERFLOW =
+# define FE_UNDERFLOW	(1 << 5)
+      FE_UNDERFLOW,
+    FE_OVERFLOW =
+# define FE_OVERFLOW	(1 << 6)
+      FE_OVERFLOW,
+    FE_INVALID =
+# define FE_INVALID	(1 << 7)
+      FE_INVALID
   };
 
-#define FE_ALL_EXCEPT \
+# define FE_ALL_EXCEPT \
 	(FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
 
 /* The m68k FPU supports all of the four defined rounding modes.  We use
@@ -44,21 +50,45 @@ enum
    appropriate macros.  */
 enum
   {
-    FE_TONEAREST = 0,
-#define FE_TONEAREST	FE_TONEAREST
-    FE_TOWARDZERO = 1 << 4,
-#define FE_TOWARDZERO	FE_TOWARDZERO
-    FE_DOWNWARD = 2 << 4,
-#define FE_DOWNWARD	FE_DOWNWARD
-    FE_UPWARD = 3 << 4
-#define FE_UPWARD	FE_UPWARD
+    FE_TONEAREST =
+# define FE_TONEAREST	0
+      FE_TONEAREST,
+    FE_TOWARDZERO =
+# define FE_TOWARDZERO	(1 << 4)
+      FE_TOWARDZERO,
+    FE_DOWNWARD =
+# define FE_DOWNWARD	(2 << 4)
+      FE_DOWNWARD,
+    FE_UPWARD =
+# define FE_UPWARD	(3 << 4)
+      FE_UPWARD
   };
 
+#else
+
+/* In the soft-float case, only rounding to nearest is supported, with
+   no exceptions.  */
+
+# define FE_ALL_EXCEPT 0
+
+enum
+  {
+    __FE_UNDEFINED = -1,
+
+    FE_TONEAREST =
+# define FE_TONEAREST	0
+      FE_TONEAREST
+  };
+
+#endif
+
 
 /* Type representing exception flags.  */
 typedef unsigned int fexcept_t;
 
 
+#if defined __HAVE_68881__ || defined __HAVE_FPU__ || defined __mcffpu__
+
 /* Type representing floating-point environment.  This structure
    corresponds to the layout of the block written by `fmovem'.  */
 typedef struct
@@ -69,10 +99,30 @@ typedef struct
   }
 fenv_t;
 
+#else
+
+/* Keep ABI compatibility with the type used in the generic
+   bits/fenv.h, formerly used for no-FPU ColdFire.  */
+typedef struct
+  {
+    fexcept_t __excepts;
+  }
+fenv_t;
+
+#endif
+
 /* If the default argument is used we use this value.  */
 #define FE_DFL_ENV	((const fenv_t *) -1)
 
-#ifdef __USE_GNU
+#if defined __USE_GNU && (defined __HAVE_68881__	\
+			  || defined __HAVE_FPU__	\
+			  || defined __mcffpu__)
 /* Floating-point environment where none of the exceptions are masked.  */
 # define FE_NOMASK_ENV	((const fenv_t *) -2)
 #endif
+
+/* Type representing floating-point control modes.  */
+typedef unsigned int femode_t;
+
+/* Default floating-point control modes.  */
+# define FE_DFL_MODE	((const femode_t *) -1L)

+ 46 - 31
libc/sysdeps/linux/m68k/fpu_control.h

@@ -1,6 +1,5 @@
 /* 68k FPU control word definitions.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   Copyright (C) 1996-2025 Free Software Foundation, Inc.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -13,8 +12,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
 
 #ifndef _FPU_CONTROL_H
 #define _FPU_CONTROL_H
@@ -29,9 +28,9 @@
  * 12     -> enable trap for OVFL exception
  * 11     -> enable trap for UNFL exception
  * 10     -> enable trap for DZ exception
- *  9     -> enable trap for INEX2 exception
- *  8     -> enable trap for INEX1 exception
- *  7-6   -> Precision Control
+ *  9     -> enable trap for INEX2 exception (INEX on Coldfire)
+ *  8     -> enable trap for INEX1 exception (IDE on Coldfire)
+ *  7-6   -> Precision Control (only bit 6 is used on Coldfire)
  *  5-4   -> Rounding Control
  *  3-0   -> zero (read as 0, write as 0)
  *
@@ -53,50 +52,66 @@
 
 #include <features.h>
 
+#if defined (__mcoldfire__) && !defined (__mcffpu__)
+
+# define _FPU_RESERVED 0xffffffff
+# define _FPU_DEFAULT  0x00000000
+# define _FPU_GETCW(cw) ((cw) = 0)
+# define _FPU_SETCW(cw) ((void) (cw))
+
+#else
+
 /* masking of interrupts */
-#define _FPU_MASK_BSUN  0x8000
-#define _FPU_MASK_SNAN  0x4000
-#define _FPU_MASK_OPERR 0x2000
-#define _FPU_MASK_OVFL  0x1000
-#define _FPU_MASK_UNFL  0x0800
-#define _FPU_MASK_DZ    0x0400
-#define _FPU_MASK_INEX1 0x0200
-#define _FPU_MASK_INEX2 0x0100
+# define _FPU_MASK_BSUN  0x8000
+# define _FPU_MASK_SNAN  0x4000
+# define _FPU_MASK_OPERR 0x2000
+# define _FPU_MASK_OVFL  0x1000
+# define _FPU_MASK_UNFL  0x0800
+# define _FPU_MASK_DZ    0x0400
+# define _FPU_MASK_INEX1 0x0200
+# define _FPU_MASK_INEX2 0x0100
 
 /* precision control */
-#define _FPU_EXTENDED 0x00   /* RECOMMENDED */
-#define _FPU_DOUBLE   0x80
-#define _FPU_SINGLE   0x40     /* DO NOT USE */
+# ifdef __mcoldfire__
+#  define _FPU_DOUBLE   0x00
+# else
+#  define _FPU_EXTENDED 0x00   /* RECOMMENDED */
+#  define _FPU_DOUBLE   0x80
+# endif
+# define _FPU_SINGLE   0x40     /* DO NOT USE */
 
 /* rounding control */
-#define _FPU_RC_NEAREST 0x00    /* RECOMMENDED */
-#define _FPU_RC_ZERO    0x10
-#define _FPU_RC_DOWN    0x20
-#define _FPU_RC_UP      0x30
+# define _FPU_RC_NEAREST 0x00    /* RECOMMENDED */
+# define _FPU_RC_ZERO    0x10
+# define _FPU_RC_DOWN    0x20
+# define _FPU_RC_UP      0x30
 
-#define _FPU_RESERVED 0xFFFF000F  /* Reserved bits in fpucr */
+# ifdef __mcoldfire__
+#  define _FPU_RESERVED 0xFFFF800F
+# else
+#  define _FPU_RESERVED 0xFFFF000F  /* Reserved bits in fpucr */
+# endif
 
 
 /* Now two recommended fpucr */
 
 /* The fdlibm code requires no interrupts for exceptions.  Don't
    change the rounding mode, it would break long double I/O!  */
-#define _FPU_DEFAULT  0x00000000
+# define _FPU_DEFAULT  0x00000000
 
 /* IEEE:  same as above, but exceptions.  We must make it non-zero so
    that __setfpucw works.  This bit will be ignored.  */
-#define _FPU_IEEE     0x00000001
+# define _FPU_IEEE     0x00000001
+
+/* Macros for accessing the hardware control word.  */
+# define _FPU_GETCW(cw) __asm__ ("fmove%.l %!, %0" : "=dm" (cw))
+# define _FPU_SETCW(cw) __asm__ volatile ("fmove%.l %0, %!" : : "dm" (cw))
+#endif
 
 /* Type of the control word.  */
 typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
 
-/* Macros for accessing the hardware control word.  */
-#define _FPU_GETCW(cw) __asm__ ("fmove%.l %!, %0" : "=dm" (cw))
-#define _FPU_SETCW(cw) __asm__ __volatile__ ("fmove%.l %0, %!" : : "dm" (cw))
-
-#if 0
 /* Default control word set at startup.  */
 extern fpu_control_t __fpu_control;
-#endif
 
 #endif /* _M68K_FPU_CONTROL_H */

+ 16 - 0
libm/m68k/Makefile.arch

@@ -0,0 +1,16 @@
+# Makefile for uClibc-ng
+# Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+
+ifeq ($(UCLIBC_HAS_FENV),y)
+libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c)
+libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC))
+endif
+
+libm_ARCH_OBJS:=$(libm_ARCH_OBJ)
+
+ifeq ($(DOPIC),y)
+libm-a-y+=$(libm_ARCH_OBJS:.o=.os)
+else
+libm-a-y+=$(libm_ARCH_OBJS)
+endif
+libm-so-y+=$(libm_ARCH_OBJS:.o=.os)

+ 39 - 0
libm/m68k/fclrexcpt.c

@@ -0,0 +1,39 @@
+/* Clear given exceptions in current floating-point environment.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+feclearexcept (int excepts)
+{
+  fexcept_t fpsr;
+
+  /* Mask out unsupported bits/exceptions.  */
+  excepts &= FE_ALL_EXCEPT;
+
+  /* Fetch the fpu status register.  */
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+  /* Clear the relevant bits.  */
+  fpsr &= ~excepts;
+
+  /* Put the new data in effect.  */
+  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+
+  /* Success.  */
+  return 0;
+}

+ 36 - 0
libm/m68k/fedisblxcpt.c

@@ -0,0 +1,36 @@
+/* Disable floating-point exceptions.
+   Copyright (C) 2000-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fedisableexcept (int excepts)
+{
+  unsigned int old_exc, new_exc;
+
+  /* Get the current control register contents.  */
+  __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc));
+
+  old_exc = (new_exc >> 6) & FE_ALL_EXCEPT;
+
+  excepts &= FE_ALL_EXCEPT;
+
+  new_exc &= ~(excepts << 6);
+  __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc));
+
+  return old_exc;
+}

+ 36 - 0
libm/m68k/feenablxcpt.c

@@ -0,0 +1,36 @@
+/* Enable floating-point exceptions.
+   Copyright (C) 2000-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+feenableexcept (int excepts)
+{
+  unsigned int new_exc, old_exc;
+
+  /* Get the current control register contents.  */
+  __asm__ ("fmove%.l %!,%0" : "=dm" (new_exc));
+
+  old_exc = (new_exc >> 6) & FE_ALL_EXCEPT;
+
+  excepts &= FE_ALL_EXCEPT;
+
+  new_exc |= excepts << 6;
+  __asm__ ("fmove%.l %0,%!" : : "dm" (new_exc));
+
+  return old_exc;
+}

+ 33 - 0
libm/m68k/fegetenv.c

@@ -0,0 +1,33 @@
+/* Store current floating-point environment.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fegetenv (fenv_t *envp)
+{
+#ifdef __mcoldfire__
+  __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register));
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register));
+  __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address));
+#else
+  __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp));
+#endif
+
+  /* Success.  */
+  return 0;
+}

+ 29 - 0
libm/m68k/fegetexcept.c

@@ -0,0 +1,29 @@
+/* Get enabled floating-point exceptions.
+   Copyright (C) 2000-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fegetexcept (void)
+{
+  unsigned int exc;
+
+  /* Get the current control register contents.  */
+  __asm__ ("fmove%.l %!,%0" : "=dm" (exc));
+
+  return (exc >> 6) & FE_ALL_EXCEPT;
+}

+ 26 - 0
libm/m68k/fegetmode.c

@@ -0,0 +1,26 @@
+/* Store current floating-point control modes.  M68K version.
+   Copyright (C) 2016-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fegetmode (femode_t *modep)
+{
+  _FPU_GETCW (*modep);
+  return 0;
+}

+ 28 - 0
libm/m68k/fegetround.c

@@ -0,0 +1,28 @@
+/* Return current rounding direction.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fegetround (void)
+{
+  int fpcr;
+
+  __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr));
+
+  return fpcr & FE_UPWARD;
+}

+ 42 - 0
libm/m68k/feholdexcpt.c

@@ -0,0 +1,42 @@
+/* Store current floating-point environment and clear exceptions.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+feholdexcept (fenv_t *envp)
+{
+  fexcept_t fpcr, fpsr;
+
+  /* Store the environment.  */
+#ifdef __mcoldfire__
+  __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (envp->__control_register));
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (envp->__status_register));
+  __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (envp->__instruction_address));
+#else
+  __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*envp));
+#endif
+
+  /* Now clear all exceptions.  */
+  fpsr = envp->__status_register & ~FE_ALL_EXCEPT;
+  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+  /* And set all exceptions to non-stop.  */
+  fpcr = envp->__control_register & ~(FE_ALL_EXCEPT << 6);
+  __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr));
+
+  return 0;
+}

+ 63 - 0
libm/m68k/fesetenv.c

@@ -0,0 +1,63 @@
+/* Install given floating-point environment.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fesetenv (const fenv_t *envp)
+{
+  fenv_t temp;
+
+  /* Install the environment specified by ENVP.  But there are a few
+     values which we do not want to come from the saved environment.
+     Therefore, we get the current environment and replace the values
+     we want to use from the environment specified by the parameter.  */
+#ifdef __mcoldfire__
+  __asm__ ("fmove%.l %/fpcr,%0" : "=dm" (temp.__control_register));
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (temp.__status_register));
+  __asm__ ("fmove%.l %/fpiar,%0" : "=dm" (temp.__instruction_address));
+#else
+  __asm__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (*&temp));
+#endif
+
+  temp.__status_register &= ~FE_ALL_EXCEPT;
+  temp.__control_register &= ~((FE_ALL_EXCEPT << 6) | FE_UPWARD);
+  if (envp == FE_DFL_ENV)
+    ;
+  else if (envp == FE_NOMASK_ENV)
+    temp.__control_register |= FE_ALL_EXCEPT << 6;
+  else
+    {
+      temp.__control_register |= (envp->__control_register
+				  & ((FE_ALL_EXCEPT << 6) | FE_UPWARD));
+      temp.__status_register |= envp->__status_register & FE_ALL_EXCEPT;
+    }
+
+#ifdef __mcoldfire__
+  __asm__ __volatile__ ("fmove%.l %0,%/fpiar"
+			:: "dm" (temp.__instruction_address));
+  __asm__ __volatile__ ("fmove%.l %0,%/fpcr"
+			:: "dm" (temp.__control_register));
+  __asm__ __volatile__ ("fmove%.l %0,%/fpsr"
+			:: "dm" (temp.__status_register));
+#else
+  __asm__ __volatile__ ("fmovem%.l %0,%/fpcr/%/fpsr/%/fpiar" : : "m" (*&temp));
+#endif
+
+  /* Success.  */
+  return 0;
+}

+ 30 - 0
libm/m68k/fesetexcept.c

@@ -0,0 +1,30 @@
+/* Set given exception flags.  M68K version.
+   Copyright (C) 2016-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fesetexcept (int excepts)
+{
+  fexcept_t fpsr;
+
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+  fpsr |= excepts & FE_ALL_EXCEPT;
+  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+
+  return 0;
+}

+ 31 - 0
libm/m68k/fesetmode.c

@@ -0,0 +1,31 @@
+/* Install given floating-point control modes.  M68K version.
+   Copyright (C) 2016-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+#include <fpu_control.h>
+
+int
+fesetmode (const femode_t *modep)
+{
+  femode_t mode;
+  if (modep == FE_DFL_MODE)
+    mode = _FPU_DEFAULT;
+  else
+    mode = *modep;
+  _FPU_SETCW (mode);
+  return 0;
+}

+ 35 - 0
libm/m68k/fesetround.c

@@ -0,0 +1,35 @@
+/* Set current rounding direction.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fesetround (int round)
+{
+  fexcept_t fpcr;
+
+  if (round & ~FE_UPWARD)
+    /* ROUND is no valid rounding mode.  */
+    return 1;
+
+  __asm__ ("fmove%.l %!,%0" : "=dm" (fpcr));
+  fpcr &= ~FE_UPWARD;
+  fpcr |= round;
+  __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (fpcr));
+
+  return 0;
+}

+ 39 - 0
libm/m68k/feupdateenv.c

@@ -0,0 +1,39 @@
+/* Install given floating-point environment and raise exceptions.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+feupdateenv (const fenv_t *envp)
+{
+  fexcept_t fpsr;
+
+  /* Save current exceptions.  */
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+  fpsr &= FE_ALL_EXCEPT;
+
+  /* Install new environment.  */
+  fesetenv (envp);
+
+  /* Raise the saved exception.  Incidentally for us the implementation
+     defined format of the values in objects of type fexcept_t is the
+     same as the ones specified using the FE_* constants.  */
+  feraiseexcept ((int) fpsr);
+
+  /* Success.  */
+  return 0;
+}

+ 32 - 0
libm/m68k/fgetexcptflg.c

@@ -0,0 +1,32 @@
+/* Store current representation for exceptions.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+  fexcept_t fpsr;
+
+  /* Get the current exceptions.  */
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+  *flagp = fpsr & excepts & FE_ALL_EXCEPT;
+
+  /* Success.  */
+  return 0;
+}

+ 106 - 0
libm/m68k/fraiseexcpt.c

@@ -0,0 +1,106 @@
+/* Raise given exceptions.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+#include <float.h>
+#include <math.h>
+
+int
+feraiseexcept (int excepts)
+{
+#if defined(__mcffpu__)
+
+  /* The Coldfire FPU allows an exception to be raised by asserting
+     the associated EXC bit and then executing an arbitrary arithmetic
+     instruction.  fmove.l is classified as an arithmetic instruction
+     and suffices for this purpose.
+
+     We therefore raise an exception by setting both the EXC and AEXC
+     bit associated with the exception (the former being 6 bits to the
+     left of the latter) and then loading the longword at (%sp) into an
+     FP register.  */
+
+  inline void
+  raise_one_exception (int mask)
+  {
+    if (excepts & mask)
+      {
+	int fpsr;
+	double unused;
+
+	__asm__ volatile ("fmove%.l %/fpsr,%0" : "=d" (fpsr));
+	fpsr |= (mask << 6) | mask;
+	__asm__ volatile ("fmove%.l %0,%/fpsr" :: "d" (fpsr));
+	__asm__ volatile ("fmove%.l (%%sp),%0" : "=f" (unused));
+      }
+  }
+
+  raise_one_exception (FE_INVALID);
+  raise_one_exception (FE_DIVBYZERO);
+  raise_one_exception (FE_OVERFLOW);
+  raise_one_exception (FE_UNDERFLOW);
+  raise_one_exception (FE_INEXACT);
+
+#else
+  /* Raise exceptions represented by EXCEPTS.  But we must raise only one
+     signal at a time.  It is important that if the overflow/underflow
+     exception and the divide by zero exception are given at the same
+     time, the overflow/underflow exception follows the divide by zero
+     exception.  */
+
+  /* First: invalid exception.  */
+  if (excepts & FE_INVALID)
+    {
+      /* One example of an invalid operation is 0 * Infinity.  */
+      double d = HUGE_VAL;
+      __asm__ __volatile__ ("fmul%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d));
+    }
+
+  /* Next: division by zero.  */
+  if (excepts & FE_DIVBYZERO)
+    {
+      double d = 1.0;
+      __asm__ __volatile__ ("fdiv%.s %#0r0,%0; fnop" : "=f" (d) : "0" (d));
+    }
+
+  /* Next: overflow.  */
+  if (excepts & FE_OVERFLOW)
+    {
+      long double d = LDBL_MAX;
+
+      __asm__ __volatile__ ("fmul%.x %0,%0; fnop" : "=f" (d) : "0" (d));
+    }
+
+  /* Next: underflow.  */
+  if (excepts & FE_UNDERFLOW)
+    {
+      long double d = -LDBL_MAX;
+
+      __asm__ __volatile__ ("fetox%.x %0; fnop" : "=f" (d) : "0" (d));
+    }
+
+  /* Last: inexact.  */
+  if (excepts & FE_INEXACT)
+    {
+      long double d = 1.0;
+      __asm__ __volatile__ ("fdiv%.s %#0r3,%0; fnop" : "=f" (d) : "0" (d));
+    }
+
+#endif
+  /* Success.  */
+  return 0;
+}

+ 38 - 0
libm/m68k/fsetexcptflg.c

@@ -0,0 +1,38 @@
+/* Set floating-point environment exception handling.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+#include <math.h>
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+  fexcept_t fpsr;
+
+  /* Get the current status register.  */
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+  /* Install the new exception bits in the Accrued Exception Byte.  */
+  fpsr &= ~(excepts & FE_ALL_EXCEPT);
+  fpsr |= *flagp & excepts & FE_ALL_EXCEPT;
+
+  /* Store the new status register.  */
+  __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (fpsr));
+
+  /* Success.  */
+  return 0;
+}

+ 29 - 0
libm/m68k/ftestexcept.c

@@ -0,0 +1,29 @@
+/* Test exception in current environment.
+   Copyright (C) 1997-2025 Free Software Foundation, Inc.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+
+int
+fetestexcept (int excepts)
+{
+  fexcept_t fpsr;
+
+  /* Get current exceptions.  */
+  __asm__ ("fmove%.l %/fpsr,%0" : "=dm" (fpsr));
+
+  return fpsr & excepts & FE_ALL_EXCEPT;
+}