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
26float64 float64_exp(float64 Fm);
27float64 float64_ln(float64 Fm);
28float64 float64_sin(float64 rFm);
29float64 float64_cos(float64 rFm);
30float64 float64_arcsin(float64 rFm);
31float64 float64_arctan(float64 rFm);
32float64 float64_log(float64 rFm);
33float64 float64_tan(float64 rFm);
34float64 float64_arccos(float64 rFm);
35float64 float64_pow(float64 rFn,float64 rFm);
36float64 float64_pol(float64 rFn,float64 rFm);
37
38unsigned int DoubleCPDO(const unsigned int opcode)
39{
40   FPA11 *fpa11 = GET_FPA11();
41   float64 rFm, rFn = 0;
42   unsigned int Fd, Fm, Fn, nRc = 1;
43
44   //printk("DoubleCPDO(0x%08x)\n",opcode);
45
46   Fm = getFm(opcode);
47   if (CONSTANT_FM(opcode))
48   {
49     rFm = getDoubleConstant(Fm);
50   }
51   else
52   {
53     switch (fpa11->fType[Fm])
54     {
55        case typeSingle:
56          rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
57        break;
58
59        case typeDouble:
60          rFm = fpa11->fpreg[Fm].fDouble;
61          break;
62
63        case typeExtended:
64            // !! patb
65	    //printk("not implemented! why not?\n");
66            //!! ScottB
67            // should never get here, if extended involved
68            // then other operand should be promoted then
69            // ExtendedCPDO called.
70            break;
71
72        default: return 0;
73     }
74   }
75
76   if (!MONADIC_INSTRUCTION(opcode))
77   {
78      Fn = getFn(opcode);
79      switch (fpa11->fType[Fn])
80      {
81        case typeSingle:
82          rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
83        break;
84
85        case typeDouble:
86          rFn = fpa11->fpreg[Fn].fDouble;
87        break;
88
89        default: return 0;
90      }
91   }
92
93   Fd = getFd(opcode);
94   /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */
95   switch (opcode & MASK_ARITHMETIC_OPCODE)
96   {
97      /* dyadic opcodes */
98      case ADF_CODE:
99         fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm);
100      break;
101
102      case MUF_CODE:
103      case FML_CODE:
104         fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm);
105      break;
106
107      case SUF_CODE:
108         fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm);
109      break;
110
111      case RSF_CODE:
112         fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn);
113      break;
114
115      case DVF_CODE:
116      case FDV_CODE:
117         fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm);
118      break;
119
120      case RDF_CODE:
121      case FRD_CODE:
122         fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn);
123      break;
124
125
126      case RMF_CODE:
127         fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm);
128      break;
129
130
131      /* monadic opcodes */
132      case MVF_CODE:
133         fpa11->fpreg[Fd].fDouble = rFm;
134      break;
135
136      case MNF_CODE:
137      {
138         unsigned int *p = (unsigned int*)&rFm;
139         p[1] ^= 0x80000000;
140         fpa11->fpreg[Fd].fDouble = rFm;
141      }
142      break;
143
144      case ABS_CODE:
145      {
146         unsigned int *p = (unsigned int*)&rFm;
147         p[1] &= 0x7fffffff;
148         fpa11->fpreg[Fd].fDouble = rFm;
149      }
150      break;
151
152      case RND_CODE:
153      case URD_CODE:
154         fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm);
155      break;
156
157      case SQT_CODE:
158         fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm);
159      break;
160
161
162      case NRM_CODE:
163      break;
164
165      default:
166      {
167        nRc = 0;
168      }
169   }
170
171   if (0 != nRc) fpa11->fType[Fd] = typeDouble;
172   return nRc;
173}
174