xref: /OK3568_Linux_fs/kernel/arch/nds32/include/asm/sfp-machine.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /* Copyright (C) 2005-2018 Andes Technology Corporation */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <asm/bitfield.h>
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #define _FP_W_TYPE_SIZE		32
7*4882a593Smuzhiyun #define _FP_W_TYPE		unsigned long
8*4882a593Smuzhiyun #define _FP_WS_TYPE		signed long
9*4882a593Smuzhiyun #define _FP_I_TYPE		long
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
12*4882a593Smuzhiyun #define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
13*4882a593Smuzhiyun #define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define _FP_MUL_MEAT_S(R, X, Y)				\
16*4882a593Smuzhiyun 	_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S, R, X, Y, umul_ppmm)
17*4882a593Smuzhiyun #define _FP_MUL_MEAT_D(R, X, Y)				\
18*4882a593Smuzhiyun 	_FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
19*4882a593Smuzhiyun #define _FP_MUL_MEAT_Q(R, X, Y)				\
20*4882a593Smuzhiyun 	_FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define _FP_MUL_MEAT_DW_S(R, X, Y)			\
23*4882a593Smuzhiyun 	_FP_MUL_MEAT_DW_1_wide(_FP_WFRACBITS_S, R, X, Y, umul_ppmm)
24*4882a593Smuzhiyun #define _FP_MUL_MEAT_DW_D(R, X, Y)			\
25*4882a593Smuzhiyun 	_FP_MUL_MEAT_DW_2_wide(_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define _FP_DIV_MEAT_S(R, X, Y)	_FP_DIV_MEAT_1_udiv_norm(S, R, X, Y)
28*4882a593Smuzhiyun #define _FP_DIV_MEAT_D(R, X, Y)	_FP_DIV_MEAT_2_udiv(D, R, X, Y)
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
31*4882a593Smuzhiyun #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
32*4882a593Smuzhiyun #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
33*4882a593Smuzhiyun #define _FP_NANSIGN_S		0
34*4882a593Smuzhiyun #define _FP_NANSIGN_D		0
35*4882a593Smuzhiyun #define _FP_NANSIGN_Q		0
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define _FP_KEEPNANFRACP 1
38*4882a593Smuzhiyun #define _FP_QNANNEGATEDP 0
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
41*4882a593Smuzhiyun do {								\
42*4882a593Smuzhiyun 	if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)	\
43*4882a593Smuzhiyun 	  && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) { \
44*4882a593Smuzhiyun 		R##_s = Y##_s;					\
45*4882a593Smuzhiyun 		_FP_FRAC_COPY_##wc(R, Y);			\
46*4882a593Smuzhiyun 	} else {						\
47*4882a593Smuzhiyun 		R##_s = X##_s;					\
48*4882a593Smuzhiyun 		_FP_FRAC_COPY_##wc(R, X);			\
49*4882a593Smuzhiyun 	}							\
50*4882a593Smuzhiyun 	R##_c = FP_CLS_NAN;					\
51*4882a593Smuzhiyun } while (0)
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #define __FPU_FPCSR	(current->thread.fpu.fpcsr)
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun /* Obtain the current rounding mode. */
56*4882a593Smuzhiyun #define FP_ROUNDMODE                    \
57*4882a593Smuzhiyun ({                                      \
58*4882a593Smuzhiyun 	__FPU_FPCSR & FPCSR_mskRM;      \
59*4882a593Smuzhiyun })
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define FP_RND_NEAREST		0
62*4882a593Smuzhiyun #define FP_RND_PINF		1
63*4882a593Smuzhiyun #define FP_RND_MINF		2
64*4882a593Smuzhiyun #define FP_RND_ZERO		3
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #define FP_EX_INVALID		FPCSR_mskIVO
67*4882a593Smuzhiyun #define FP_EX_DIVZERO		FPCSR_mskDBZ
68*4882a593Smuzhiyun #define FP_EX_OVERFLOW		FPCSR_mskOVF
69*4882a593Smuzhiyun #define FP_EX_UNDERFLOW		FPCSR_mskUDF
70*4882a593Smuzhiyun #define FP_EX_INEXACT		FPCSR_mskIEX
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun #define SF_CEQ	2
73*4882a593Smuzhiyun #define SF_CLT	1
74*4882a593Smuzhiyun #define SF_CGT	3
75*4882a593Smuzhiyun #define SF_CUN	4
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #include <asm/byteorder.h>
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #ifdef __BIG_ENDIAN__
80*4882a593Smuzhiyun #define __BYTE_ORDER __BIG_ENDIAN
81*4882a593Smuzhiyun #define __LITTLE_ENDIAN 0
82*4882a593Smuzhiyun #else
83*4882a593Smuzhiyun #define __BYTE_ORDER __LITTLE_ENDIAN
84*4882a593Smuzhiyun #define __BIG_ENDIAN 0
85*4882a593Smuzhiyun #endif
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun #define abort() do { } while (0)
88*4882a593Smuzhiyun #define umul_ppmm(w1, w0, u, v)						\
89*4882a593Smuzhiyun do {									\
90*4882a593Smuzhiyun 	UWtype __x0, __x1, __x2, __x3;                                  \
91*4882a593Smuzhiyun 	UHWtype __ul, __vl, __uh, __vh;                                 \
92*4882a593Smuzhiyun 									\
93*4882a593Smuzhiyun 	__ul = __ll_lowpart(u);						\
94*4882a593Smuzhiyun 	__uh = __ll_highpart(u);					\
95*4882a593Smuzhiyun 	__vl = __ll_lowpart(v);						\
96*4882a593Smuzhiyun 	__vh = __ll_highpart(v);					\
97*4882a593Smuzhiyun 									\
98*4882a593Smuzhiyun 	__x0 = (UWtype) __ul * __vl;                                    \
99*4882a593Smuzhiyun 	__x1 = (UWtype) __ul * __vh;                                    \
100*4882a593Smuzhiyun 	__x2 = (UWtype) __uh * __vl;                                    \
101*4882a593Smuzhiyun 	__x3 = (UWtype) __uh * __vh;                                    \
102*4882a593Smuzhiyun 									\
103*4882a593Smuzhiyun 	__x1 += __ll_highpart(__x0);					\
104*4882a593Smuzhiyun 	__x1 += __x2;							\
105*4882a593Smuzhiyun 	if (__x1 < __x2)						\
106*4882a593Smuzhiyun 		__x3 += __ll_B;						\
107*4882a593Smuzhiyun 									\
108*4882a593Smuzhiyun 	(w1) = __x3 + __ll_highpart(__x1);				\
109*4882a593Smuzhiyun 	(w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);	\
110*4882a593Smuzhiyun } while (0)
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
113*4882a593Smuzhiyun do { \
114*4882a593Smuzhiyun 	UWtype __x; \
115*4882a593Smuzhiyun 	__x = (al) + (bl); \
116*4882a593Smuzhiyun 	(sh) = (ah) + (bh) + (__x < (al)); \
117*4882a593Smuzhiyun 	(sl) = __x; \
118*4882a593Smuzhiyun } while (0)
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
121*4882a593Smuzhiyun do { \
122*4882a593Smuzhiyun 	UWtype __x; \
123*4882a593Smuzhiyun 	__x = (al) - (bl); \
124*4882a593Smuzhiyun 	(sh) = (ah) - (bh) - (__x > (al)); \
125*4882a593Smuzhiyun 	(sl) = __x; \
126*4882a593Smuzhiyun } while (0)
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun #define udiv_qrnnd(q, r, n1, n0, d)				\
129*4882a593Smuzhiyun do {								\
130*4882a593Smuzhiyun 	UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m;		\
131*4882a593Smuzhiyun 	__d1 = __ll_highpart(d);				\
132*4882a593Smuzhiyun 	__d0 = __ll_lowpart(d);					\
133*4882a593Smuzhiyun 								\
134*4882a593Smuzhiyun 	__r1 = (n1) % __d1;					\
135*4882a593Smuzhiyun 	__q1 = (n1) / __d1;					\
136*4882a593Smuzhiyun 	__m = (UWtype) __q1 * __d0;				\
137*4882a593Smuzhiyun 	__r1 = __r1 * __ll_B | __ll_highpart(n0);		\
138*4882a593Smuzhiyun 	if (__r1 < __m)	{					\
139*4882a593Smuzhiyun 		__q1--, __r1 += (d);				\
140*4882a593Smuzhiyun 		if (__r1 >= (d))				\
141*4882a593Smuzhiyun 			if (__r1 < __m)				\
142*4882a593Smuzhiyun 				__q1--, __r1 += (d);		\
143*4882a593Smuzhiyun 	}							\
144*4882a593Smuzhiyun 	__r1 -= __m;						\
145*4882a593Smuzhiyun 	__r0 = __r1 % __d1;					\
146*4882a593Smuzhiyun 	__q0 = __r1 / __d1;					\
147*4882a593Smuzhiyun 	__m = (UWtype) __q0 * __d0;				\
148*4882a593Smuzhiyun 	__r0 = __r0 * __ll_B | __ll_lowpart(n0);		\
149*4882a593Smuzhiyun 	if (__r0 < __m)	{					\
150*4882a593Smuzhiyun 		__q0--, __r0 += (d);				\
151*4882a593Smuzhiyun 		if (__r0 >= (d))				\
152*4882a593Smuzhiyun 			if (__r0 < __m)				\
153*4882a593Smuzhiyun 				__q0--, __r0 += (d);		\
154*4882a593Smuzhiyun 	}							\
155*4882a593Smuzhiyun 	__r0 -= __m;						\
156*4882a593Smuzhiyun 	(q) = (UWtype) __q1 * __ll_B | __q0;			\
157*4882a593Smuzhiyun 	(r) = __r0;						\
158*4882a593Smuzhiyun } while (0)
159