xref: /openbsd-src/lib/libc/arch/sparc64/fpu/fpu_qp.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: fpu_qp.c,v 1.6 2016/05/08 18:41:17 guenther Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002 Jake Burkholder.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #if 0
30 __FBSDID("$FreeBSD: src/lib/libc/sparc64/fpu/fpu_qp.c,v 1.3 2002/09/02 02:30:20 jake Exp $");
31 #endif
32 
33 #include <sys/types.h>
34 #include <machine/fsr.h>
35 
36 #include "fpu_emu.h"
37 #include "fpu_extern.h"
38 
39 #define	_QP_OP(op) \
40 __dso_hidden void _Qp_ ## op(u_int *c, u_int *a, u_int *b); \
41 PROTO_NORMAL(_Qp_ ## op); \
42 void \
43 _Qp_ ## op(u_int *c, u_int *a, u_int *b) \
44 { \
45 	struct fpemu fe; \
46 	struct fpn *r; \
47 	__asm volatile("stx %%fsr, [%0]" : : "r" (&fe.fe_fsr)); \
48 	fe.fe_f1.fp_sign = a[0] >> 31; \
49 	fe.fe_f1.fp_sticky = 0; \
50 	fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \
51 	fe.fe_f2.fp_sign = b[0] >> 31; \
52 	fe.fe_f2.fp_sticky = 0; \
53 	fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \
54 	r = __fpu_ ## op(&fe); \
55 	c[0] = __fpu_ftoq(&fe, r, c); \
56 } \
57 DEF_STRONG(_Qp_ ## op);
58 
59 #define	_QP_TTOQ(qname, fname, ntype, atype, signed, ...) \
60 void _Qp_ ## qname ## toq(u_int *c, ntype n); \
61 PROTO_NORMAL(_Qp_ ## qname ## toq); \
62 void \
63 _Qp_ ## qname ## toq(u_int *c, ntype n) \
64 { \
65 	struct fpemu fe; \
66 	atype *a; \
67 	__asm volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
68 	a = (atype *)&n; \
69 	fe.fe_f1.fp_sign = signed ? a[0] >> 31 : 0; \
70 	fe.fe_f1.fp_sticky = 0; \
71 	fe.fe_f1.fp_class = __fpu_ ## fname ## tof(&fe.fe_f1, __VA_ARGS__); \
72 	c[0] = __fpu_ftoq(&fe, &fe.fe_f1, c); \
73 } \
74 DEF_STRONG(_Qp_ ## qname ## toq);
75 
76 #define	_QP_QTOT4(qname, fname, type, x)		\
77 type _Qp_qto ## qname(u_int *c); \
78 PROTO_NORMAL(_Qp_qto ## qname); \
79 type \
80 _Qp_qto ## qname(u_int *c) \
81 { \
82 	struct fpemu fe; \
83 	u_int *a; \
84 	type n; \
85 	__asm volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
86 	a = (u_int *)&n; \
87 	fe.fe_f1.fp_sign = c[0] >> 31; \
88 	fe.fe_f1.fp_sticky = 0; \
89 	fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, c[0], c[1], c[2], c[3]); \
90 	a[0] = __fpu_fto ## fname(&fe, &fe.fe_f1, x); \
91 	return (n); \
92 } \
93 DEF_STRONG(_Qp_qto ## qname);
94 
95 #define	_QP_QTOT3(qname, fname, type)		\
96 type _Qp_qto ## qname(u_int *c); \
97 PROTO_NORMAL(_Qp_qto ## qname); \
98 type \
99 _Qp_qto ## qname(u_int *c) \
100 { \
101 	struct fpemu fe; \
102 	u_int *a; \
103 	type n; \
104 	__asm volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
105 	a = (u_int *)&n; \
106 	fe.fe_f1.fp_sign = c[0] >> 31; \
107 	fe.fe_f1.fp_sticky = 0; \
108 	fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, c[0], c[1], c[2], c[3]); \
109 	a[0] = __fpu_fto ## fname(&fe, &fe.fe_f1); \
110 	return (n); \
111 } \
112 DEF_STRONG(_Qp_qto ## qname);
113 
114 #define	_QP_QTOT(qname, fname, type, ...) \
115 type _Qp_qto ## qname(u_int *c); \
116 PROTO_NORMAL(_Qp_qto ## qname); \
117 type \
118 _Qp_qto ## qname(u_int *c) \
119 { \
120 	struct fpemu fe; \
121 	u_int *a; \
122 	type n; \
123 	__asm volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
124 	a = (u_int *)&n; \
125 	fe.fe_f1.fp_sign = c[0] >> 31; \
126 	fe.fe_f1.fp_sticky = 0; \
127 	fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, c[0], c[1], c[2], c[3]); \
128 	a[0] = __fpu_fto ## fname(&fe, &fe.fe_f1, ## __VA_ARGS__); \
129 	return (n); \
130 } \
131 DEF_STRONG(_Qp_qto ## qname);
132 
133 #define	FCC_EQ(fcc)	((fcc) == FSR_CC_EQ)
134 #define	FCC_GE(fcc)	((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_GT)
135 #define	FCC_GT(fcc)	((fcc) == FSR_CC_GT)
136 #define	FCC_LE(fcc)	((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_LT)
137 #define	FCC_LT(fcc)	((fcc) == FSR_CC_LT)
138 #define	FCC_NE(fcc)	((fcc) != FSR_CC_EQ)
139 #define	FCC_ID(fcc)	(fcc)
140 
141 #define	FSR_GET_FCC0(fsr)	(((fsr) >> FSR_FCC_SHIFT) & FSR_FCC_MASK)
142 
143 #define	_QP_CMP(name, cmpe, test) \
144 int _Qp_ ## name(u_int *a, u_int *b) ; \
145 PROTO_NORMAL(_Qp_ ## name); \
146 int \
147 _Qp_ ## name(u_int *a, u_int *b) \
148 { \
149 	struct fpemu fe; \
150 	__asm volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
151 	fe.fe_f1.fp_sign = a[0] >> 31; \
152 	fe.fe_f1.fp_sticky = 0; \
153 	fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \
154 	fe.fe_f2.fp_sign = b[0] >> 31; \
155 	fe.fe_f2.fp_sticky = 0; \
156 	fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \
157 	__fpu_compare(&fe, cmpe, 0); \
158 	return (test(FSR_GET_FCC0(fe.fe_fsr))); \
159 } \
160 DEF_STRONG(_Qp_ ## name);
161 
162 void _Qp_sqrt(u_int *c, u_int *a);
163 PROTO_NORMAL(_Qp_sqrt);
164 void
165 _Qp_sqrt(u_int *c, u_int *a)
166 {
167 	struct fpemu fe;
168 	struct fpn *r;
169 	__asm volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :);
170 	fe.fe_f1.fp_sign = a[0] >> 31;
171 	fe.fe_f1.fp_sticky = 0;
172 	fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]);
173 	r = __fpu_sqrt(&fe);
174 	c[0] = __fpu_ftoq(&fe, r, c);
175 }
176 DEF_STRONG(_Qp_sqrt);
177 
178 _QP_OP(add)
179 _QP_OP(div)
180 _QP_OP(mul)
181 _QP_OP(sub)
182 
183 _QP_TTOQ(d,	d,	double,	u_int,	1, a[0], a[1])
184 _QP_TTOQ(i,	i,	int,	u_int,	1, a[0])
185 _QP_TTOQ(s,	s,	float,	u_int,	1, a[0])
186 _QP_TTOQ(x,	x,	long,	u_long,	1, a[0])
187 _QP_TTOQ(ui,	ui,	u_int,	u_int,	0, a[0])
188 _QP_TTOQ(ux,	ux,	u_long,	u_long,	0, a[0])
189 
190 _QP_QTOT4(d,	d,	double,	a)
191 _QP_QTOT3(i,	i,	int)
192 _QP_QTOT3(s,	s,	float)
193 _QP_QTOT4(x,	x,	long,	a)
194 _QP_QTOT3(ui,	i,	u_int)
195 _QP_QTOT4(ux,	x,	u_long,	a)
196 
197 _QP_CMP(feq,	0,	FCC_EQ)
198 _QP_CMP(fge,	0,	FCC_GE)
199 _QP_CMP(fgt,	0,	FCC_GT)
200 _QP_CMP(fle,	0,	FCC_LE)
201 _QP_CMP(flt,	0,	FCC_LT)
202 _QP_CMP(fne,	0, 	FCC_NE)
203 _QP_CMP(cmp,	0, 	FCC_ID)
204 _QP_CMP(cmpe,	1, 	FCC_ID)
205