gcc/libgcc/config/riscv/sfp-machine.h
Xiao Zeng 8c7cee80eb [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>
2024-05-06 15:39:12 -06:00

147 lines
4.5 KiB
C

/* Software floating-point machine description for RISC-V.
Copyright (C) 2016-2024 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC 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 General Public License
for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#if __riscv_xlen == 32
#define _FP_W_TYPE_SIZE 32
#define _FP_W_TYPE unsigned long
#define _FP_WS_TYPE signed long
#define _FP_I_TYPE long
#define _FP_MUL_MEAT_S(R,X,Y) \
_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_D(R,X,Y) \
_FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_Q(R,X,Y) \
_FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
#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
#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0
#else
#define _FP_W_TYPE_SIZE 64
#define _FP_W_TYPE unsigned long long
#define _FP_WS_TYPE signed long long
#define _FP_I_TYPE long long
#define _FP_MUL_MEAT_S(R,X,Y) \
_FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
#define _FP_MUL_MEAT_D(R,X,Y) \
_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_Q(R,X,Y) \
_FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
#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
#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0
#endif
#if __riscv_xlen == 64
typedef int TItype __attribute__ ((mode (TI)));
typedef unsigned int UTItype __attribute__ ((mode (TI)));
#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype))
#endif
/* The type of the result of a floating point comparison. This must
match __libgcc_cmp_return__ in GCC for the target. */
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
#define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 0
#define _FP_QNANNEGATEDP 0
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
do { \
R##_s = _FP_NANSIGN_##fs; \
_FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \
R##_c = FP_CLS_NAN; \
} while (0)
#define _FP_DECL_EX int _frm __attribute__ ((unused));
#define FP_ROUNDMODE _frm
#define FP_RND_NEAREST 0x0
#define FP_RND_ZERO 0x1
#define FP_RND_PINF 0x3
#define FP_RND_MINF 0x2
#define FP_EX_INVALID 0x10
#define FP_EX_OVERFLOW 0x04
#define FP_EX_UNDERFLOW 0x02
#define FP_EX_DIVZERO 0x08
#define FP_EX_INEXACT 0x01
#define _FP_TININESS_AFTER_ROUNDING 1
#if defined(__riscv_flen) || defined(__riscv_zfinx)
#define FP_INIT_ROUNDMODE \
do { \
__asm__ volatile ("frrm %0" : "=r" (_frm)); \
} while (0)
#define FP_HANDLE_EXCEPTIONS \
do { \
if (__builtin_expect (_fex, 0)) \
__asm__ volatile ("csrs fflags, %0" : : "rK" (_fex)); \
} while (0)
#else
#define FP_INIT_ROUNDMODE _frm = FP_RND_NEAREST
#endif
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define __BYTE_ORDER __BIG_ENDIAN
#else
#define __BYTE_ORDER __LITTLE_ENDIAN
#endif
/* Define ALIASNAME as a strong alias for NAME. */
# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
# define _strong_alias(name, aliasname) \
extern __typeof (name) aliasname __attribute__ ((alias (#name)));