1 /* RISC-V softfloat definitions
2    Copyright (C) 2017-2021 Free Software Foundation, Inc.
3 
4    This file is part of the GNU C Library.
5 
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10 
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library.  If not, see
18    <https://www.gnu.org/licenses/>.  */
19 
20 #include <fenv.h>
21 #include <fpu_control.h>
22 
23 #if __riscv_xlen == 32
24 
25 # define _FP_W_TYPE_SIZE	32
26 # define _FP_W_TYPE		unsigned long
27 # define _FP_WS_TYPE		signed long
28 # define _FP_I_TYPE		long
29 
30 # define _FP_MUL_MEAT_S(R, X, Y)				\
31   _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_S, R, X, Y, umul_ppmm)
32 # define _FP_MUL_MEAT_D(R, X, Y)				\
33   _FP_MUL_MEAT_2_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
34 # define _FP_MUL_MEAT_Q(R, X, Y)				\
35   _FP_MUL_MEAT_4_wide (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
36 
37 # define _FP_MUL_MEAT_DW_S(R, X, Y)					\
38   _FP_MUL_MEAT_DW_1_wide (_FP_WFRACBITS_S, R, X, Y, umul_ppmm)
39 # define _FP_MUL_MEAT_DW_D(R, X, Y)					\
40   _FP_MUL_MEAT_DW_2_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
41 # define _FP_MUL_MEAT_DW_Q(R, X, Y)					\
42   _FP_MUL_MEAT_DW_4_wide (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
43 
44 # define _FP_DIV_MEAT_S(R, X, Y)	_FP_DIV_MEAT_1_udiv_norm (S, R, X, Y)
45 # define _FP_DIV_MEAT_D(R, X, Y)	_FP_DIV_MEAT_2_udiv (D, R, X, Y)
46 # define _FP_DIV_MEAT_Q(R, X, Y)	_FP_DIV_MEAT_4_udiv (Q, R, X, Y)
47 
48 # define _FP_NANFRAC_S		_FP_QNANBIT_S
49 # define _FP_NANFRAC_D		_FP_QNANBIT_D, 0
50 # define _FP_NANFRAC_Q		_FP_QNANBIT_Q, 0, 0, 0
51 
52 #else
53 
54 # define _FP_W_TYPE_SIZE		64
55 # define _FP_W_TYPE		unsigned long long
56 # define _FP_WS_TYPE		signed long long
57 # define _FP_I_TYPE		long long
58 
59 # define _FP_MUL_MEAT_S(R, X, Y)					\
60   _FP_MUL_MEAT_1_imm (_FP_WFRACBITS_S, R, X, Y)
61 # define _FP_MUL_MEAT_D(R, X, Y)					\
62   _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
63 # define _FP_MUL_MEAT_Q(R, X, Y)					\
64   _FP_MUL_MEAT_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
65 
66 # define _FP_MUL_MEAT_DW_S(R, X, Y)					\
67   _FP_MUL_MEAT_DW_1_imm (_FP_WFRACBITS_S, R, X, Y)
68 # define _FP_MUL_MEAT_DW_D(R, X, Y)					\
69   _FP_MUL_MEAT_DW_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
70 # define _FP_MUL_MEAT_DW_Q(R, X, Y)					\
71   _FP_MUL_MEAT_DW_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
72 
73 # define _FP_DIV_MEAT_S(R, X, Y)	_FP_DIV_MEAT_1_imm (S, R, X, Y, _FP_DIV_HELP_imm)
74 # define _FP_DIV_MEAT_D(R, X, Y)	_FP_DIV_MEAT_1_udiv_norm (D, R, X, Y)
75 # define _FP_DIV_MEAT_Q(R, X, Y)	_FP_DIV_MEAT_2_udiv (Q, R, X, Y)
76 
77 # define _FP_NANFRAC_S		_FP_QNANBIT_S
78 # define _FP_NANFRAC_D		_FP_QNANBIT_D
79 # define _FP_NANFRAC_Q		_FP_QNANBIT_Q, 0
80 
81 #endif
82 
83 #define _FP_NANSIGN_S		0
84 #define _FP_NANSIGN_D		0
85 #define _FP_NANSIGN_Q		0
86 
87 #define _FP_KEEPNANFRACP 0
88 #define _FP_QNANNEGATEDP 0
89 
90 #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)	\
91   do {						\
92     R##_s = _FP_NANSIGN_##fs;			\
93     _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs);	\
94     R##_c = FP_CLS_NAN;				\
95   } while (0)
96 
97 #define _FP_DECL_EX		int _frm __attribute__ ((unused));
98 #define FP_ROUNDMODE		_frm
99 
100 #define FP_RND_NEAREST		FE_TONEAREST
101 #define FP_RND_ZERO		FE_TOWARDZERO
102 #define FP_RND_PINF		FE_UPWARD
103 #define FP_RND_MINF		FE_DOWNWARD
104 
105 #define FP_EX_INVALID		FE_INVALID
106 #define FP_EX_OVERFLOW		FE_OVERFLOW
107 #define FP_EX_UNDERFLOW		FE_UNDERFLOW
108 #define FP_EX_DIVZERO		FE_DIVBYZERO
109 #define FP_EX_INEXACT		FE_INEXACT
110 
111 #define _FP_TININESS_AFTER_ROUNDING 1
112 
113 #ifdef __riscv_flen
114 # define FP_INIT_ROUNDMODE			\
115 do {						\
116   __asm__ volatile ("frrm %0" : "=r" (_frm));	\
117 } while (0)
118 
119 # define FP_HANDLE_EXCEPTIONS					\
120 do {								\
121   if (__builtin_expect (_fex, 0))				\
122     __asm__ volatile ("csrs fflags, %0" : : "rK" (_fex));	\
123 } while (0)
124 #else
125 # define FP_INIT_ROUNDMODE	_frm = FP_RND_NEAREST
126 #endif
127