1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun NetWinder Floating Point Emulator
4*4882a593Smuzhiyun (c) Rebel.COM, 1998,1999
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "fpa11.h"
11*4882a593Smuzhiyun #include "softfloat.h"
12*4882a593Smuzhiyun #include "fpopcode.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun floatx80 floatx80_exp(floatx80 Fm);
15*4882a593Smuzhiyun floatx80 floatx80_ln(floatx80 Fm);
16*4882a593Smuzhiyun floatx80 floatx80_sin(floatx80 rFm);
17*4882a593Smuzhiyun floatx80 floatx80_cos(floatx80 rFm);
18*4882a593Smuzhiyun floatx80 floatx80_arcsin(floatx80 rFm);
19*4882a593Smuzhiyun floatx80 floatx80_arctan(floatx80 rFm);
20*4882a593Smuzhiyun floatx80 floatx80_log(floatx80 rFm);
21*4882a593Smuzhiyun floatx80 floatx80_tan(floatx80 rFm);
22*4882a593Smuzhiyun floatx80 floatx80_arccos(floatx80 rFm);
23*4882a593Smuzhiyun floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
24*4882a593Smuzhiyun floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
25*4882a593Smuzhiyun
floatx80_rsf(struct roundingData * roundData,floatx80 rFn,floatx80 rFm)26*4882a593Smuzhiyun static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun return floatx80_sub(roundData, rFm, rFn);
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
floatx80_rdv(struct roundingData * roundData,floatx80 rFn,floatx80 rFm)31*4882a593Smuzhiyun static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun return floatx80_div(roundData, rFm, rFn);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
37*4882a593Smuzhiyun [ADF_CODE >> 20] = floatx80_add,
38*4882a593Smuzhiyun [MUF_CODE >> 20] = floatx80_mul,
39*4882a593Smuzhiyun [SUF_CODE >> 20] = floatx80_sub,
40*4882a593Smuzhiyun [RSF_CODE >> 20] = floatx80_rsf,
41*4882a593Smuzhiyun [DVF_CODE >> 20] = floatx80_div,
42*4882a593Smuzhiyun [RDF_CODE >> 20] = floatx80_rdv,
43*4882a593Smuzhiyun [RMF_CODE >> 20] = floatx80_rem,
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /* strictly, these opcodes should not be implemented */
46*4882a593Smuzhiyun [FML_CODE >> 20] = floatx80_mul,
47*4882a593Smuzhiyun [FDV_CODE >> 20] = floatx80_div,
48*4882a593Smuzhiyun [FRD_CODE >> 20] = floatx80_rdv,
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun
floatx80_mvf(struct roundingData * roundData,floatx80 rFm)51*4882a593Smuzhiyun static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun return rFm;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
floatx80_mnf(struct roundingData * roundData,floatx80 rFm)56*4882a593Smuzhiyun static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun rFm.high ^= 0x8000;
59*4882a593Smuzhiyun return rFm;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
floatx80_abs(struct roundingData * roundData,floatx80 rFm)62*4882a593Smuzhiyun static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun rFm.high &= 0x7fff;
65*4882a593Smuzhiyun return rFm;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
69*4882a593Smuzhiyun [MVF_CODE >> 20] = floatx80_mvf,
70*4882a593Smuzhiyun [MNF_CODE >> 20] = floatx80_mnf,
71*4882a593Smuzhiyun [ABS_CODE >> 20] = floatx80_abs,
72*4882a593Smuzhiyun [RND_CODE >> 20] = floatx80_round_to_int,
73*4882a593Smuzhiyun [URD_CODE >> 20] = floatx80_round_to_int,
74*4882a593Smuzhiyun [SQT_CODE >> 20] = floatx80_sqrt,
75*4882a593Smuzhiyun [NRM_CODE >> 20] = floatx80_mvf,
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun
ExtendedCPDO(struct roundingData * roundData,const unsigned int opcode,FPREG * rFd)78*4882a593Smuzhiyun unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun FPA11 *fpa11 = GET_FPA11();
81*4882a593Smuzhiyun floatx80 rFm;
82*4882a593Smuzhiyun unsigned int Fm, opc_mask_shift;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun Fm = getFm(opcode);
85*4882a593Smuzhiyun if (CONSTANT_FM(opcode)) {
86*4882a593Smuzhiyun rFm = getExtendedConstant(Fm);
87*4882a593Smuzhiyun } else {
88*4882a593Smuzhiyun switch (fpa11->fType[Fm]) {
89*4882a593Smuzhiyun case typeSingle:
90*4882a593Smuzhiyun rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
91*4882a593Smuzhiyun break;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun case typeDouble:
94*4882a593Smuzhiyun rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
95*4882a593Smuzhiyun break;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun case typeExtended:
98*4882a593Smuzhiyun rFm = fpa11->fpreg[Fm].fExtended;
99*4882a593Smuzhiyun break;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun default:
102*4882a593Smuzhiyun return 0;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
107*4882a593Smuzhiyun if (!MONADIC_INSTRUCTION(opcode)) {
108*4882a593Smuzhiyun unsigned int Fn = getFn(opcode);
109*4882a593Smuzhiyun floatx80 rFn;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun switch (fpa11->fType[Fn]) {
112*4882a593Smuzhiyun case typeSingle:
113*4882a593Smuzhiyun rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
114*4882a593Smuzhiyun break;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun case typeDouble:
117*4882a593Smuzhiyun rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
118*4882a593Smuzhiyun break;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun case typeExtended:
121*4882a593Smuzhiyun rFn = fpa11->fpreg[Fn].fExtended;
122*4882a593Smuzhiyun break;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun default:
125*4882a593Smuzhiyun return 0;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun if (dyadic_extended[opc_mask_shift]) {
129*4882a593Smuzhiyun rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
130*4882a593Smuzhiyun } else {
131*4882a593Smuzhiyun return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun } else {
134*4882a593Smuzhiyun if (monadic_extended[opc_mask_shift]) {
135*4882a593Smuzhiyun rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
136*4882a593Smuzhiyun } else {
137*4882a593Smuzhiyun return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun return 1;
142*4882a593Smuzhiyun }
143