[RISC-V] Add support for _Bfloat16

1 At point <https://github.com/riscv/riscv-bfloat16>,
  BF16 has already been completed "post public review".

2 LLVM has also added support for RISCV BF16 in
  <https://reviews.llvm.org/D151313> and
  <https://reviews.llvm.org/D150929>.

3 According to the discussion <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/367>,
  this use __bf16 and use DF16b in riscv_mangle_type like x86.

Below test are passed for this patch
    * The riscv fully regression test.

gcc/ChangeLog:

	* config/riscv/iterators.md: New mode iterator HFBF.
	* config/riscv/riscv-builtins.cc (riscv_init_builtin_types):
	Initialize data type _Bfloat16.
	* config/riscv/riscv-modes.def (FLOAT_MODE): New.
	(ADJUST_FLOAT_FORMAT): New.
	* config/riscv/riscv.cc (riscv_mangle_type): Support for BFmode.
	(riscv_scalar_mode_supported_p): Ditto.
	(riscv_libgcc_floating_mode_supported_p): Ditto.
	(riscv_init_libfuncs): Set the conversion method for BFmode and
	HFmode.
	(riscv_block_arith_comp_libfuncs_for_mode): Set the arithmetic
	and comparison libfuncs for the mode.
	* config/riscv/riscv.md (mode" ): Add BF.
	(movhf): Support for BFmode.
	(mov<mode>): Ditto.
	(*movhf_softfloat): Ditto.
	(*mov<mode>_softfloat): Ditto.

libgcc/ChangeLog:

	* config/riscv/sfp-machine.h (_FP_NANFRAC_B): New.
	(_FP_NANSIGN_B): Ditto.
	* config/riscv/t-softfp32: Add support for BF16 libfuncs.
	* config/riscv/t-softfp64: Ditto.
	* soft-fp/floatsibf.c: For si -> bf16.
	* soft-fp/floatunsibf.c: For unsi -> bf16.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/bf16_arithmetic.c: New test.
	* gcc.target/riscv/bf16_call.c: New test.
	* gcc.target/riscv/bf16_comparison.c: New test.
	* gcc.target/riscv/bf16_float_libcall_convert.c: New test.
	* gcc.target/riscv/bf16_integer_libcall_convert.c: New test.

Co-authored-by: Jin Ma <jinma@linux.alibaba.com>
This commit is contained in:
Xiao Zeng 2024-05-06 15:39:12 -06:00 committed by Jeff Law
parent 6ffea3e373
commit 8c7cee80eb
15 changed files with 409 additions and 38 deletions

View File

@ -75,6 +75,8 @@
;; Iterator for floating-point modes that can be loaded into X registers.
(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
;; Iterator for floating-point modes of BF16
(define_mode_iterator HFBF [HF BF])
;; -------------------------------------------------------------------
;; Mode attributes

View File

@ -230,6 +230,7 @@ static GTY(()) int riscv_builtin_decl_index[NUM_INSN_CODES];
riscv_builtin_decls[riscv_builtin_decl_index[(CODE)]]
tree riscv_float16_type_node = NULL_TREE;
tree riscv_bfloat16_type_node = NULL_TREE;
/* Return the function type associated with function prototype TYPE. */
@ -273,6 +274,21 @@ riscv_init_builtin_types (void)
if (!maybe_get_identifier ("_Float16"))
lang_hooks.types.register_builtin_type (riscv_float16_type_node,
"_Float16");
/* Provide the _Bfloat16 type and bfloat16_type_node if needed. */
if (!bfloat16_type_node)
{
riscv_bfloat16_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (riscv_bfloat16_type_node) = 16;
SET_TYPE_MODE (riscv_bfloat16_type_node, BFmode);
layout_type (riscv_bfloat16_type_node);
}
else
riscv_bfloat16_type_node = bfloat16_type_node;
if (!maybe_get_identifier ("_Bfloat16"))
lang_hooks.types.register_builtin_type (riscv_bfloat16_type_node,
"_Bfloat16");
}
/* Implement TARGET_INIT_BUILTINS. */

View File

@ -21,6 +21,9 @@ along with GCC; see the file COPYING3. If not see
FLOAT_MODE (HF, 2, ieee_half_format);
FLOAT_MODE (TF, 16, ieee_quad_format);
FLOAT_MODE (BF, 2, 0);
/* Reuse definition from arm. */
ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format);
/* Vector modes. */

View File

@ -10188,9 +10188,17 @@ riscv_asan_shadow_offset (void)
static const char *
riscv_mangle_type (const_tree type)
{
/* Half-precision float, _Float16 is "DF16_". */
/* Half-precision float, _Float16 is "DF16_" and _Bfloat16 is "DF16b". */
if (SCALAR_FLOAT_TYPE_P (type) && TYPE_PRECISION (type) == 16)
return "DF16_";
{
if (TYPE_MODE (type) == HFmode)
return "DF16_";
if (TYPE_MODE (type) == BFmode)
return "DF16b";
gcc_unreachable ();
}
/* Mangle all vector type for vector extension. */
/* The mangle name follows the rule of RVV LLVM
@ -10211,19 +10219,20 @@ riscv_mangle_type (const_tree type)
static bool
riscv_scalar_mode_supported_p (scalar_mode mode)
{
if (mode == HFmode)
if (mode == HFmode || mode == BFmode)
return true;
else
return default_scalar_mode_supported_p (mode);
}
/* Implement TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P - return TRUE
if MODE is HFmode, and punt to the generic implementation otherwise. */
if MODE is HFmode or BFmode, and punt to the generic implementation
otherwise. */
static bool
riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode)
{
if (mode == HFmode)
if (mode == HFmode || mode == BFmode)
return true;
else
return default_libgcc_floating_mode_supported_p (mode);
@ -10274,27 +10283,42 @@ riscv_floatn_mode (int n, bool extended)
return default_floatn_mode (n, extended);
}
/* Record that we have no arithmetic or comparison libfuncs for
machine_mode MODE. */
static void
riscv_block_arith_comp_libfuncs_for_mode (machine_mode mode)
{
/* Half-precision float or Brain float operations. The compiler handles all
operations with NULL libfuncs by converting to SFmode. */
/* Arithmetic. */
set_optab_libfunc (add_optab, mode, NULL);
set_optab_libfunc (sdiv_optab, mode, NULL);
set_optab_libfunc (smul_optab, mode, NULL);
set_optab_libfunc (neg_optab, mode, NULL);
set_optab_libfunc (sub_optab, mode, NULL);
/* Comparisons. */
set_optab_libfunc (eq_optab, mode, NULL);
set_optab_libfunc (ne_optab, mode, NULL);
set_optab_libfunc (lt_optab, mode, NULL);
set_optab_libfunc (le_optab, mode, NULL);
set_optab_libfunc (ge_optab, mode, NULL);
set_optab_libfunc (gt_optab, mode, NULL);
set_optab_libfunc (unord_optab, mode, NULL);
}
static void
riscv_init_libfuncs (void)
{
/* Half-precision float operations. The compiler handles all operations
with NULL libfuncs by converting to SFmode. */
riscv_block_arith_comp_libfuncs_for_mode (HFmode);
riscv_block_arith_comp_libfuncs_for_mode (BFmode);
/* Arithmetic. */
set_optab_libfunc (add_optab, HFmode, NULL);
set_optab_libfunc (sdiv_optab, HFmode, NULL);
set_optab_libfunc (smul_optab, HFmode, NULL);
set_optab_libfunc (neg_optab, HFmode, NULL);
set_optab_libfunc (sub_optab, HFmode, NULL);
/* Comparisons. */
set_optab_libfunc (eq_optab, HFmode, NULL);
set_optab_libfunc (ne_optab, HFmode, NULL);
set_optab_libfunc (lt_optab, HFmode, NULL);
set_optab_libfunc (le_optab, HFmode, NULL);
set_optab_libfunc (ge_optab, HFmode, NULL);
set_optab_libfunc (gt_optab, HFmode, NULL);
set_optab_libfunc (unord_optab, HFmode, NULL);
/* Convert between BFmode and HFmode using only trunc libfunc if needed. */
set_conv_libfunc (sext_optab, BFmode, HFmode, "__trunchfbf2");
set_conv_libfunc (sext_optab, HFmode, BFmode, "__truncbfhf2");
set_conv_libfunc (trunc_optab, BFmode, HFmode, "__trunchfbf2");
set_conv_libfunc (trunc_optab, HFmode, BFmode, "__truncbfhf2");
}
#if CHECKING_P

View File

@ -196,7 +196,7 @@
(const_string "unknown"))
;; Main data type used by the insn
(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,SF,DF,TF,
(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,BF,SF,DF,TF,
RVVMF64BI,RVVMF32BI,RVVMF16BI,RVVMF8BI,RVVMF4BI,RVVMF2BI,RVVM1BI,
RVVM8QI,RVVM4QI,RVVM2QI,RVVM1QI,RVVMF2QI,RVVMF4QI,RVVMF8QI,
RVVM8HI,RVVM4HI,RVVM2HI,RVVM1HI,RVVMF2HI,RVVMF4HI,
@ -1887,12 +1887,12 @@
(set_attr "mode" "DF")])
;; 16-bit floating point moves
(define_expand "movhf"
[(set (match_operand:HF 0 "")
(match_operand:HF 1 ""))]
(define_expand "mov<mode>"
[(set (match_operand:HFBF 0 "")
(match_operand:HFBF 1 ""))]
""
{
if (riscv_legitimize_move (HFmode, operands[0], operands[1]))
if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
DONE;
})
@ -1907,16 +1907,16 @@
(set_attr "type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
(set_attr "mode" "HF")])
(define_insn "*movhf_softfloat"
[(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
(match_operand:HF 1 "move_operand" " f,Gr,m,r,*r,*f"))]
"!TARGET_ZFHMIN
&& (register_operand (operands[0], HFmode)
|| reg_or_0_operand (operands[1], HFmode))"
(define_insn "*mov<mode>_softfloat"
[(set (match_operand:HFBF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
(match_operand:HFBF 1 "move_operand" " f,Gr,m,r,*r,*f"))]
"((!TARGET_ZFHMIN && <MODE>mode == HFmode) || (<MODE>mode == BFmode))
&& (register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))"
{ return riscv_output_move (operands[0], operands[1]); }
[(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
(set_attr "type" "fmove,move,load,store,mtc,mfc")
(set_attr "mode" "HF")])
(set_attr "mode" "<MODE>")])
(define_insn "*movhf_softfloat_boxing"
[(set (match_operand:HF 0 "register_operand" "=f")

View File

@ -0,0 +1,42 @@
/* { dg-do compile } */
/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
/* 1) bf -> sf (call __extendbfsf2) */
/* 2) sf1 [+|-|*|/] sf2 (call __[add|sub|mul|div]sf3) */
/* 3) sf -> bf (call __truncsfbf2) */
extern _Bfloat16 bf;
extern _Bfloat16 bf1;
extern _Bfloat16 bf2;
void bf_add_bf () { bf = bf1 + bf2; }
void bf_sub_bf () { bf = bf1 - bf2; }
void bf_mul_bf () { bf = bf1 * bf2; }
void bf_div_bf () { bf = bf1 / bf2; }
void bf_add_const () { bf = bf1 + 3.14f; }
void const_sub_bf () { bf = 3.14f - bf2; }
void bf_mul_const () { bf = bf1 * 3.14f; }
void const_div_bf () { bf = 3.14f / bf2; }
void bf_inc () { ++bf; }
void bf_dec () { --bf; }
/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 16 } } */
/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 10 } } */
/* { dg-final { scan-assembler-times "call\t__addsf3" 3 } } */
/* { dg-final { scan-assembler-times "call\t__subsf3" 3 } } */
/* { dg-final { scan-assembler-times "call\t__mulsf3" 2 } } */
/* { dg-final { scan-assembler-times "call\t__divsf3" 2 } } */
/* { dg-final { scan-assembler-not "call\t__addbf3" } } */
/* { dg-final { scan-assembler-not "call\t__subbf3" } } */
/* { dg-final { scan-assembler-not "call\t__mulbf3" } } */
/* { dg-final { scan-assembler-not "call\t__divbf3" } } */

View File

@ -0,0 +1,12 @@
/* { dg-do compile } */
/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
/* 1) bf -> sf (call __extendbfsf2) */
/* 2) sf -> bf (call __truncsfbf2) */
__attribute__ ((noinline)) _Bfloat16 add (_Bfloat16 a, _Bfloat16 b) { return a + b; }
_Bfloat16 test(_Bfloat16 a, _Bfloat16 b) { return add (a, b); }
/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 2 } } */
/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 1 } } */

View File

@ -0,0 +1,36 @@
/* { dg-do compile } */
/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
/* 1) bf -> sf (call __extendbfsf2) */
/* 2) sf1 [<|<=|>|>=|==] sf2 (call __[lt|le|gt|ge|eq]sf2) */
extern _Bfloat16 bf;
extern _Bfloat16 bf1;
extern _Bfloat16 bf2;
void bf_lt_bf () { bf = (bf1 < bf2) ? bf1 : bf2; }
void bf_le_bf () { bf = (bf1 <= bf2) ? bf1 : bf2; }
void bf_gt_bf () { bf = (bf1 > bf2) ? bf1 : bf2; }
void bf_ge_bf () { bf = (bf1 >= bf2) ? bf1 : bf2; }
void bf_eq_bf () { bf = (bf1 == bf2) ? bf1 : bf2; }
void bf_lt_const () { bf = (bf1 < 3.14f) ? bf1 : bf2; }
void bf_le_const () { bf = (bf1 <= 3.14f) ? bf1 : bf2; }
void const_gt_bf () { bf = (3.14f > bf2) ? bf1 : bf2; }
void const_ge_bf () { bf = (3.14f >= bf2) ? bf1 : bf2; }
void bf_eq_const () { bf = (bf1 == 3.14f) ? bf1 : bf2; }
/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 15 } } */
/* { dg-final { scan-assembler-not "call\t__ltbf2" } } */
/* { dg-final { scan-assembler-not "call\t__lebf2" } } */
/* { dg-final { scan-assembler-not "call\t__gtbf2" } } */
/* { dg-final { scan-assembler-not "call\t__gebf2" } } */
/* { dg-final { scan-assembler-not "call\t__eqbf2" } } */

View File

@ -0,0 +1,57 @@
/* { dg-do compile } */
/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
/* 1) float -> BF16
* hf/sf/df/tf -> bf (call __trunc[h|s|d|t]fbf2)
*/
/* 2) BF16 -> float
* bf -> hf == sf -> hf (call __truncsfhf2)
* bf -> sf (call __extendbfsf2)
* bf -> df == bf -> sf -> df (call __extendbfsf2 && __extendsfdf2)
* bf -> tf == bf -> sf -> tf (call __extendbfsf2 && __extendsftf2)
*/
extern _Bfloat16 bf;
extern _Float16 hf;
extern float sf;
extern double df;
extern long double tf;
void hf_to_bf () { bf = hf; }
void bf_to_hf () { hf = bf; }
void sf_to_bf () { bf = sf; }
void bf_to_sf () { sf = bf; }
void df_to_bf () { bf = df; }
void bf_to_df () { df = bf; }
void tf_to_bf () { bf = tf; }
void bf_to_tf () { tf = bf; }
/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 3 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 3 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__extendsfdf2" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__extendsfdf2" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__extendsftf2" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__extendsftf2" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__trunchfbf2" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__trunchfbf2" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__truncdfbf2" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__truncdfbf2" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__trunctfbf2" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__trunctfbf2" 1 { target { rv64 } } } } */

View File

@ -0,0 +1,81 @@
/* { dg-do compile } */
/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
/* 1) Integer -> BF16
* qi/hi/si -> bf (call __floatsibf)
* uqi/uhi/usi -> bf (call __floatunsibf)
* di/ti -> bf (call __float[d|t]ibf)
* udi/uti -> bf (call __floatun[d|t]ibf)
*/
/* 2) BF16 -> Integer
* bf -> qi/hi/si (call __fixsfsi)
* bf -> uqi/uhi/usi (call __fixunssfsi)
* bf -> di/ti (call __fixsf[d|t]i)
* bf -> udi/uti (call __fixunssf[d|t]i)
*/
extern _Bfloat16 bf;
extern signed char qi;
extern unsigned char uqi;
extern signed short hi;
extern unsigned short uhi;
extern signed int si;
extern unsigned int usi;
extern signed long long di;
extern unsigned long long udi;
void qi_to_bf () { bf = qi; }
void uqi_to_bf () { bf = uqi; }
void bf_to_qi () { qi = bf; }
void bf_to_uqi () { uqi = bf; }
void hi_to_bf () { bf = hi; }
void uhi_to_bf () { bf = uhi; }
void bf_to_hi () { hi = bf; }
void bf_to_uhi () { uhi = bf; }
void si_to_bf () { bf = si; }
void usi_to_bf () { bf = usi; }
void bf_to_si () { si = bf; }
void bf_to_usi () { usi = bf; }
void di_to_bf () { bf = di; }
void udi_to_bf () { bf = udi; }
void bf_to_di () { di = bf; }
void bf_to_udi () { udi = bf; }
#if __riscv_xlen == 64
extern signed __int128 ti;
extern unsigned __int128 uti;
void ti_to_bf () { bf = ti; } /* { dg-final { scan-assembler-times "call\t__floattibf" 1 { target { rv64 } } } } */
void uti_to_bf () { bf = uti; } /* { dg-final { scan-assembler-times "call\t__floatuntibf" 1 { target { rv64 } } } } */
void bf_to_ti () { ti = bf; } /* { dg-final { scan-assembler-times "call\t__fixsfti" 1 { target { rv64 } } } } */
void bf_to_uti () { uti = bf; } /* { dg-final { scan-assembler-times "call\t__fixunssfti" 1 { target { rv64 } } } } */
#endif
/* { dg-final { scan-assembler-times "call\t__fixsfsi" 3 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__fixsfsi" 3 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__fixsfdi" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__fixsfdi" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__fixunssfsi" 3 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__fixunssfsi" 3 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__fixunssfdi" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__fixunssfdi" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatsibf" 3 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatsibf" 3 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatdibf" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatdibf" 1 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatunsibf" 3 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatunsibf" 3 { target { rv64 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatundibf" 1 { target { rv32 } } } } */
/* { dg-final { scan-assembler-times "call\t__floatundibf" 1 { target { rv64 } } } } */

View File

@ -41,6 +41,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
#define _FP_NANFRAC_B _FP_QNANBIT_B
#define _FP_NANFRAC_H _FP_QNANBIT_H
#define _FP_NANFRAC_S _FP_QNANBIT_S
#define _FP_NANFRAC_D _FP_QNANBIT_D, 0
@ -64,6 +65,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
#define _FP_NANFRAC_B _FP_QNANBIT_B
#define _FP_NANFRAC_H _FP_QNANBIT_H
#define _FP_NANFRAC_S _FP_QNANBIT_S
#define _FP_NANFRAC_D _FP_QNANBIT_D
@ -82,6 +84,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
#define CMPtype __gcc_CMPtype
#define _FP_NANSIGN_B 0
#define _FP_NANSIGN_H 0
#define _FP_NANSIGN_S 0
#define _FP_NANSIGN_D 0

View File

@ -42,7 +42,11 @@ softfp_extras += divsf3 divdf3 divtf3
endif
softfp_extensions += hfsf hfdf hftf
softfp_truncations += tfhf dfhf sfhf
softfp_extensions += hfsf hfdf hftf \
bfsf
softfp_truncations += tfhf dfhf sfhf \
tfbf dfbf sfbf \
hfbf bfhf
softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \
floatsihf floatdihf floatunsihf floatundihf
floatsihf floatdihf floatunsihf floatundihf \
floatsibf floatdibf floatunsibf floatundibf

View File

@ -1,4 +1,5 @@
include $(srcdir)/config/riscv/t-softfp32
softfp_int_modes += ti
softfp_extras += fixhfti fixunshfti floattihf floatuntihf
softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
floattibf floatuntibf

View File

@ -0,0 +1,45 @@
/* Software floating-point emulation.
Convert a 32bit signed integer to bfloat16
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.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file into
combinations with other programs, and to distribute those
combinations without any restriction coming from the use of this
file. (The Lesser General Public License restrictions do apply in
other respects; for example, they cover modification of the file,
and distribution when not linked into a combine executable.)
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 "brain.h"
BFtype
__floatsibf (SItype i)
{
FP_DECL_EX;
FP_DECL_B (A);
BFtype a;
FP_INIT_ROUNDMODE;
FP_FROM_INT_B (A, i, SI_BITS, USItype);
FP_PACK_RAW_B (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
}

View File

@ -0,0 +1,45 @@
/* Software floating-point emulation.
Convert a 32bit unsigned integer to bfloat16
Copyright (C) 2007-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.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file into
combinations with other programs, and to distribute those
combinations without any restriction coming from the use of this
file. (The Lesser General Public License restrictions do apply in
other respects; for example, they cover modification of the file,
and distribution when not linked into a combine executable.)
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 "brain.h"
BFtype
__floatunsibf (USItype i)
{
FP_DECL_EX;
FP_DECL_B (A);
BFtype a;
FP_INIT_ROUNDMODE;
FP_FROM_INT_B (A, i, SI_BITS, USItype);
FP_PACK_RAW_B (a, A);
FP_HANDLE_EXCEPTIONS;
return a;
}