public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Daniel Engel <gnu@danielengel.com>
To: Richard Earnshaw <Richard.Earnshaw@foss.arm.com>,
	gcc-patches@gcc.gnu.org
Cc: Daniel Engel <gnu@danielengel.com>,
	Christophe Lyon <christophe.lyon@linaro.org>
Subject: [PATCH v7 32/34] Import float<->__fp16 conversion from the CM0 library
Date: Mon, 31 Oct 2022 08:45:27 -0700	[thread overview]
Message-ID: <20221031154529.3627576-33-gnu@danielengel.com> (raw)
In-Reply-To: <20221031154529.3627576-1-gnu@danielengel.com>

gcc/libgcc/ChangeLog:
2022-10-09 Daniel Engel <gnu@danielengel.com>

	* config/arm/eabi/fcast.S (__aeabi_h2f, __aeabi_f2h): Added functions.
	* config/arm/fp16 (__gnu_f2h_ieee, __gnu_h2f_ieee, __gnu_f2h_alternative,
	__gnu_h2f_alternative): Disable build for v6m multilibs.
	* config/arm/t-bpabi (LIB1ASMFUNCS): Added _aeabi_f2h_ieee,
	_aeabi_h2f_ieee, _aeabi_f2h_alt, and _aeabi_h2f_alt (v6m only).
---
 libgcc/config/arm/eabi/fcast.S | 277 +++++++++++++++++++++++++++++++++
 libgcc/config/arm/fp16.c       |   4 +
 libgcc/config/arm/t-bpabi      |   7 +
 3 files changed, 288 insertions(+)

diff --git a/libgcc/config/arm/eabi/fcast.S b/libgcc/config/arm/eabi/fcast.S
index f0d1373d31a..09876a95767 100644
--- a/libgcc/config/arm/eabi/fcast.S
+++ b/libgcc/config/arm/eabi/fcast.S
@@ -254,3 +254,280 @@ FUNC_END D2F_NAME
 
 #endif /* L_arm_d2f || L_arm_truncdfsf2 */
 
+
+#if defined(L_aeabi_h2f_ieee) || defined(L_aeabi_h2f_alt)
+
+#ifdef L_aeabi_h2f_ieee
+  #define H2F_NAME aeabi_h2f
+  #define H2F_ALIAS gnu_h2f_ieee
+#else
+  #define H2F_NAME aeabi_h2f_alt
+  #define H2F_ALIAS gnu_h2f_alternative
+#endif
+
+// float __aeabi_h2f(short hf)
+// float __aeabi_h2f_alt(short hf)
+// Converts a half-precision float in $r0 to single-precision.
+// Rounding, overflow, and underflow conditions are impossible.
+// In IEEE mode, INF, ZERO, and NAN are returned unmodified.
+FUNC_START_SECTION H2F_NAME .text.sorted.libgcc.h2f
+FUNC_ALIAS H2F_ALIAS H2F_NAME
+    CFI_START_FUNCTION
+
+        // Set up registers for __fp_normalize2().
+        push    { rT, lr }
+                .cfi_remember_state
+                .cfi_adjust_cfa_offset 8
+                .cfi_rel_offset rT, 0
+                .cfi_rel_offset lr, 4
+
+        // Save the mantissa and exponent.
+        lsls    r2,     r0,     #17
+
+        // Isolate the sign.
+        lsrs    r0,     #15
+        lsls    r0,     #31
+
+        // Align the exponent at bit[24] for normalization.
+        // If zero, return the original sign.
+        lsrs    r2,     #3
+
+      #ifdef __HAVE_FEATURE_IT
+        do_it   eq
+        RETc(eq)
+      #else
+        beq     LLSYM(__h2f_return)
+      #endif
+
+        // Split the exponent and mantissa into separate registers.
+        // This is the most efficient way to convert subnormals in the
+        //  half-precision form into normals in single-precision.
+        // This does add a leading implicit '1' to INF and NAN,
+        //  but that will be absorbed when the value is re-assembled.
+        bl      SYM(__fp_normalize2) __PLT__
+
+   #ifdef L_aeabi_h2f_ieee
+        // Set up the exponent bias.  For INF/NAN values, the bias is 223,
+        //  where the last '1' accounts for the implicit '1' in the mantissa.
+        adds    r2,     #(255 - 31 - 1)
+
+        // Test for INF/NAN.
+        cmp     r2,     #254
+
+      #ifdef __HAVE_FEATURE_IT
+        do_it   ne
+      #else
+        beq     LLSYM(__h2f_assemble)
+      #endif
+
+        // For normal values, the bias should have been 111.
+        // However, this offset must be adjusted per the INF check above.
+     IT(sub,ne) r2,     #((255 - 31 - 1) - (127 - 15 - 1))
+
+    #else /* L_aeabi_h2f_alt */
+        // Set up the exponent bias.  All values are normal.
+        adds    r2,     #(127 - 15 - 1)
+    #endif
+
+    LLSYM(__h2f_assemble):
+        // Combine exponent and sign.
+        lsls    r2,     #23
+        adds    r0,     r2
+
+        // Combine mantissa.
+        lsrs    r3,     #8
+        add     r0,     r3
+
+    LLSYM(__h2f_return):
+        pop     { rT, pc }
+                .cfi_restore_state
+
+    CFI_END_FUNCTION
+FUNC_END H2F_NAME
+FUNC_END H2F_ALIAS
+
+#endif /* L_aeabi_h2f_ieee || L_aeabi_h2f_alt */
+
+
+#if defined(L_aeabi_f2h_ieee) || defined(L_aeabi_f2h_alt)
+
+#ifdef L_aeabi_f2h_ieee
+  #define F2H_NAME aeabi_f2h
+  #define F2H_ALIAS gnu_f2h_ieee
+#else
+  #define F2H_NAME aeabi_f2h_alt
+  #define F2H_ALIAS gnu_f2h_alternative
+#endif
+
+// short __aeabi_f2h(float f)
+// short __aeabi_f2h_alt(float f)
+// Converts a single-precision float in $r0 to half-precision,
+//  rounding to nearest, ties to even.
+// Values out of range are forced to either ZERO or INF.
+// In IEEE mode, the upper 12 bits of a NAN will be preserved.
+FUNC_START_SECTION F2H_NAME .text.sorted.libgcc.f2h
+FUNC_ALIAS F2H_ALIAS F2H_NAME
+    CFI_START_FUNCTION
+
+        // Set up the sign.
+        lsrs    r2,     r0,     #31
+        lsls    r2,     #15
+
+        // Save the exponent and mantissa.
+        // If ZERO, return the original sign.
+        lsls    r0,     #1
+
+      #ifdef __HAVE_FEATURE_IT
+        do_it   ne,t
+        addne   r0,     r2
+        RETc(ne)
+      #else
+        beq     LLSYM(__f2h_return)
+      #endif
+
+        // Isolate the exponent.
+        lsrs    r1,     r0,     #24
+
+  #ifdef L_aeabi_f2h_ieee
+        // Check for NAN.
+        cmp     r1,     #255
+        beq     LLSYM(__f2h_indefinite)
+
+        // Check for overflow.
+        cmp     r1,     #(127 + 15)
+        bhi     LLSYM(__f2h_overflow)
+
+  #else /* L_aeabi_f2h_alt */
+        // Detect overflow.
+        subs    r1,     #(127 + 16)
+        rsbs    r3,     r1,     $0
+        asrs    r3,     #31
+
+        // Saturate the mantissa on overflow.
+        bics    r0,     r3
+        lsrs    r3,     #17
+	orrs    r0,     r3
+        bcs     LLSYM(__f2h_return)
+
+  #endif /* L_aeabi_f2h_alt */
+
+        // Isolate the mantissa, adding back the implicit '1'.
+        lsls    r0,     #8
+        adds    r0,     #1
+        rors    r0,     r0
+
+        // Adjust exponent bias for half-precision, including '1' to
+        //  account for the mantissa's implicit '1'.
+      #ifdef L_aeabi_f2h_ieee
+        subs    r1,     #(127 - 15 + 1)
+      #else
+        adds    r1,     #((127 + 16) - (127 - 15 + 1))
+      #endif
+
+        bmi     LLSYM(__f2h_underflow)
+
+        // This next part is delicate.  The rouncing check requires a scratch
+        //  register, but the sign can't be merged in until after the final
+        //  overflow check below. Prepare the exponent.
+        // The mantissa and exponent can be combined, but the exponent
+        //  must be prepared now while the flags don't matter.
+        lsls    r1,     #10
+
+        // Split the mantissa (11 bits) and remainder (13 bits).
+        lsls    r3,     r0,     #12
+        lsrs    r0,     #21
+
+        // Combine mantissa and exponent without affecting flags.
+        add     r0,     r1
+
+     LLSYM(__f2h_round):
+        // If the carry bit is '0', always round down.
+      #ifdef __HAVE_FEATURE_IT
+        do_it   cs,t
+        addcs   r0,     r2
+        RETc(cs)
+      #else
+        bcc     LLSYM(__f2h_return)
+      #endif
+
+        // Carry was set.  If a tie (no remainder) and the
+        //  LSB of the result is '0', round down (to even).
+        lsls    r1,     r0,     #31
+        orrs    r1,     r3
+
+      #ifdef __HAVE_FEATURE_IT
+        do_it   ne
+      #else
+        beq     LLSYM(__f2h_return)
+      #endif
+
+        // Round up, ties to even.
+     IT(add,ne) r0,     #1
+
+  #ifndef L_aeabi_f2h_ieee
+        // HACK: The result may overflow to -0 not INF in alt mode.
+        // Subtract overflow to reverse.
+        lsrs    r3,    r0,    #15
+        subs    r0,    r3
+  #endif
+
+     LLSYM(__f2h_return):
+        // Combine mantissa and exponent with the sign.
+        adds    r0,     r2
+        RET
+
+    LLSYM(__f2h_underflow):
+        // Align the remainder. The remainder consists of the last 12 bits
+        //  of the mantissa plus the magnitude of underflow.
+        movs    r3,     r0
+        adds    r1,     #12
+        lsls    r3,     r1
+
+        // Align the mantissa.  The MSB of the remainder must be
+        // shifted out last into the 'C' flag for rounding.
+        subs    r1,     #33
+        rsbs    r1,     #0
+        lsrs    r0,     r1
+        b       LLSYM(__f2h_round)
+
+  #ifdef L_aeabi_f2h_ieee
+    LLSYM(__f2h_overflow):
+        // Create single-precision INF from which to construct half-precision.
+        movs    r0,     #255
+        lsls    r0,     #24
+
+    LLSYM(__f2h_indefinite):
+        // Check for INF.
+        lsls    r3,     r0,     #8
+
+      #ifdef __HAVE_FEATURE_IT
+        do_it   ne,t
+      #else
+        beq     LLSYM(__f2h_infinite)
+      #endif
+
+        // HACK: The ARM specification states "the least significant 13 bits
+        //  of a NAN are lost in the conversion." But what happens when the
+        //  NAN-ness of the value resides in these 13 bits?
+        // Set bit[8] to ensure NAN without changing bit[9] (quiet).
+     IT(add,ne) r2,     #128
+     IT(add,ne) r2,     #128
+
+    LLSYM(__f2h_infinite):
+        // Construct the result from the upper 11 bits of the mantissa
+        //  and the lower 5 bits of the exponent.
+        lsls    r0,     #3
+        lsrs    r0,     #17
+
+        // Combine with the sign (and possibly NAN flag).
+        orrs    r0,     r2
+        RET
+
+  #endif /* L_aeabi_f2h_ieee */
+
+    CFI_END_FUNCTION
+FUNC_END F2H_NAME
+FUNC_END F2H_ALIAS
+
+#endif  /* L_aeabi_f2h_ieee || L_aeabi_f2h_alt */
+
diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index 39004a4fe1f..afde9a97d57 100644
--- a/libgcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
@@ -198,6 +198,8 @@ __gnu_h2f_internal(unsigned short a, int ieee)
   return sign | (((aexp + 0x70) << 23) + (mantissa << 13));
 }
 
+#if (__ARM_ARCH_ISA_ARM) || (__ARM_ARCH_ISA_THUMB > 1)
+
 unsigned short
 __gnu_f2h_ieee(unsigned int a)
 {
@@ -222,6 +224,8 @@ __gnu_h2f_alternative(unsigned short a)
   return __gnu_h2f_internal(a, 0);
 }
 
+#endif /* NOT_ISA_TARGET_32BIT */
+
 unsigned short
 __gnu_d2h_ieee (unsigned long long a)
 {
diff --git a/libgcc/config/arm/t-bpabi b/libgcc/config/arm/t-bpabi
index 86234d5676f..1b1ecfc638e 100644
--- a/libgcc/config/arm/t-bpabi
+++ b/libgcc/config/arm/t-bpabi
@@ -1,6 +1,13 @@
 # Add the bpabi.S functions.
 LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
 
+# Only enabled for v6m.
+ARM_ISA:=$(findstring __ARM_ARCH_ISA_ARM,$(shell $(gcc_compile_bare) -dM -E - </dev/null))
+THUMB1_ISA:=$(findstring __ARM_ARCH_ISA_THUMB 1,$(shell $(gcc_compile_bare) -dM -E - </dev/null))
+ifeq (__ARM_ARCH_ISA_THUMB 1,$(ARM_ISA)$(THUMB1_ISA))
+LIB1ASMFUNCS += _aeabi_f2h_ieee _aeabi_h2f_ieee _aeabi_f2h_alt _aeabi_h2f_alt
+endif
+
 # Add the BPABI C functions.
 LIB2ADD += $(srcdir)/config/arm/unaligned-funcs.c
 
-- 
2.34.1


  parent reply	other threads:[~2022-10-31 15:49 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-31 15:44 [PATCH v7 00/34] libgcc: Thumb-1 Floating-Point Assembly for Cortex M0 Daniel Engel
2022-10-31 15:44 ` [PATCH v7 01/34] Add and restructure function declaration macros Daniel Engel
2022-10-31 15:44 ` [PATCH v7 02/34] Rename THUMB_FUNC_START to THUMB_FUNC_ENTRY Daniel Engel
2022-10-31 15:44 ` [PATCH v7 03/34] Fix syntax warnings on conditional instructions Daniel Engel
2022-10-31 15:44 ` [PATCH v7 04/34] Reorganize LIB1ASMFUNCS object wrapper macros Daniel Engel
2022-10-31 15:45 ` [PATCH v7 05/34] Add the __HAVE_FEATURE_IT and IT() macros Daniel Engel
2022-10-31 15:45 ` [PATCH v7 06/34] Refactor 'clz' functions into a new file Daniel Engel
2022-10-31 15:45 ` [PATCH v7 07/34] Refactor 'ctz' " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 08/34] Refactor 64-bit shift " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 09/34] Import 'clz' functions from the CM0 library Daniel Engel
2022-10-31 15:45 ` [PATCH v7 10/34] Import 'ctz' " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 11/34] Import 64-bit shift " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 12/34] Import 'clrsb' " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 13/34] Import 'ffs' " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 14/34] Import 'parity' " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 15/34] Import 'popcnt' " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 16/34] Refactor Thumb-1 64-bit comparison into a new file Daniel Engel
2022-10-31 15:45 ` [PATCH v7 17/34] Import 64-bit comparison from CM0 library Daniel Engel
2022-10-31 15:45 ` [PATCH v7 18/34] Merge Thumb-2 optimizations for 64-bit comparison Daniel Engel
2022-10-31 15:45 ` [PATCH v7 19/34] Import 32-bit division from the CM0 library Daniel Engel
2022-10-31 15:45 ` [PATCH v7 20/34] Refactor Thumb-1 64-bit division into a new file Daniel Engel
2022-10-31 15:45 ` [PATCH v7 21/34] Import 64-bit division from the CM0 library Daniel Engel
2022-10-31 15:45 ` [PATCH v7 22/34] Import integer multiplication " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 23/34] Refactor Thumb-1 float comparison into a new file Daniel Engel
2022-10-31 15:45 ` [PATCH v7 24/34] Import float comparison from the CM0 library Daniel Engel
2022-10-31 15:45 ` [PATCH v7 25/34] Refactor Thumb-1 float subtraction into a new file Daniel Engel
2022-10-31 15:45 ` [PATCH v7 26/34] Import float addition and subtraction from the CM0 library Daniel Engel
2022-10-31 15:45 ` [PATCH v7 27/34] Import float multiplication " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 28/34] Import float division " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 29/34] Import integer-to-float conversion " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 30/34] Import float-to-integer " Daniel Engel
2022-10-31 15:45 ` [PATCH v7 31/34] Import float<->double " Daniel Engel
2022-10-31 15:45 ` Daniel Engel [this message]
2022-10-31 15:45 ` [PATCH v7 33/34] Drop single-precision Thumb-1 soft-float functions Daniel Engel
2022-10-31 15:45 ` [PATCH v7 34/34] Add -mpure-code support to the CM0 functions Daniel Engel
2022-11-15 15:27 ` [PING] Re: [PATCH v7 00/34] libgcc: Thumb-1 Floating-Point Assembly for Cortex M0 Daniel Engel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221031154529.3627576-33-gnu@danielengel.com \
    --to=gnu@danielengel.com \
    --cc=Richard.Earnshaw@foss.arm.com \
    --cc=christophe.lyon@linaro.org \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).