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 union float64_components {
15*4882a593Smuzhiyun float64 f64;
16*4882a593Smuzhiyun unsigned int i[2];
17*4882a593Smuzhiyun };
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun float64 float64_exp(float64 Fm);
20*4882a593Smuzhiyun float64 float64_ln(float64 Fm);
21*4882a593Smuzhiyun float64 float64_sin(float64 rFm);
22*4882a593Smuzhiyun float64 float64_cos(float64 rFm);
23*4882a593Smuzhiyun float64 float64_arcsin(float64 rFm);
24*4882a593Smuzhiyun float64 float64_arctan(float64 rFm);
25*4882a593Smuzhiyun float64 float64_log(float64 rFm);
26*4882a593Smuzhiyun float64 float64_tan(float64 rFm);
27*4882a593Smuzhiyun float64 float64_arccos(float64 rFm);
28*4882a593Smuzhiyun float64 float64_pow(float64 rFn, float64 rFm);
29*4882a593Smuzhiyun float64 float64_pol(float64 rFn, float64 rFm);
30*4882a593Smuzhiyun
float64_rsf(struct roundingData * roundData,float64 rFn,float64 rFm)31*4882a593Smuzhiyun static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun return float64_sub(roundData, rFm, rFn);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
float64_rdv(struct roundingData * roundData,float64 rFn,float64 rFm)36*4882a593Smuzhiyun static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun return float64_div(roundData, rFm, rFn);
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
42*4882a593Smuzhiyun [ADF_CODE >> 20] = float64_add,
43*4882a593Smuzhiyun [MUF_CODE >> 20] = float64_mul,
44*4882a593Smuzhiyun [SUF_CODE >> 20] = float64_sub,
45*4882a593Smuzhiyun [RSF_CODE >> 20] = float64_rsf,
46*4882a593Smuzhiyun [DVF_CODE >> 20] = float64_div,
47*4882a593Smuzhiyun [RDF_CODE >> 20] = float64_rdv,
48*4882a593Smuzhiyun [RMF_CODE >> 20] = float64_rem,
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* strictly, these opcodes should not be implemented */
51*4882a593Smuzhiyun [FML_CODE >> 20] = float64_mul,
52*4882a593Smuzhiyun [FDV_CODE >> 20] = float64_div,
53*4882a593Smuzhiyun [FRD_CODE >> 20] = float64_rdv,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
float64_mvf(struct roundingData * roundData,float64 rFm)56*4882a593Smuzhiyun static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun return rFm;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
float64_mnf(struct roundingData * roundData,float64 rFm)61*4882a593Smuzhiyun static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun union float64_components u;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun u.f64 = rFm;
66*4882a593Smuzhiyun #ifdef __ARMEB__
67*4882a593Smuzhiyun u.i[0] ^= 0x80000000;
68*4882a593Smuzhiyun #else
69*4882a593Smuzhiyun u.i[1] ^= 0x80000000;
70*4882a593Smuzhiyun #endif
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun return u.f64;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
float64_abs(struct roundingData * roundData,float64 rFm)75*4882a593Smuzhiyun static float64 float64_abs(struct roundingData *roundData,float64 rFm)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun union float64_components u;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun u.f64 = rFm;
80*4882a593Smuzhiyun #ifdef __ARMEB__
81*4882a593Smuzhiyun u.i[0] &= 0x7fffffff;
82*4882a593Smuzhiyun #else
83*4882a593Smuzhiyun u.i[1] &= 0x7fffffff;
84*4882a593Smuzhiyun #endif
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun return u.f64;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
90*4882a593Smuzhiyun [MVF_CODE >> 20] = float64_mvf,
91*4882a593Smuzhiyun [MNF_CODE >> 20] = float64_mnf,
92*4882a593Smuzhiyun [ABS_CODE >> 20] = float64_abs,
93*4882a593Smuzhiyun [RND_CODE >> 20] = float64_round_to_int,
94*4882a593Smuzhiyun [URD_CODE >> 20] = float64_round_to_int,
95*4882a593Smuzhiyun [SQT_CODE >> 20] = float64_sqrt,
96*4882a593Smuzhiyun [NRM_CODE >> 20] = float64_mvf,
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun
DoubleCPDO(struct roundingData * roundData,const unsigned int opcode,FPREG * rFd)99*4882a593Smuzhiyun unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun FPA11 *fpa11 = GET_FPA11();
102*4882a593Smuzhiyun float64 rFm;
103*4882a593Smuzhiyun unsigned int Fm, opc_mask_shift;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun Fm = getFm(opcode);
106*4882a593Smuzhiyun if (CONSTANT_FM(opcode)) {
107*4882a593Smuzhiyun rFm = getDoubleConstant(Fm);
108*4882a593Smuzhiyun } else {
109*4882a593Smuzhiyun switch (fpa11->fType[Fm]) {
110*4882a593Smuzhiyun case typeSingle:
111*4882a593Smuzhiyun rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
112*4882a593Smuzhiyun break;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun case typeDouble:
115*4882a593Smuzhiyun rFm = fpa11->fpreg[Fm].fDouble;
116*4882a593Smuzhiyun break;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun default:
119*4882a593Smuzhiyun return 0;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
124*4882a593Smuzhiyun if (!MONADIC_INSTRUCTION(opcode)) {
125*4882a593Smuzhiyun unsigned int Fn = getFn(opcode);
126*4882a593Smuzhiyun float64 rFn;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun switch (fpa11->fType[Fn]) {
129*4882a593Smuzhiyun case typeSingle:
130*4882a593Smuzhiyun rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
131*4882a593Smuzhiyun break;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun case typeDouble:
134*4882a593Smuzhiyun rFn = fpa11->fpreg[Fn].fDouble;
135*4882a593Smuzhiyun break;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun default:
138*4882a593Smuzhiyun return 0;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun if (dyadic_double[opc_mask_shift]) {
142*4882a593Smuzhiyun rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
143*4882a593Smuzhiyun } else {
144*4882a593Smuzhiyun return 0;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun } else {
147*4882a593Smuzhiyun if (monadic_double[opc_mask_shift]) {
148*4882a593Smuzhiyun rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
149*4882a593Smuzhiyun } else {
150*4882a593Smuzhiyun return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun return 1;
155*4882a593Smuzhiyun }
156