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