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, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "fpa11.h"
22 #include "softfloat.h"
23 #include "fpopcode.h"
24 
25 float64 float64_exp(float64 Fm);
26 float64 float64_ln(float64 Fm);
27 float64 float64_sin(float64 rFm);
28 float64 float64_cos(float64 rFm);
29 float64 float64_arcsin(float64 rFm);
30 float64 float64_arctan(float64 rFm);
31 float64 float64_log(float64 rFm);
32 float64 float64_tan(float64 rFm);
33 float64 float64_arccos(float64 rFm);
34 float64 float64_pow(float64 rFn,float64 rFm);
35 float64 float64_pol(float64 rFn,float64 rFm);
36 
37 unsigned int DoubleCPDO(const unsigned int opcode)
38 {
39    FPA11 *fpa11 = GET_FPA11();
40    float64 rFm, rFn = float64_zero;
41    unsigned int Fd, Fm, Fn, nRc = 1;
42 
43    //printk("DoubleCPDO(0x%08x)\n",opcode);
44 
45    Fm = getFm(opcode);
46    if (CONSTANT_FM(opcode))
47    {
48      rFm = getDoubleConstant(Fm);
49    }
50    else
51    {
52      switch (fpa11->fType[Fm])
53      {
54         case typeSingle:
55           rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
56         break;
57 
58         case typeDouble:
59           rFm = fpa11->fpreg[Fm].fDouble;
60           break;
61 
62         case typeExtended:
63             // !! patb
64 	    //printk("not implemented! why not?\n");
65             //!! ScottB
66             // should never get here, if extended involved
67             // then other operand should be promoted then
68             // ExtendedCPDO called.
69             break;
70 
71         default: return 0;
72      }
73    }
74 
75    if (!MONADIC_INSTRUCTION(opcode))
76    {
77       Fn = getFn(opcode);
78       switch (fpa11->fType[Fn])
79       {
80         case typeSingle:
81           rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
82         break;
83 
84         case typeDouble:
85           rFn = fpa11->fpreg[Fn].fDouble;
86         break;
87 
88         default: return 0;
89       }
90    }
91 
92    Fd = getFd(opcode);
93    /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */
94    switch (opcode & MASK_ARITHMETIC_OPCODE)
95    {
96       /* dyadic opcodes */
97       case ADF_CODE:
98          fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm, &fpa11->fp_status);
99       break;
100 
101       case MUF_CODE:
102       case FML_CODE:
103          fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm, &fpa11->fp_status);
104       break;
105 
106       case SUF_CODE:
107          fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm, &fpa11->fp_status);
108       break;
109 
110       case RSF_CODE:
111          fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn, &fpa11->fp_status);
112       break;
113 
114       case DVF_CODE:
115       case FDV_CODE:
116          fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm, &fpa11->fp_status);
117       break;
118 
119       case RDF_CODE:
120       case FRD_CODE:
121          fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn, &fpa11->fp_status);
122       break;
123 
124 #if 0
125       case POW_CODE:
126          fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm);
127       break;
128 
129       case RPW_CODE:
130          fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn);
131       break;
132 #endif
133 
134       case RMF_CODE:
135          fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm, &fpa11->fp_status);
136       break;
137 
138 #if 0
139       case POL_CODE:
140          fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm);
141       break;
142 #endif
143 
144       /* monadic opcodes */
145       case MVF_CODE:
146          fpa11->fpreg[Fd].fDouble = rFm;
147       break;
148 
149       case MNF_CODE:
150       {
151          unsigned int *p = (unsigned int*)&rFm;
152 #ifdef HOST_WORDS_BIGENDIAN
153          p[0] ^= 0x80000000;
154 #else
155          p[1] ^= 0x80000000;
156 #endif
157          fpa11->fpreg[Fd].fDouble = rFm;
158       }
159       break;
160 
161       case ABS_CODE:
162       {
163          unsigned int *p = (unsigned int*)&rFm;
164 #ifdef HOST_WORDS_BIGENDIAN
165          p[0] &= 0x7fffffff;
166 #else
167          p[1] &= 0x7fffffff;
168 #endif
169          fpa11->fpreg[Fd].fDouble = rFm;
170       }
171       break;
172 
173       case RND_CODE:
174       case URD_CODE:
175          fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm, &fpa11->fp_status);
176       break;
177 
178       case SQT_CODE:
179          fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm, &fpa11->fp_status);
180       break;
181 
182 #if 0
183       case LOG_CODE:
184          fpa11->fpreg[Fd].fDouble = float64_log(rFm);
185       break;
186 
187       case LGN_CODE:
188          fpa11->fpreg[Fd].fDouble = float64_ln(rFm);
189       break;
190 
191       case EXP_CODE:
192          fpa11->fpreg[Fd].fDouble = float64_exp(rFm);
193       break;
194 
195       case SIN_CODE:
196          fpa11->fpreg[Fd].fDouble = float64_sin(rFm);
197       break;
198 
199       case COS_CODE:
200          fpa11->fpreg[Fd].fDouble = float64_cos(rFm);
201       break;
202 
203       case TAN_CODE:
204          fpa11->fpreg[Fd].fDouble = float64_tan(rFm);
205       break;
206 
207       case ASN_CODE:
208          fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm);
209       break;
210 
211       case ACS_CODE:
212          fpa11->fpreg[Fd].fDouble = float64_arccos(rFm);
213       break;
214 
215       case ATN_CODE:
216          fpa11->fpreg[Fd].fDouble = float64_arctan(rFm);
217       break;
218 #endif
219 
220       case NRM_CODE:
221       break;
222 
223       default:
224       {
225         nRc = 0;
226       }
227    }
228 
229    if (0 != nRc) fpa11->fType[Fd] = typeDouble;
230    return nRc;
231 }
232 
233 #if 0
234 float64 float64_exp(float64 rFm)
235 {
236   return rFm;
237 //series
238 }
239 
240 float64 float64_ln(float64 rFm)
241 {
242   return rFm;
243 //series
244 }
245 
246 float64 float64_sin(float64 rFm)
247 {
248   return rFm;
249 //series
250 }
251 
252 float64 float64_cos(float64 rFm)
253 {
254    return rFm;
255    //series
256 }
257 
258 #if 0
259 float64 float64_arcsin(float64 rFm)
260 {
261 //series
262 }
263 
264 float64 float64_arctan(float64 rFm)
265 {
266   //series
267 }
268 #endif
269 
270 float64 float64_log(float64 rFm)
271 {
272   return float64_div(float64_ln(rFm),getDoubleConstant(7));
273 }
274 
275 float64 float64_tan(float64 rFm)
276 {
277   return float64_div(float64_sin(rFm),float64_cos(rFm));
278 }
279 
280 float64 float64_arccos(float64 rFm)
281 {
282 return rFm;
283    //return float64_sub(halfPi,float64_arcsin(rFm));
284 }
285 
286 float64 float64_pow(float64 rFn,float64 rFm)
287 {
288   return float64_exp(float64_mul(rFm,float64_ln(rFn)));
289 }
290 
291 float64 float64_pol(float64 rFn,float64 rFm)
292 {
293   return float64_arctan(float64_div(rFn,rFm));
294 }
295 #endif
296