mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [PATCH v3] aarch64: rewrite fenv routines in C using inline asm
@ 2026-01-29 21:43 Bill Roberts
  2026-01-29 21:57 ` Michael Morrell
  0 siblings, 1 reply; 4+ messages in thread
From: Bill Roberts @ 2026-01-29 21:43 UTC (permalink / raw)
  To: musl; +Cc: dalias, dalias, Bill Roberts

Rewrite the AArch64 floating-point environment routines (fegetround,
__fesetround, fetestexcept, feclearexcept, feraiseexcept, fegetenv,
fesetenv) from assembly into C implementations using inline assembly.

This change eliminates the need for handwritten function prologues and
epilogues in fenv.s, which simplifies maintenance and allows the compiler
to automatically insert architecture features such as BTI landing pads and
pointer authentication (PAC) sequences where applicable.

The new implementations mirror the original assembly semantics exactly:
- access FPCR/FPSR using `mrs`/`msr` inline asm
- preserve the same FE_* masks and return conventions
- retain `__fesetround` as a hidden internal symbol
- support the special FE_DFL_ENV case in fesetenv

Moving to C also enables the compiler to manage register allocation,
stack usage, and ABI compliance automatically while keeping the low-level
behavior (bitmasks and register accesses) explicit and verifiable.

No functional changes intended.

Signed-off-by: Bill Roberts <bill.roberts@arm.com>
---
 Changes since v2:
   - Actually use hidden in features.h :-p

 src/fenv/aarch64/fenv.c | 96 +++++++++++++++++++++++++++++++++++++++++
 src/fenv/aarch64/fenv.s | 68 -----------------------------
 2 files changed, 96 insertions(+), 68 deletions(-)
 create mode 100644 src/fenv/aarch64/fenv.c
 delete mode 100644 src/fenv/aarch64/fenv.s

diff --git a/src/fenv/aarch64/fenv.c b/src/fenv/aarch64/fenv.c
new file mode 100644
index 00000000..86632c0a
--- /dev/null
+++ b/src/fenv/aarch64/fenv.c
@@ -0,0 +1,96 @@
+#include <features.h>
+#include <fenv.h>
+#include <stdint.h>
+
+#define FE_RMODE_MASK 0x00C00000u  // FPCR RMode bits [23:22]
+#define FE_EXC_MASK   0x0000001Fu  // FPSR exception flags [4:0]
+
+static inline uint32_t read_fpcr_u32(void)
+{
+	uint64_t x;
+	__asm__ volatile ("mrs %0, fpcr" : "=r"(x));
+	return (uint32_t)x;
+}
+
+static inline void write_fpcr_u32(uint32_t v)
+{
+	uint64_t x = v;
+	__asm__ volatile ("msr fpcr, %0" :: "r"(x) : "memory");
+}
+
+static inline uint32_t read_fpsr_u32(void)
+{
+	uint64_t x;
+	__asm__ volatile ("mrs %0, fpsr" : "=r"(x));
+	return (uint32_t)x;
+}
+
+static inline void write_fpsr_u32(uint32_t v)
+{
+	uint64_t x = v;
+	__asm__ volatile ("msr fpsr, %0" :: "r"(x) : "memory");
+}
+
+int fegetround(void)
+{
+	uint32_t fpcr = read_fpcr_u32();
+	return (int)(fpcr & FE_RMODE_MASK);
+}
+
+hidden int __fesetround(int rm)
+{
+	uint32_t fpcr = read_fpcr_u32();
+	fpcr &= ~FE_RMODE_MASK;
+	fpcr |= (uint32_t)rm;
+	write_fpcr_u32(fpcr);
+	return 0;
+}
+
+int fetestexcept(int mask)
+{
+	uint32_t m   = (uint32_t)mask & FE_EXC_MASK;
+	uint32_t fpsr = read_fpsr_u32();
+	return (int)(m & fpsr);
+}
+
+int feclearexcept(int mask)
+{
+	uint32_t m    = (uint32_t)mask & FE_EXC_MASK;
+	uint32_t fpsr = read_fpsr_u32();
+	fpsr &= ~m;
+	write_fpsr_u32(fpsr);
+	return 0;
+}
+
+int feraiseexcept(int mask)
+{
+	uint32_t m    = (uint32_t)mask & FE_EXC_MASK;
+	uint32_t fpsr = read_fpsr_u32();
+	fpsr |= m;
+	write_fpsr_u32(fpsr);
+	return 0;
+}
+
+int fegetenv(fenv_t *env)
+{
+	uint32_t fpcr = read_fpcr_u32();
+	uint32_t fpsr = read_fpsr_u32();
+	env->__fpcr = fpcr;
+	env->__fpsr = fpsr;
+	return 0;
+}
+
+int fesetenv(const fenv_t *env)
+{
+	uint32_t fpcr = 0;
+	uint32_t fpsr = 0;
+
+	if (env != FE_DFL_ENV) {
+		fpcr = env->__fpcr;
+		fpsr = env->__fpsr;
+	}
+
+	write_fpcr_u32(fpcr);
+	write_fpsr_u32(fpsr);
+	return 0;
+}
diff --git a/src/fenv/aarch64/fenv.s b/src/fenv/aarch64/fenv.s
deleted file mode 100644
index 8f3ec965..00000000
--- a/src/fenv/aarch64/fenv.s
+++ /dev/null
@@ -1,68 +0,0 @@
-.global fegetround
-.type fegetround,%function
-fegetround:
-	mrs x0, fpcr
-	and w0, w0, #0xc00000
-	ret
-
-.global __fesetround
-.hidden __fesetround
-.type __fesetround,%function
-__fesetround:
-	mrs x1, fpcr
-	bic w1, w1, #0xc00000
-	orr w1, w1, w0
-	msr fpcr, x1
-	mov w0, #0
-	ret
-
-.global fetestexcept
-.type fetestexcept,%function
-fetestexcept:
-	and w0, w0, #0x1f
-	mrs x1, fpsr
-	and w0, w0, w1
-	ret
-
-.global feclearexcept
-.type feclearexcept,%function
-feclearexcept:
-	and w0, w0, #0x1f
-	mrs x1, fpsr
-	bic w1, w1, w0
-	msr fpsr, x1
-	mov w0, #0
-	ret
-
-.global feraiseexcept
-.type feraiseexcept,%function
-feraiseexcept:
-	and w0, w0, #0x1f
-	mrs x1, fpsr
-	orr w1, w1, w0
-	msr fpsr, x1
-	mov w0, #0
-	ret
-
-.global fegetenv
-.type fegetenv,%function
-fegetenv:
-	mrs x1, fpcr
-	mrs x2, fpsr
-	stp w1, w2, [x0]
-	mov w0, #0
-	ret
-
-// TODO preserve some bits
-.global fesetenv
-.type fesetenv,%function
-fesetenv:
-	mov x1, #0
-	mov x2, #0
-	cmn x0, #1
-	b.eq 1f
-	ldp w1, w2, [x0]
-1:	msr fpcr, x1
-	msr fpsr, x2
-	mov w0, #0
-	ret
-- 
2.51.0


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

* RE: [musl] [PATCH v3] aarch64: rewrite fenv routines in C using inline asm
  2026-01-29 21:43 [musl] [PATCH v3] aarch64: rewrite fenv routines in C using inline asm Bill Roberts
@ 2026-01-29 21:57 ` Michael Morrell
  2026-01-30  0:40   ` Bill Roberts
  0 siblings, 1 reply; 4+ messages in thread
From: Michael Morrell @ 2026-01-29 21:57 UTC (permalink / raw)
  To: musl@lists.openwall.com; +Cc: dalias@libc.org, dalias@aerifal.cx, Bill Roberts

+static inline uint32_t read_fpcr_u32(void) {
+	uint64_t x;
+	__asm__ volatile ("mrs %0, fpcr" : "=r"(x));
+	return (uint32_t)x;
+}
+
+static inline void write_fpcr_u32(uint32_t v) {
+	uint64_t x = v;
+	__asm__ volatile ("msr fpcr, %0" :: "r"(x) : "memory"); }
+
+static inline uint32_t read_fpsr_u32(void) {
+	uint64_t x;
+	__asm__ volatile ("mrs %0, fpsr" : "=r"(x));
+	return (uint32_t)x;
+}
+
+static inline void write_fpsr_u32(uint32_t v) {
+	uint64_t x = v;
+	__asm__ volatile ("msr fpsr, %0" :: "r"(x) : "memory"); }
+

Shouldn't the ending brace be on its own line for write_fpcr_u32 and write_fpsr_u32?

   Michael


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

* Re: [musl] [PATCH v3] aarch64: rewrite fenv routines in C using inline asm
  2026-01-29 21:57 ` Michael Morrell
@ 2026-01-30  0:40   ` Bill Roberts
  2026-01-30  4:05     ` Markus Wichmann
  0 siblings, 1 reply; 4+ messages in thread
From: Bill Roberts @ 2026-01-30  0:40 UTC (permalink / raw)
  To: musl, Michael Morrell; +Cc: dalias@libc.org, dalias@aerifal.cx, Bill Roberts



On 1/29/26 3:57 PM, Michael Morrell wrote:
> +static inline uint32_t read_fpcr_u32(void) {
> +	uint64_t x;
> +	__asm__ volatile ("mrs %0, fpcr" : "=r"(x));
> +	return (uint32_t)x;
> +}
> +
> +static inline void write_fpcr_u32(uint32_t v) {
> +	uint64_t x = v;
> +	__asm__ volatile ("msr fpcr, %0" :: "r"(x) : "memory"); }
> +
> +static inline uint32_t read_fpsr_u32(void) {
> +	uint64_t x;
> +	__asm__ volatile ("mrs %0, fpsr" : "=r"(x));
> +	return (uint32_t)x;
> +}
> +
> +static inline void write_fpsr_u32(uint32_t v) {
> +	uint64_t x = v;
> +	__asm__ volatile ("msr fpsr, %0" :: "r"(x) : "memory"); }
> +
> 
> Shouldn't the ending brace be on its own line for write_fpcr_u32 and write_fpsr_u32?
> 

Yep, but I don't understand what happened as the patch shown here[1] on 
the mailing list archive looks fine, as well as my local patch. Perhaps 
something mangled it on your end? I also looked to see if any weird 
non-ASCII chars got into the patch, I didn't see any, I see that line 
ending with "; LF + } LF" or "3B 0A 2B 7D 0A" in hex.

1. https://openwall.com/lists/musl/2026/01/29/6

Thanks Michael,

Bill

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

* Re: [musl] [PATCH v3] aarch64: rewrite fenv routines in C using inline asm
  2026-01-30  0:40   ` Bill Roberts
@ 2026-01-30  4:05     ` Markus Wichmann
  0 siblings, 0 replies; 4+ messages in thread
From: Markus Wichmann @ 2026-01-30  4:05 UTC (permalink / raw)
  To: musl; +Cc: Michael Morrell, dalias@libc.org, dalias@aerifal.cx, Bill Roberts

Am Thu, Jan 29, 2026 at 06:40:17PM -0600 schrieb Bill Roberts:
> 
> 
> On 1/29/26 3:57 PM, Michael Morrell wrote:
> > +static inline uint32_t read_fpcr_u32(void) {
> > +	uint64_t x;
> > +	__asm__ volatile ("mrs %0, fpcr" : "=r"(x));
> > +	return (uint32_t)x;
> > +}
> > +
> > +static inline void write_fpcr_u32(uint32_t v) {
> > +	uint64_t x = v;
> > +	__asm__ volatile ("msr fpcr, %0" :: "r"(x) : "memory"); }
> > +
> > +static inline uint32_t read_fpsr_u32(void) {
> > +	uint64_t x;
> > +	__asm__ volatile ("mrs %0, fpsr" : "=r"(x));
> > +	return (uint32_t)x;
> > +}
> > +
> > +static inline void write_fpsr_u32(uint32_t v) {
> > +	uint64_t x = v;
> > +	__asm__ volatile ("msr fpsr, %0" :: "r"(x) : "memory"); }
> > +
> > 
> > Shouldn't the ending brace be on its own line for write_fpcr_u32 and write_fpsr_u32?
> > 
> 
> Yep, but I don't understand what happened as the patch shown here[1] on the
> mailing list archive looks fine, as well as my local patch. Perhaps
> something mangled it on your end? I also looked to see if any weird
> non-ASCII chars got into the patch, I didn't see any, I see that line ending
> with "; LF + } LF" or "3B 0A 2B 7D 0A" in hex.
> 
> 1. https://openwall.com/lists/musl/2026/01/29/6
> 
> Thanks Michael,
> 
> Bill

Can confirm that it is correct in the mail I received. So I guess
Michael's mail toolchain did something weird here.

Ciao,
Markus

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

end of thread, other threads:[~2026-01-30  4:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-29 21:43 [musl] [PATCH v3] aarch64: rewrite fenv routines in C using inline asm Bill Roberts
2026-01-29 21:57 ` Michael Morrell
2026-01-30  0:40   ` Bill Roberts
2026-01-30  4:05     ` Markus Wichmann

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

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 NNTP newsgroup(s).