GNU Linux-libre 4.19.314-gnu1
[releases.git] / arch / arm / nwfpe / extended_cpdo.c
1 /*
2     NetWinder Floating Point Emulator
3     (c) Rebel.COM, 1998,1999
4
5     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "fpa11.h"
23 #include "softfloat.h"
24 #include "fpopcode.h"
25
26 floatx80 floatx80_exp(floatx80 Fm);
27 floatx80 floatx80_ln(floatx80 Fm);
28 floatx80 floatx80_sin(floatx80 rFm);
29 floatx80 floatx80_cos(floatx80 rFm);
30 floatx80 floatx80_arcsin(floatx80 rFm);
31 floatx80 floatx80_arctan(floatx80 rFm);
32 floatx80 floatx80_log(floatx80 rFm);
33 floatx80 floatx80_tan(floatx80 rFm);
34 floatx80 floatx80_arccos(floatx80 rFm);
35 floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
36 floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
37
38 static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
39 {
40         return floatx80_sub(roundData, rFm, rFn);
41 }
42
43 static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
44 {
45         return floatx80_div(roundData, rFm, rFn);
46 }
47
48 static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
49         [ADF_CODE >> 20] = floatx80_add,
50         [MUF_CODE >> 20] = floatx80_mul,
51         [SUF_CODE >> 20] = floatx80_sub,
52         [RSF_CODE >> 20] = floatx80_rsf,
53         [DVF_CODE >> 20] = floatx80_div,
54         [RDF_CODE >> 20] = floatx80_rdv,
55         [RMF_CODE >> 20] = floatx80_rem,
56
57         /* strictly, these opcodes should not be implemented */
58         [FML_CODE >> 20] = floatx80_mul,
59         [FDV_CODE >> 20] = floatx80_div,
60         [FRD_CODE >> 20] = floatx80_rdv,
61 };
62
63 static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
64 {
65         return rFm;
66 }
67
68 static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
69 {
70         rFm.high ^= 0x8000;
71         return rFm;
72 }
73
74 static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
75 {
76         rFm.high &= 0x7fff;
77         return rFm;
78 }
79
80 static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
81         [MVF_CODE >> 20] = floatx80_mvf,
82         [MNF_CODE >> 20] = floatx80_mnf,
83         [ABS_CODE >> 20] = floatx80_abs,
84         [RND_CODE >> 20] = floatx80_round_to_int,
85         [URD_CODE >> 20] = floatx80_round_to_int,
86         [SQT_CODE >> 20] = floatx80_sqrt,
87         [NRM_CODE >> 20] = floatx80_mvf,
88 };
89
90 unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
91 {
92         FPA11 *fpa11 = GET_FPA11();
93         floatx80 rFm;
94         unsigned int Fm, opc_mask_shift;
95
96         Fm = getFm(opcode);
97         if (CONSTANT_FM(opcode)) {
98                 rFm = getExtendedConstant(Fm);
99         } else {
100                 switch (fpa11->fType[Fm]) {
101                 case typeSingle:
102                         rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
103                         break;
104
105                 case typeDouble:
106                         rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
107                         break;
108
109                 case typeExtended:
110                         rFm = fpa11->fpreg[Fm].fExtended;
111                         break;
112
113                 default:
114                         return 0;
115                 }
116         }
117
118         opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
119         if (!MONADIC_INSTRUCTION(opcode)) {
120                 unsigned int Fn = getFn(opcode);
121                 floatx80 rFn;
122
123                 switch (fpa11->fType[Fn]) {
124                 case typeSingle:
125                         rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
126                         break;
127
128                 case typeDouble:
129                         rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
130                         break;
131
132                 case typeExtended:
133                         rFn = fpa11->fpreg[Fn].fExtended;
134                         break;
135
136                 default:
137                         return 0;
138                 }
139
140                 if (dyadic_extended[opc_mask_shift]) {
141                         rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
142                 } else {
143                         return 0;
144                 }
145         } else {
146                 if (monadic_extended[opc_mask_shift]) {
147                         rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
148                 } else {
149                         return 0;
150                 }
151         }
152
153         return 1;
154 }