diff mbox series

LoongArch: Add soft floating-point fe* function implementations.

Message ID 20240326124623.1245676-1-caiyinyu@loongson.cn
State New
Headers show
Series LoongArch: Add soft floating-point fe* function implementations. | expand

Commit Message

caiyinyu March 26, 2024, 12:46 p.m. UTC
This patch accomplishes the following:
1. Implements soft floating-point functions to enhance compatibility and
  flexibility in environments without hardware floating-point support.
2. Refactors macro definitions by moving them from `fenv_libc.h` to
  `fpu_control.h`. This change not only simplifies the codebase but also
  eliminates the need for the unexported header file `fenv_libc.h`,
  streamlining the inclusion of floating-point utilities across different
  modules.

Signed-off-by: caiyinyu <caiyinyu@loongson.cn>
---
 sysdeps/loongarch/fpu/fclrexcpt.c             |  1 -
 sysdeps/loongarch/fpu/fedisblxcpt.c           |  3 +-
 sysdeps/loongarch/fpu/feenablxcpt.c           |  3 +-
 sysdeps/loongarch/fpu/fegetexcept.c           |  3 +-
 sysdeps/loongarch/fpu_control.h               | 29 +++++++------
 sysdeps/loongarch/math_private.h              |  1 -
 sysdeps/loongarch/nofpu/Makefile              | 10 +++++
 sysdeps/loongarch/nofpu/Subdirs               |  1 +
 sysdeps/loongarch/nofpu/Versions              |  5 +++
 sysdeps/loongarch/nofpu/fclrexcpt.c           | 37 ++++++++++++++++
 .../{fpu/fenv_libc.h => nofpu/fedisblxcpt.c}  | 24 ++++++-----
 sysdeps/loongarch/nofpu/feenablxcpt.c         | 32 ++++++++++++++
 sysdeps/loongarch/nofpu/fegetenv.c            | 32 ++++++++++++++
 sysdeps/loongarch/nofpu/fegetexcept.c         | 26 +++++++++++
 sysdeps/loongarch/nofpu/fegetmode.c           | 27 ++++++++++++
 sysdeps/loongarch/nofpu/fegetround.c          | 29 +++++++++++++
 sysdeps/loongarch/nofpu/feholdexcpt.c         | 37 ++++++++++++++++
 sysdeps/loongarch/nofpu/fesetenv.c            | 37 ++++++++++++++++
 sysdeps/loongarch/nofpu/fesetexcept.c         | 27 ++++++++++++
 sysdeps/loongarch/nofpu/fesetmode.c           | 34 +++++++++++++++
 sysdeps/loongarch/nofpu/fesetround.c          | 36 ++++++++++++++++
 sysdeps/loongarch/nofpu/feupdateenv.c         | 43 +++++++++++++++++++
 sysdeps/loongarch/nofpu/fgetexcptflg.c        | 28 ++++++++++++
 sysdeps/loongarch/nofpu/fraiseexcpt.c         | 42 ++++++++++++++++++
 sysdeps/loongarch/nofpu/fsetexcptflg.c        | 35 +++++++++++++++
 sysdeps/loongarch/nofpu/ftestexcept.c         | 27 ++++++++++++
 sysdeps/loongarch/nofpu/get-rounding-mode.h   | 34 +++++++++++++++
 sysdeps/loongarch/nofpu/sim-full.c            | 23 ++++++++++
 sysdeps/loongarch/nofpu/soft-supp.h           | 20 +++++++++
 29 files changed, 654 insertions(+), 32 deletions(-)
 create mode 100644 sysdeps/loongarch/nofpu/Makefile
 create mode 100644 sysdeps/loongarch/nofpu/Subdirs
 create mode 100644 sysdeps/loongarch/nofpu/Versions
 create mode 100644 sysdeps/loongarch/nofpu/fclrexcpt.c
 rename sysdeps/loongarch/{fpu/fenv_libc.h => nofpu/fedisblxcpt.c} (62%)
 create mode 100644 sysdeps/loongarch/nofpu/feenablxcpt.c
 create mode 100644 sysdeps/loongarch/nofpu/fegetenv.c
 create mode 100644 sysdeps/loongarch/nofpu/fegetexcept.c
 create mode 100644 sysdeps/loongarch/nofpu/fegetmode.c
 create mode 100644 sysdeps/loongarch/nofpu/fegetround.c
 create mode 100644 sysdeps/loongarch/nofpu/feholdexcpt.c
 create mode 100644 sysdeps/loongarch/nofpu/fesetenv.c
 create mode 100644 sysdeps/loongarch/nofpu/fesetexcept.c
 create mode 100644 sysdeps/loongarch/nofpu/fesetmode.c
 create mode 100644 sysdeps/loongarch/nofpu/fesetround.c
 create mode 100644 sysdeps/loongarch/nofpu/feupdateenv.c
 create mode 100644 sysdeps/loongarch/nofpu/fgetexcptflg.c
 create mode 100644 sysdeps/loongarch/nofpu/fraiseexcpt.c
 create mode 100644 sysdeps/loongarch/nofpu/fsetexcptflg.c
 create mode 100644 sysdeps/loongarch/nofpu/ftestexcept.c
 create mode 100644 sysdeps/loongarch/nofpu/get-rounding-mode.h
 create mode 100644 sysdeps/loongarch/nofpu/sim-full.c
 create mode 100644 sysdeps/loongarch/nofpu/soft-supp.h

Comments

Joseph Myers March 26, 2024, 5:34 p.m. UTC | #1
On Tue, 26 Mar 2024, caiyinyu wrote:

> This patch accomplishes the following:
> 1. Implements soft floating-point functions to enhance compatibility and
>   flexibility in environments without hardware floating-point support.

Does this actually do anything useful for users, i.e. make the software 
floating-point rounding mode and exceptions state affect both user 
arithmetic and functions within libc/libm?  As far as I can see, while 
you're building copies of some software floating-point libgcc functions 
for libc, you're not doing anything to make them use the software 
floating-point environment state, and not exporting them for use by users.

For software floating-point rounding modes and exceptions to be useful to 
users, you need to follow powerpc/nofpu and export the functions from 
libc.  You then need to arrange for libgcc *not* to provide the functions 
when libc does (see how libgcc/configure.ac sets ppc_fp_compat depending 
on glibc version, for example).  And there's also the matter of providing 
libc (as opposed to libm) interfaces for cases where compiler-generated 
code may need to manipulate floating-point environment state without 
calling libm functions (see how powerpc-nofpu provides 
__atomic_feholdexcept __atomic_feclearexcept __atomic_feupdateenv 
__flt_rounds and rs6000_atomic_assign_expand_fenv in the GCC back end can 
generate calls to the first three of those functions - the fourth is 
future-proofing for if GCC gets proper support for making FLT_ROUNDS 
depend on the rounding mode in future).
caiyinyu March 27, 2024, 8:42 a.m. UTC | #2
在 2024/3/27 上午1:34, Joseph Myers 写道:
> On Tue, 26 Mar 2024, caiyinyu wrote:
>
>> This patch accomplishes the following:
>> 1. Implements soft floating-point functions to enhance compatibility and
>>    flexibility in environments without hardware floating-point support.
> Does this actually do anything useful for users, i.e. make the software
> floating-point rounding mode and exceptions state affect both user
> arithmetic and functions within libc/libm?  As far as I can see, while
> you're building copies of some software floating-point libgcc functions
> for libc, you're not doing anything to make them use the software
> floating-point environment state, and not exporting them for use by users.

Yes, this patch does make sense in both libc and libm and it can be 
proved by the following glibc tests:
stdlib/tst-strtod-underflow
stdio-common/tst-printf-round
math/test-fenv
math/test-femode{, -traps}
...


Actually, without this patch, you will get the warning info something 
like the following when make check and the related tsts would failed or 
not be tested correctly.
"test-fenv.c:229:(.text+0x48): warning: feclearexcept is not implemented 
and will always fail"

Even more, the warning information appears in glibc's check logs of all 
the following architectures (tested with build-many-glibcs.py).
csky-linux-gnuabiv2-soft
m68k-linux-gnu-coldfire-soft
or1k-linux-gnu-soft
powerpc-linux-gnu-soft
riscv64-linux-gnu-rv64imac-lp64
sh4-linux-gnu-soft
...
I think all these related tsts were not tested correctly on these 
architectures.


>
> For software floating-point rounding modes and exceptions to be useful to
> users, you need to follow powerpc/nofpu and export the functions from
> libc.

All the functions Implemented in this patch are exported from libm.so 
the same as powerpc nofpu.


> You then need to arrange for libgcc *not* to provide the functions
> when libc does (see how libgcc/configure.ac sets ppc_fp_compat depending
> on glibc version, for example).  And there's also the matter of providing
> libc (as opposed to libm) interfaces for cases where compiler-generated
> code may need to manipulate floating-point environment state without
> calling libm functions (see how powerpc-nofpu provides
> __atomic_feholdexcept __atomic_feclearexcept __atomic_feupdateenv
> __flt_rounds and rs6000_atomic_assign_expand_fenv in the GCC back end can
> generate calls to the first three of those functions - the fourth is
> future-proofing for if GCC gets proper support for making FLT_ROUNDS
> depend on the rounding mode in future).

I've reviewed your previous commits in glibc and gcc about
__atomic_feholdexcept __atomic_feclearexcept __atomic_feupdateenv and 
__flt_rounds
and I wil make other patches to implement these functions in glibc and gcc.


In summary, I believe this patch is fine except for the _atomic* and 
__flt_rounds functions.


>
Joseph Myers March 27, 2024, 5:10 p.m. UTC | #3
On Wed, 27 Mar 2024, caiyinyu wrote:

> Yes, this patch does make sense in both libc and libm and it can be proved by
> the following glibc tests:

Please explain more how it works.

> All the functions Implemented in this patch are exported from libm.so the same
> as powerpc nofpu.

I'm talking about functions such as __adddf3 (which would need to be 
exported from libc, not libm, to provide exceptions / rounding modes 
support for software floating point).  I don't see them in any Versions 
file for LoongArch.

Furthermore, this patch isn't changing sfp-machine.h for LoongArch, which 
uses fpu_control.h to get rounding mode / exceptions state, and it isn't 
changing how fpu_control.h uses constant 0 for that state in the 
soft-float case.  So I don't see how it would produce *working* exceptions 
/ rounding modes support for software floating-point arithmetic.
caiyinyu March 31, 2024, 10:31 a.m. UTC | #4
在 2024/3/28 上午1:10, Joseph Myers 写道:
> On Wed, 27 Mar 2024, caiyinyu wrote:
>
>> Yes, this patch does make sense in both libc and libm and it can be proved by
>> the following glibc tests:
> Please explain more how it works.
>
>> All the functions Implemented in this patch are exported from libm.so the same
>> as powerpc nofpu.
> I'm talking about functions such as __adddf3 (which would need to be
> exported from libc, not libm, to provide exceptions / rounding modes
> support for software floating point).  I don't see them in any Versions
> file for LoongArch.
>
> Furthermore, this patch isn't changing sfp-machine.h for LoongArch, which
> uses fpu_control.h to get rounding mode / exceptions state, and it isn't
> changing how fpu_control.h uses constant 0 for that state in the
> soft-float case.  So I don't see how it would produce *working* exceptions
> / rounding modes support for software floating-point arithmetic.

I revised and submitted the version 2 patch:

The main corrections in the version 2 patch are:
1. Correcting the nofpu libc files:  sim-full.c sfp-machine.h soft-supp.h.
2. Updating/modifying the fpu/nofpu libc 
Versions/libc.abilist/localplt.data files.

v1: https://sourceware.org/pipermail/libc-alpha/2024-March/155597.html
v2: https://sourceware.org/pipermail/libc-alpha/2024-March/155707.html

LoongArch soft float support was added in version 2.37, but the fe* 
functions
were not completely added. I want to backport this patch if possible
(it requires some modifications) to the 2.37/38/39/master branch, so the 
version of
the relevant symbols in  Versions is GLIBC_2.37.

Here is the difference between v1 and v2 :
1.
diff --git a/sysdeps/loongarch/nofpu/sim-full.c 
b/sysdeps/loongarch/nofpu/sim-full.c
index a2bbb9f880..b10e5b2f4d 100644
--- a/sysdeps/loongarch/nofpu/sim-full.c
+++ b/sysdeps/loongarch/nofpu/sim-full.c
@@ -16,8 +16,22 @@
     License along with the GNU C Library.  If not, see
     <https://www.gnu.org/licenses/>.  */

+#include "soft-fp.h"
  #include "soft-supp.h"
+#include <signal.h>

  /* By default, no exceptions should trap.  */
  __thread int __sim_cw_thread;
  libc_hidden_tls_def (__sim_cw_thread);
+
+void
+__simulate_exceptions (int excepts)
+{
+  int enable;
+  __sim_cw_thread |= excepts;
+
+  enable = __sim_cw_thread & _FPU_ENABLE_MASK;
+  if (excepts & __sim_cw_thread & (enable << ENABLE_SHIFT))
+    raise (SIGFPE);
+}
+libc_hidden_def (__simulate_exceptions)
diff --git a/sysdeps/loongarch/nofpu/soft-supp.h 
b/sysdeps/loongarch/nofpu/soft-supp.h
index 37d83399e8..8d3ba09764 100644
--- a/sysdeps/loongarch/nofpu/soft-supp.h
+++ b/sysdeps/loongarch/nofpu/soft-supp.h
@@ -18,3 +18,5 @@

  extern __thread int __sim_cw_thread attribute_tls_model_ie;
  libc_hidden_tls_proto (__sim_cw_thread, tls_model ("initial-exec"));
+
+extern void __simulate_exceptions (int excepts);
diff --git a/sysdeps/loongarch/sfp-machine.h 
b/sysdeps/loongarch/sfp-machine.h
index cbf66500db..eda6c66423 100644
--- a/sysdeps/loongarch/sfp-machine.h
+++ b/sysdeps/loongarch/sfp-machine.h
@@ -64,10 +64,6 @@
      } \
    while (0)

-#define _FP_DECL_EX fpu_control_t _fcw
-
-#define FP_ROUNDMODE (_fcw & 0x300)
-
  #define FP_RND_NEAREST FE_TONEAREST
  #define FP_RND_ZERO FE_TOWARDZERO
  #define FP_RND_PINF FE_UPWARD
@@ -82,6 +78,8 @@
  #define _FP_TININESS_AFTER_ROUNDING 1

  #ifdef __loongarch_hard_float
+#define _FP_DECL_EX fpu_control_t _fcw
+#define FP_ROUNDMODE (_fcw & 0x300)
  #define FP_INIT_ROUNDMODE \
    do \
      { \
@@ -98,5 +96,12 @@
    while (0)
  #define FP_TRAPPING_EXCEPTIONS ((_fcw << 16) & 0x1f0000)
  #else
-#define FP_INIT_ROUNDMODE _fcw = FP_RND_NEAREST
+#define FP_HANDLE_EXCEPTIONS    __simulate_exceptions (_fex)
+#define FP_ROUNDMODE        (__sim_cw_thread & _FPU_RC_MASK)
+#define FP_TRAPPING_EXCEPTIONS    (__sim_cw_thread & _FPU_ENABLE_MASK)
+
+extern __thread int __sim_cw_thread attribute_tls_model_ie;
+libc_hidden_tls_proto (__sim_cw_thread, tls_model ("initial-exec"));
+extern void __simulate_exceptions (int excepts);
+libc_hidden_proto (__simulate_exceptions)
  #endif

2. libc.abilist is too long so not listed here.
diff --git a/sysdeps/loongarch/nofpu/Versions 
b/sysdeps/loongarch/nofpu/Versions
index 6d7f6aae6c..73b6a71bbd 100644
--- a/sysdeps/loongarch/nofpu/Versions
+++ b/sysdeps/loongarch/nofpu/Versions
@@ -1,5 +1,13 @@
  libc {
+  GLIBC_2.37 {
+    __adddf3; __addsf3; __divdf3; __divsf3; __eqdf2; __eqsf2;
+    __extendsfdf2; __fixdfsi; __fixsfsi;
+    __fixunsdfsi; __fixunssfsi;
+    __floatsidf; __floatsisf;
+    __gedf2; __gesf2; __ledf2; __lesf2; __muldf3; __mulsf3;
+    __negdf2; __negsf2; __subdf3; __subsf3; __truncdfsf2;
+  }
    GLIBC_PRIVATE {
-    __sim_cw_thread;
+    __sim_cw_thread; __simulate_exceptions;
    }
  }
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/fpu/localplt.data 
b/sysdeps/unix/sysv/linux/loongarch/lp64/fpu/localplt.data
new file mode 100644
index 0000000000..547b1c1b7f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/fpu/localplt.data
@@ -0,0 +1,7 @@
+# See scripts/check-localplt.awk for how this file is processed.
+# PLT use is required for the malloc family and for matherr because
+# users can define their own functions and have library internals call 
them.
+libc.so: calloc
+libc.so: free
+libc.so: malloc
+libc.so: realloc
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/Implies 
b/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/Implies
new file mode 100644
index 0000000000..1090fb545a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/Implies
@@ -0,0 +1 @@
+loongarch/nofpu
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/localplt.data 
b/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/localplt.data
new file mode 100644
index 0000000000..d40826c783
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/localplt.data
@@ -0,0 +1,23 @@
+# See scripts/check-localplt.awk for how this file is processed.
+# PLT use is required for the malloc family and for matherr because
+# users can define their own functions and have library internals call 
them.
+libc.so: calloc
+libc.so: free
+libc.so: malloc
+libc.so: realloc
+libc.so: __fixsfsi
+libc.so: __divsf3
+libc.so: __adddf3
+libc.so: __eqdf2
+libc.so: __gedf2
+libc.so: __floatsisf
+libc.so: __eqsf2
+libc.so: __subsf3
+libc.so: __mulsf3
+libc.so: __muldf3
+libc.so: __subdf3
+libc.so: __divdf3
+libc.so: __ledf2
+libc.so: __floatsidf
+libc.so: __extendsfdf2
+libc.so: __addsf3


>
Joseph Myers April 2, 2024, 9:10 p.m. UTC | #5
On Sun, 31 Mar 2024, caiyinyu wrote:

> LoongArch soft float support was added in version 2.37, but the fe* functions
> were not completely added. I want to backport this patch if possible
> (it requires some modifications) to the 2.37/38/39/master branch, so the
> version of
> the relevant symbols in  Versions is GLIBC_2.37.

I don't think such new symbol additions are appropriate for backporting; 
the GLIBC_2.37 symbol version contents should have been fixed at the time 
2.37 was released.

> diff --git a/sysdeps/loongarch/nofpu/Versions
> b/sysdeps/loongarch/nofpu/Versions
> index 6d7f6aae6c..73b6a71bbd 100644
> --- a/sysdeps/loongarch/nofpu/Versions
> +++ b/sysdeps/loongarch/nofpu/Versions
> @@ -1,5 +1,13 @@
>  libc {
> +  GLIBC_2.37 {
> +    __adddf3; __addsf3; __divdf3; __divsf3; __eqdf2; __eqsf2;
> +    __extendsfdf2; __fixdfsi; __fixsfsi;
> +    __fixunsdfsi; __fixunssfsi;
> +    __floatsidf; __floatsisf;
> +    __gedf2; __gesf2; __ledf2; __lesf2; __muldf3; __mulsf3;
> +    __negdf2; __negsf2; __subdf3; __subsf3; __truncdfsf2;
> +  }

I'd tend to expect you also to have the symbols that powerpc-nofpu has at 
GLIBC_2.4 version.

    __floatundidf; __floatundisf;
    __floatunsidf; __floatunsisf;
    __unorddf2; __unordsf2;
    __nedf2; __nesf2;
    __gtdf2; __gtsf2;
    __ltdf2; __ltsf2;

Also, as LoongArch uses binary128 long double, I'd expect all the TFmode 
symbols as well.  And as a 64-bit architecture, I'd expect TImode symbols 
(conversions between floating modes and 128-bit signed and unsigned 
integers, in both directions) as well.
diff mbox series

Patch

diff --git a/sysdeps/loongarch/fpu/fclrexcpt.c b/sysdeps/loongarch/fpu/fclrexcpt.c
index 4301b1fd68..6ed9989760 100644
--- a/sysdeps/loongarch/fpu/fclrexcpt.c
+++ b/sysdeps/loongarch/fpu/fclrexcpt.c
@@ -17,7 +17,6 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
-#include <fenv_libc.h>
 #include <fpu_control.h>
 
 int
diff --git a/sysdeps/loongarch/fpu/fedisblxcpt.c b/sysdeps/loongarch/fpu/fedisblxcpt.c
index a3f92f108d..5563e51d28 100644
--- a/sysdeps/loongarch/fpu/fedisblxcpt.c
+++ b/sysdeps/loongarch/fpu/fedisblxcpt.c
@@ -17,7 +17,6 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
-#include <fenv_libc.h>
 #include <fpu_control.h>
 
 int
@@ -28,7 +27,7 @@  fedisableexcept (int excepts)
   /* Get the current control word.  */
   _FPU_GETCW (new_exc);
 
-  old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT;
+  old_exc = (new_exc & _FPU_ENABLE_MASK) << ENABLE_SHIFT;
 
   excepts &= FE_ALL_EXCEPT;
 
diff --git a/sysdeps/loongarch/fpu/feenablxcpt.c b/sysdeps/loongarch/fpu/feenablxcpt.c
index 9b415f09b7..84dc49db2a 100644
--- a/sysdeps/loongarch/fpu/feenablxcpt.c
+++ b/sysdeps/loongarch/fpu/feenablxcpt.c
@@ -17,7 +17,6 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
-#include <fenv_libc.h>
 #include <fpu_control.h>
 
 int
@@ -28,7 +27,7 @@  feenableexcept (int excepts)
   /* Get the current control word.  */
   _FPU_GETCW (new_exc);
 
-  old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT;
+  old_exc = (new_exc & _FPU_ENABLE_MASK) << ENABLE_SHIFT;
 
   excepts &= FE_ALL_EXCEPT;
 
diff --git a/sysdeps/loongarch/fpu/fegetexcept.c b/sysdeps/loongarch/fpu/fegetexcept.c
index a57543fcd3..32ad3332ab 100644
--- a/sysdeps/loongarch/fpu/fegetexcept.c
+++ b/sysdeps/loongarch/fpu/fegetexcept.c
@@ -17,7 +17,6 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <fenv.h>
-#include <fenv_libc.h>
 #include <fpu_control.h>
 
 int
@@ -28,5 +27,5 @@  fegetexcept (void)
   /* Get the current control word.  */
   _FPU_GETCW (exc);
 
-  return (exc & ENABLE_MASK) << ENABLE_SHIFT;
+  return (exc & _FPU_ENABLE_MASK) << ENABLE_SHIFT;
 }
diff --git a/sysdeps/loongarch/fpu_control.h b/sysdeps/loongarch/fpu_control.h
index 54add4e01c..5a8148e781 100644
--- a/sysdeps/loongarch/fpu_control.h
+++ b/sysdeps/loongarch/fpu_control.h
@@ -51,10 +51,25 @@ 
 
 #include <features.h>
 
+#define _FPU_DEFAULT 0x0
+#define _FPU_IEEE 0x1F
+/* Mask for rounding control/enable/cause fields.  */
+#define _FPU_RC_MASK 0x300
+#define _FPU_ENABLE_MASK 0x0000001f
+#define _FPU_CAUSE_MASK  0x1f000000
+/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits.  */
+#define ENABLE_SHIFT 16
+#define CAUSE_SHIFT 8
+/* Masks for interrupts.  */
+#define _FPU_MASK_V 0x10 /* Invalid operation */
+#define _FPU_MASK_Z 0x08 /* Division by zero  */
+#define _FPU_MASK_O 0x04 /* Overflow */
+#define _FPU_MASK_U 0x02 /* Underflow */
+#define _FPU_MASK_I 0x01 /* Inexact operation */
+
 #ifdef __loongarch_soft_float
 
 #define _FPU_RESERVED 0xffffffff
-#define _FPU_DEFAULT 0x00000000
 typedef unsigned int fpu_control_t;
 #define _FPU_GETCW(cw) (cw) = 0
 #define _FPU_SETCW(cw) (void) (cw)
@@ -62,13 +77,6 @@  extern fpu_control_t __fpu_control;
 
 #else /* __loongarch_soft_float */
 
-/* Masks for interrupts.  */
-#define _FPU_MASK_V 0x10 /* Invalid operation */
-#define _FPU_MASK_Z 0x08 /* Division by zero  */
-#define _FPU_MASK_O 0x04 /* Overflow */
-#define _FPU_MASK_U 0x02 /* Underflow */
-#define _FPU_MASK_I 0x01 /* Inexact operation */
-
 /* Flush denormalized numbers to zero.  */
 #define _FPU_FLUSH_TZ 0x1000000
 
@@ -77,14 +85,9 @@  extern fpu_control_t __fpu_control;
 #define _FPU_RC_ZERO 0x100
 #define _FPU_RC_UP 0x200
 #define _FPU_RC_DOWN 0x300
-/* Mask for rounding control.  */
-#define _FPU_RC_MASK 0x300
 
 #define _FPU_RESERVED 0x0
 
-#define _FPU_DEFAULT 0x0
-#define _FPU_IEEE 0x1F
-
 /* Type of the control word.  */
 typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
 
diff --git a/sysdeps/loongarch/math_private.h b/sysdeps/loongarch/math_private.h
index 40cd54c8cf..a2708a4af8 100644
--- a/sysdeps/loongarch/math_private.h
+++ b/sysdeps/loongarch/math_private.h
@@ -27,7 +27,6 @@ 
 #ifdef __loongarch_hard_float
 
 #include <fenv.h>
-#include <fenv_libc.h>
 #include <fpu_control.h>
 
 #define _FPU_MASK_ALL \
diff --git a/sysdeps/loongarch/nofpu/Makefile b/sysdeps/loongarch/nofpu/Makefile
new file mode 100644
index 0000000000..53b015c3dc
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/Makefile
@@ -0,0 +1,10 @@ 
+# Makefile fragment for LoongArch with no FPU.
+
+ifeq ($(subdir),soft-fp)
+sysdep_routines += $(gcc-single-routines) $(gcc-double-routines) \
+		   sim-full
+endif
+
+ifeq ($(subdir),math)
+CPPFLAGS += -I../soft-fp/
+endif
diff --git a/sysdeps/loongarch/nofpu/Subdirs b/sysdeps/loongarch/nofpu/Subdirs
new file mode 100644
index 0000000000..87eadf3024
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/Subdirs
@@ -0,0 +1 @@ 
+soft-fp
diff --git a/sysdeps/loongarch/nofpu/Versions b/sysdeps/loongarch/nofpu/Versions
new file mode 100644
index 0000000000..6d7f6aae6c
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/Versions
@@ -0,0 +1,5 @@ 
+libc {
+  GLIBC_PRIVATE {
+    __sim_cw_thread;
+  }
+}
diff --git a/sysdeps/loongarch/nofpu/fclrexcpt.c b/sysdeps/loongarch/nofpu/fclrexcpt.c
new file mode 100644
index 0000000000..2938331a09
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fclrexcpt.c
@@ -0,0 +1,37 @@ 
+/* Clear floating-point exceptions (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+feclearexcept (int excepts)
+{
+  /* Mask out unsupported bits/exceptions.  */
+  excepts &= FE_ALL_EXCEPT;
+
+  /* Clear exception flag bits and cause bits.  If the cause bit is not
+     cleared, the next CTC instruction (just below) will re-generate the
+     exception.  */
+
+  __sim_cw_thread &= ~(excepts | (excepts << CAUSE_SHIFT));
+
+  return 0;
+}
+
+libm_hidden_weak (feclearexcept)
diff --git a/sysdeps/loongarch/fpu/fenv_libc.h b/sysdeps/loongarch/nofpu/fedisblxcpt.c
similarity index 62%
rename from sysdeps/loongarch/fpu/fenv_libc.h
rename to sysdeps/loongarch/nofpu/fedisblxcpt.c
index 639e0b16b2..293b530461 100644
--- a/sysdeps/loongarch/fpu/fenv_libc.h
+++ b/sysdeps/loongarch/nofpu/fedisblxcpt.c
@@ -1,5 +1,5 @@ 
-/* Internal libc stuff for floating point environment routines.
-   Copyright (C) 2022-2024 Free Software Foundation, Inc.
+/* Disable exceptions (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,15 +16,17 @@ 
    License along with the GNU C Library.  If not, see
    <https://www.gnu.org/licenses/>.  */
 
-#ifndef _FENV_LIBC_H
-#define _FENV_LIBC_H 1
+#include "soft-fp.h"
+#include "soft-supp.h"
 
-/* Mask for enabling exceptions and for the CAUSE bits.  */
-#define ENABLE_MASK 0x0000001FU
-#define CAUSE_MASK 0x1F000000U
+int
+fedisableexcept (int excepts)
+{
+  unsigned int old_exc = (__sim_cw_thread & _FPU_ENABLE_MASK) << ENABLE_SHIFT;
 
-/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits.  */
-#define ENABLE_SHIFT 16
-#define CAUSE_SHIFT 8
+  excepts &= FE_ALL_EXCEPT;
 
-#endif /* _FENV_LIBC_H */
+  __sim_cw_thread &= ~(excepts >> ENABLE_SHIFT);
+
+  return old_exc;
+}
diff --git a/sysdeps/loongarch/nofpu/feenablxcpt.c b/sysdeps/loongarch/nofpu/feenablxcpt.c
new file mode 100644
index 0000000000..8dfbe371ea
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/feenablxcpt.c
@@ -0,0 +1,32 @@ 
+/* Enable exceptions (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+feenableexcept (int excepts)
+{
+  int old_exc = (__sim_cw_thread & _FPU_ENABLE_MASK) << ENABLE_SHIFT;
+
+  excepts &= FE_ALL_EXCEPT;
+
+  __sim_cw_thread |= excepts >> ENABLE_SHIFT;
+
+  return old_exc;
+}
diff --git a/sysdeps/loongarch/nofpu/fegetenv.c b/sysdeps/loongarch/nofpu/fegetenv.c
new file mode 100644
index 0000000000..7bccaf0250
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fegetenv.c
@@ -0,0 +1,32 @@ 
+/* Store current floating-point environment (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+__fegetenv (fenv_t *envp)
+{
+
+  envp->__fp_control_register = __sim_cw_thread;
+
+  return 0;
+}
+
+libm_hidden_def (__fegetenv) weak_alias (__fegetenv, fegetenv)
+libm_hidden_weak (fegetenv)
diff --git a/sysdeps/loongarch/nofpu/fegetexcept.c b/sysdeps/loongarch/nofpu/fegetexcept.c
new file mode 100644
index 0000000000..fab16a6485
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fegetexcept.c
@@ -0,0 +1,26 @@ 
+/* Get floating-point exceptions (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+fegetexcept (void)
+{
+  return (__sim_cw_thread & _FPU_ENABLE_MASK) << ENABLE_SHIFT;
+}
diff --git a/sysdeps/loongarch/nofpu/fegetmode.c b/sysdeps/loongarch/nofpu/fegetmode.c
new file mode 100644
index 0000000000..7751fe86a0
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fegetmode.c
@@ -0,0 +1,27 @@ 
+/* Store current floating-point control modes (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+fegetmode (femode_t *modep)
+{
+  *modep = __sim_cw_thread;
+  return 0;
+}
diff --git a/sysdeps/loongarch/nofpu/fegetround.c b/sysdeps/loongarch/nofpu/fegetround.c
new file mode 100644
index 0000000000..db440c1707
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fegetround.c
@@ -0,0 +1,29 @@ 
+/* Return current rounding mode (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+__fegetround (void)
+{
+  return __sim_cw_thread & _FPU_RC_MASK;
+}
+
+libm_hidden_def (__fegetround) weak_alias (__fegetround, fegetround)
+libm_hidden_weak (fegetround)
diff --git a/sysdeps/loongarch/nofpu/feholdexcpt.c b/sysdeps/loongarch/nofpu/feholdexcpt.c
new file mode 100644
index 0000000000..bbf106f41e
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/feholdexcpt.c
@@ -0,0 +1,37 @@ 
+/* Store current floating-point environment and clear exceptions
+   (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+__feholdexcept (fenv_t *envp)
+{
+
+  envp->__fp_control_register = __sim_cw_thread;
+
+  /* Clear all exception enable bits and flags.  */
+  __sim_cw_thread &= ~(_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O | _FPU_MASK_U
+		      | _FPU_MASK_I | FE_ALL_EXCEPT);
+
+  return 0;
+}
+
+libm_hidden_def (__feholdexcept) weak_alias (__feholdexcept, feholdexcept)
+libm_hidden_weak (feholdexcept)
diff --git a/sysdeps/loongarch/nofpu/fesetenv.c b/sysdeps/loongarch/nofpu/fesetenv.c
new file mode 100644
index 0000000000..31fd258cdb
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fesetenv.c
@@ -0,0 +1,37 @@ 
+/* Set floating point environment (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+__fesetenv (const fenv_t *envp)
+{
+
+  if (envp == FE_DFL_ENV)
+    __sim_cw_thread = _FPU_DEFAULT;
+  else if (envp == FE_NOMASK_ENV)
+    __sim_cw_thread = _FPU_IEEE;
+  else
+    __sim_cw_thread = envp->__fp_control_register;
+
+  return 0;
+}
+
+libm_hidden_def (__fesetenv) weak_alias (__fesetenv, fesetenv)
+libm_hidden_weak (fesetenv)
diff --git a/sysdeps/loongarch/nofpu/fesetexcept.c b/sysdeps/loongarch/nofpu/fesetexcept.c
new file mode 100644
index 0000000000..bceff28844
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fesetexcept.c
@@ -0,0 +1,27 @@ 
+/* Set given exception flags (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+fesetexcept (int excepts)
+{
+  __sim_cw_thread |= excepts & FE_ALL_EXCEPT;
+  return 0;
+}
diff --git a/sysdeps/loongarch/nofpu/fesetmode.c b/sysdeps/loongarch/nofpu/fesetmode.c
new file mode 100644
index 0000000000..185c97372b
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fesetmode.c
@@ -0,0 +1,34 @@ 
+/* Install given floating-point control modes (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+#define FCSR_STATUS 0x1f1f0000
+
+int
+fesetmode (const femode_t *modep)
+{
+  __sim_cw_thread &= FCSR_STATUS;
+  if (modep == FE_DFL_MODE)
+    __sim_cw_thread |= _FPU_DEFAULT;
+  else
+    __sim_cw_thread |= *modep & ~FCSR_STATUS;
+
+  return 0;
+}
diff --git a/sysdeps/loongarch/nofpu/fesetround.c b/sysdeps/loongarch/nofpu/fesetround.c
new file mode 100644
index 0000000000..6b16ce0828
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fesetround.c
@@ -0,0 +1,36 @@ 
+/* Set rounding mode (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+__fesetround (int round)
+{
+  if ((round & ~_FPU_RC_MASK) != 0)
+    /* ROUND is no valid rounding mode.  */
+    return 1;
+
+  /* Set rounding bits.  */
+  __sim_cw_thread &= ~_FPU_RC_MASK;
+  __sim_cw_thread |= round;
+
+  return 0;
+}
+libm_hidden_def (__fesetround) weak_alias (__fesetround, fesetround)
+libm_hidden_weak (fesetround)
diff --git a/sysdeps/loongarch/nofpu/feupdateenv.c b/sysdeps/loongarch/nofpu/feupdateenv.c
new file mode 100644
index 0000000000..1f7c1c475f
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/feupdateenv.c
@@ -0,0 +1,43 @@ 
+/* Install given floating-point environment and raise exceptions
+   (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+#include <signal.h>
+
+int
+__feupdateenv (const fenv_t *envp)
+{
+  int temp;
+
+  temp = __sim_cw_thread & 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 (temp);
+
+  return 0;
+}
+
+libm_hidden_def (__feupdateenv) weak_alias (__feupdateenv, feupdateenv)
+libm_hidden_weak (feupdateenv)
diff --git a/sysdeps/loongarch/nofpu/fgetexcptflg.c b/sysdeps/loongarch/nofpu/fgetexcptflg.c
new file mode 100644
index 0000000000..dd16932966
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fgetexcptflg.c
@@ -0,0 +1,28 @@ 
+/* Store current representation for exceptions (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+fegetexceptflag (fexcept_t *flagp, int excepts)
+{
+  *flagp = (fexcept_t) __sim_cw_thread & excepts & FE_ALL_EXCEPT;
+
+  return 0;
+}
diff --git a/sysdeps/loongarch/nofpu/fraiseexcpt.c b/sysdeps/loongarch/nofpu/fraiseexcpt.c
new file mode 100644
index 0000000000..b701da1f86
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fraiseexcpt.c
@@ -0,0 +1,42 @@ 
+/* Raise given exceptions (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+#include <signal.h>
+
+int
+__feraiseexcept (int excepts)
+{
+  int enable;
+  /* Set flag bits (which are accumulative), and *also* set the
+     cause bits.  The setting of the cause bits is what actually causes
+     the hardware to generate the exception, if the corresponding enable
+     bit is set as well.  */
+
+  excepts &= FE_ALL_EXCEPT;
+  __sim_cw_thread |= excepts | (excepts << CAUSE_SHIFT);
+  enable = __sim_cw_thread & _FPU_ENABLE_MASK;
+  if (excepts & __sim_cw_thread & (enable << ENABLE_SHIFT))
+    raise (SIGFPE);
+
+  return 0;
+}
+
+libm_hidden_def (__feraiseexcept) weak_alias (__feraiseexcept, feraiseexcept)
+libm_hidden_weak (feraiseexcept)
diff --git a/sysdeps/loongarch/nofpu/fsetexcptflg.c b/sysdeps/loongarch/nofpu/fsetexcptflg.c
new file mode 100644
index 0000000000..cd7dd18b9c
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/fsetexcptflg.c
@@ -0,0 +1,35 @@ 
+/* Set floating-point environment exception handling (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+fesetexceptflag (const fexcept_t *flagp, int excepts)
+{
+  /* Make sure the flags we want restored are legal.  */
+  excepts &= FE_ALL_EXCEPT;
+
+  /* Now clear the bits called for, and copy them in from flagp.  Note that
+     we ignore all non-flag bits from *flagp, so they don't matter.  */
+  __sim_cw_thread = (__sim_cw_thread & ~excepts) | (*flagp & excepts);
+
+
+  /* Success.  */
+  return 0;
+}
diff --git a/sysdeps/loongarch/nofpu/ftestexcept.c b/sysdeps/loongarch/nofpu/ftestexcept.c
new file mode 100644
index 0000000000..549661c88d
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/ftestexcept.c
@@ -0,0 +1,27 @@ 
+/* Test floating-point exceptions (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-fp.h"
+#include "soft-supp.h"
+
+int
+fetestexcept (int excepts)
+{
+  return __sim_cw_thread & excepts & FE_ALL_EXCEPT;
+}
+libm_hidden_def (fetestexcept)
diff --git a/sysdeps/loongarch/nofpu/get-rounding-mode.h b/sysdeps/loongarch/nofpu/get-rounding-mode.h
new file mode 100644
index 0000000000..a4808cc54e
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/get-rounding-mode.h
@@ -0,0 +1,34 @@ 
+/* Determine floating-point rounding mode within libc (soft-float edition).
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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/>.  */
+
+#ifndef _LOONGARCH_NOFPU_GET_ROUNDING_MODE_H
+#define _LOONGARCH_NOFPU_GET_ROUNDING_MODE_H	1
+
+#include <fenv.h>
+#include <fpu_control.h>
+#include "soft-supp.h"
+
+/* Return the floating-point rounding mode.  */
+
+static inline int
+get_rounding_mode (void)
+{
+  return __sim_cw_thread & _FPU_RC_MASK;
+}
+
+#endif /* get-rounding-mode.h */
diff --git a/sysdeps/loongarch/nofpu/sim-full.c b/sysdeps/loongarch/nofpu/sim-full.c
new file mode 100644
index 0000000000..a2bbb9f880
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/sim-full.c
@@ -0,0 +1,23 @@ 
+/* Software floating-point exception handling emulation.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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 "soft-supp.h"
+
+/* By default, no exceptions should trap.  */
+__thread int __sim_cw_thread;
+libc_hidden_tls_def (__sim_cw_thread);
diff --git a/sysdeps/loongarch/nofpu/soft-supp.h b/sysdeps/loongarch/nofpu/soft-supp.h
new file mode 100644
index 0000000000..37d83399e8
--- /dev/null
+++ b/sysdeps/loongarch/nofpu/soft-supp.h
@@ -0,0 +1,20 @@ 
+/* Internal support stuff for complete soft float.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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/>.  */
+
+extern __thread int __sim_cw_thread attribute_tls_model_ie;
+libc_hidden_tls_proto (__sim_cw_thread, tls_model ("initial-exec"));