Statistics
| Branch: | Revision:

root / target-arm / nwfpe / fpa11_cpdt.c @ 1d6e34fd

History | View | Annotate | Download (8.7 kB)

1 00406dff bellard
/*
2 00406dff bellard
    NetWinder Floating Point Emulator
3 00406dff bellard
    (c) Rebel.com, 1998-1999
4 00406dff bellard
    (c) Philip Blundell, 1998
5 00406dff bellard

6 00406dff bellard
    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7 00406dff bellard

8 00406dff bellard
    This program is free software; you can redistribute it and/or modify
9 00406dff bellard
    it under the terms of the GNU General Public License as published by
10 00406dff bellard
    the Free Software Foundation; either version 2 of the License, or
11 00406dff bellard
    (at your option) any later version.
12 00406dff bellard

13 00406dff bellard
    This program is distributed in the hope that it will be useful,
14 00406dff bellard
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 00406dff bellard
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 00406dff bellard
    GNU General Public License for more details.
17 00406dff bellard

18 00406dff bellard
    You should have received a copy of the GNU General Public License
19 00406dff bellard
    along with this program; if not, write to the Free Software
20 00406dff bellard
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 00406dff bellard
*/
22 00406dff bellard
23 00406dff bellard
#include "fpa11.h"
24 00406dff bellard
#include "softfloat.h"
25 00406dff bellard
#include "fpopcode.h"
26 00406dff bellard
//#include "fpmodule.h"
27 00406dff bellard
//#include "fpmodule.inl"
28 00406dff bellard
29 00406dff bellard
//#include <asm/uaccess.h>
30 00406dff bellard
31 00406dff bellard
static inline
32 00406dff bellard
void loadSingle(const unsigned int Fn,const unsigned int *pMem)
33 00406dff bellard
{
34 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
35 00406dff bellard
   fpa11->fType[Fn] = typeSingle;
36 00406dff bellard
   get_user(fpa11->fpreg[Fn].fSingle, pMem);
37 00406dff bellard
}
38 00406dff bellard
39 00406dff bellard
static inline
40 00406dff bellard
void loadDouble(const unsigned int Fn,const unsigned int *pMem)
41 00406dff bellard
{
42 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
43 00406dff bellard
   unsigned int *p;
44 00406dff bellard
   p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
45 00406dff bellard
   fpa11->fType[Fn] = typeDouble;
46 a8d3431a bellard
#ifdef WORDS_BIGENDIAN
47 a8d3431a bellard
   get_user(p[0], &pMem[0]); /* sign & exponent */
48 a8d3431a bellard
   get_user(p[1], &pMem[1]);
49 a8d3431a bellard
#else
50 00406dff bellard
   get_user(p[0], &pMem[1]);
51 00406dff bellard
   get_user(p[1], &pMem[0]); /* sign & exponent */
52 a8d3431a bellard
#endif
53 00406dff bellard
}   
54 00406dff bellard
55 00406dff bellard
static inline
56 00406dff bellard
void loadExtended(const unsigned int Fn,const unsigned int *pMem)
57 00406dff bellard
{
58 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
59 00406dff bellard
   unsigned int *p;
60 00406dff bellard
   p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
61 00406dff bellard
   fpa11->fType[Fn] = typeExtended;
62 00406dff bellard
   get_user(p[0], &pMem[0]);  /* sign & exponent */
63 00406dff bellard
   get_user(p[1], &pMem[2]);  /* ls bits */
64 00406dff bellard
   get_user(p[2], &pMem[1]);  /* ms bits */
65 00406dff bellard
}   
66 00406dff bellard
67 00406dff bellard
static inline
68 00406dff bellard
void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
69 00406dff bellard
{
70 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
71 00406dff bellard
   register unsigned int *p;
72 00406dff bellard
   unsigned long x;
73 00406dff bellard
74 00406dff bellard
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
75 00406dff bellard
   get_user(x, &pMem[0]);
76 00406dff bellard
   fpa11->fType[Fn] = (x >> 14) & 0x00000003;
77 00406dff bellard
   
78 00406dff bellard
   switch (fpa11->fType[Fn])
79 00406dff bellard
   {
80 00406dff bellard
      case typeSingle:
81 00406dff bellard
      case typeDouble:
82 00406dff bellard
      {
83 00406dff bellard
         get_user(p[0], &pMem[2]);  /* Single */
84 00406dff bellard
         get_user(p[1], &pMem[1]);  /* double msw */
85 00406dff bellard
         p[2] = 0;        /* empty */
86 00406dff bellard
      }
87 00406dff bellard
      break; 
88 00406dff bellard
   
89 00406dff bellard
      case typeExtended:
90 00406dff bellard
      {
91 00406dff bellard
         get_user(p[1], &pMem[2]);
92 00406dff bellard
         get_user(p[2], &pMem[1]);  /* msw */
93 00406dff bellard
         p[0] = (x & 0x80003fff);      
94 00406dff bellard
      }
95 00406dff bellard
      break;
96 00406dff bellard
   }
97 00406dff bellard
}
98 00406dff bellard
99 00406dff bellard
static inline
100 00406dff bellard
void storeSingle(const unsigned int Fn,unsigned int *pMem)
101 00406dff bellard
{
102 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
103 00406dff bellard
   float32 val;
104 00406dff bellard
   register unsigned int *p = (unsigned int*)&val;
105 00406dff bellard
   
106 00406dff bellard
   switch (fpa11->fType[Fn])
107 00406dff bellard
   {
108 00406dff bellard
      case typeDouble: 
109 00406dff bellard
         val = float64_to_float32(fpa11->fpreg[Fn].fDouble);
110 00406dff bellard
      break;
111 00406dff bellard
112 00406dff bellard
      case typeExtended: 
113 00406dff bellard
         val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
114 00406dff bellard
      break;
115 00406dff bellard
116 00406dff bellard
      default: val = fpa11->fpreg[Fn].fSingle;
117 00406dff bellard
   }
118 00406dff bellard
  
119 00406dff bellard
   put_user(p[0], pMem);
120 00406dff bellard
}   
121 00406dff bellard
122 00406dff bellard
static inline
123 00406dff bellard
void storeDouble(const unsigned int Fn,unsigned int *pMem)
124 00406dff bellard
{
125 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
126 00406dff bellard
   float64 val;
127 00406dff bellard
   register unsigned int *p = (unsigned int*)&val;
128 00406dff bellard
129 00406dff bellard
   switch (fpa11->fType[Fn])
130 00406dff bellard
   {
131 00406dff bellard
      case typeSingle: 
132 00406dff bellard
         val = float32_to_float64(fpa11->fpreg[Fn].fSingle);
133 00406dff bellard
      break;
134 00406dff bellard
135 00406dff bellard
      case typeExtended:
136 00406dff bellard
         val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
137 00406dff bellard
      break;
138 00406dff bellard
139 00406dff bellard
      default: val = fpa11->fpreg[Fn].fDouble;
140 00406dff bellard
   }
141 a8d3431a bellard
#ifdef WORDS_BIGENDIAN
142 a8d3431a bellard
   put_user(p[0], &pMem[0]);        /* msw */
143 a8d3431a bellard
   put_user(p[1], &pMem[1]);        /* lsw */
144 a8d3431a bellard
#else
145 00406dff bellard
   put_user(p[1], &pMem[0]);        /* msw */
146 00406dff bellard
   put_user(p[0], &pMem[1]);        /* lsw */
147 a8d3431a bellard
#endif
148 00406dff bellard
}   
149 00406dff bellard
150 00406dff bellard
static inline
151 00406dff bellard
void storeExtended(const unsigned int Fn,unsigned int *pMem)
152 00406dff bellard
{
153 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
154 00406dff bellard
   floatx80 val;
155 00406dff bellard
   register unsigned int *p = (unsigned int*)&val;
156 00406dff bellard
   
157 00406dff bellard
   switch (fpa11->fType[Fn])
158 00406dff bellard
   {
159 00406dff bellard
      case typeSingle: 
160 00406dff bellard
         val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
161 00406dff bellard
      break;
162 00406dff bellard
163 00406dff bellard
      case typeDouble: 
164 00406dff bellard
         val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
165 00406dff bellard
      break;
166 00406dff bellard
167 00406dff bellard
      default: val = fpa11->fpreg[Fn].fExtended;
168 00406dff bellard
   }
169 00406dff bellard
   
170 00406dff bellard
   put_user(p[0], &pMem[0]); /* sign & exp */
171 00406dff bellard
   put_user(p[1], &pMem[2]);
172 00406dff bellard
   put_user(p[2], &pMem[1]); /* msw */
173 00406dff bellard
}   
174 00406dff bellard
175 00406dff bellard
static inline
176 00406dff bellard
void storeMultiple(const unsigned int Fn,unsigned int *pMem)
177 00406dff bellard
{
178 00406dff bellard
   FPA11 *fpa11 = GET_FPA11();
179 00406dff bellard
   register unsigned int nType, *p;
180 00406dff bellard
   
181 00406dff bellard
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
182 00406dff bellard
   nType = fpa11->fType[Fn];
183 00406dff bellard
   
184 00406dff bellard
   switch (nType)
185 00406dff bellard
   {
186 00406dff bellard
      case typeSingle:
187 00406dff bellard
      case typeDouble:
188 00406dff bellard
      {
189 00406dff bellard
         put_user(p[0], &pMem[2]); /* single */
190 00406dff bellard
         put_user(p[1], &pMem[1]); /* double msw */
191 00406dff bellard
         put_user(nType << 14, &pMem[0]);
192 00406dff bellard
      }
193 00406dff bellard
      break; 
194 00406dff bellard
   
195 00406dff bellard
      case typeExtended:
196 00406dff bellard
      {
197 00406dff bellard
         put_user(p[2], &pMem[1]); /* msw */
198 00406dff bellard
         put_user(p[1], &pMem[2]);
199 00406dff bellard
         put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
200 00406dff bellard
      }
201 00406dff bellard
      break;
202 00406dff bellard
   }
203 00406dff bellard
}
204 00406dff bellard
205 00406dff bellard
unsigned int PerformLDF(const unsigned int opcode)
206 00406dff bellard
{
207 00406dff bellard
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
208 00406dff bellard
     write_back = WRITE_BACK(opcode);
209 00406dff bellard
210 00406dff bellard
   //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
211 00406dff bellard
212 00406dff bellard
   pBase = (unsigned int*)readRegister(getRn(opcode));
213 00406dff bellard
   if (REG_PC == getRn(opcode))
214 00406dff bellard
   {
215 00406dff bellard
     pBase += 2;
216 00406dff bellard
     write_back = 0;
217 00406dff bellard
   }
218 00406dff bellard
219 00406dff bellard
   pFinal = pBase;
220 00406dff bellard
   if (BIT_UP_SET(opcode))
221 00406dff bellard
     pFinal += getOffset(opcode);
222 00406dff bellard
   else
223 00406dff bellard
     pFinal -= getOffset(opcode);
224 00406dff bellard
225 00406dff bellard
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
226 00406dff bellard
227 00406dff bellard
   switch (opcode & MASK_TRANSFER_LENGTH)
228 00406dff bellard
   {
229 00406dff bellard
      case TRANSFER_SINGLE  : loadSingle(getFd(opcode),pAddress);   break;
230 00406dff bellard
      case TRANSFER_DOUBLE  : loadDouble(getFd(opcode),pAddress);   break;
231 00406dff bellard
      case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
232 00406dff bellard
      default: nRc = 0;
233 00406dff bellard
   }
234 00406dff bellard
   
235 00406dff bellard
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
236 00406dff bellard
   return nRc;
237 00406dff bellard
}
238 00406dff bellard
239 00406dff bellard
unsigned int PerformSTF(const unsigned int opcode)
240 00406dff bellard
{
241 00406dff bellard
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
242 00406dff bellard
     write_back = WRITE_BACK(opcode);
243 00406dff bellard
   
244 00406dff bellard
   //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
245 00406dff bellard
   SetRoundingMode(ROUND_TO_NEAREST);
246 00406dff bellard
   
247 00406dff bellard
   pBase = (unsigned int*)readRegister(getRn(opcode));
248 00406dff bellard
   if (REG_PC == getRn(opcode))
249 00406dff bellard
   {
250 00406dff bellard
     pBase += 2;
251 00406dff bellard
     write_back = 0;
252 00406dff bellard
   }
253 00406dff bellard
254 00406dff bellard
   pFinal = pBase;
255 00406dff bellard
   if (BIT_UP_SET(opcode))
256 00406dff bellard
     pFinal += getOffset(opcode);
257 00406dff bellard
   else
258 00406dff bellard
     pFinal -= getOffset(opcode);
259 00406dff bellard
260 00406dff bellard
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
261 00406dff bellard
262 00406dff bellard
   switch (opcode & MASK_TRANSFER_LENGTH)
263 00406dff bellard
   {
264 00406dff bellard
      case TRANSFER_SINGLE  : storeSingle(getFd(opcode),pAddress);   break;
265 00406dff bellard
      case TRANSFER_DOUBLE  : storeDouble(getFd(opcode),pAddress);   break;
266 00406dff bellard
      case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
267 00406dff bellard
      default: nRc = 0;
268 00406dff bellard
   }
269 00406dff bellard
   
270 00406dff bellard
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
271 00406dff bellard
   return nRc;
272 00406dff bellard
}
273 00406dff bellard
274 00406dff bellard
unsigned int PerformLFM(const unsigned int opcode)
275 00406dff bellard
{
276 00406dff bellard
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
277 00406dff bellard
     write_back = WRITE_BACK(opcode);
278 00406dff bellard
279 00406dff bellard
   pBase = (unsigned int*)readRegister(getRn(opcode));
280 00406dff bellard
   if (REG_PC == getRn(opcode))
281 00406dff bellard
   {
282 00406dff bellard
     pBase += 2;
283 00406dff bellard
     write_back = 0;
284 00406dff bellard
   }
285 00406dff bellard
286 00406dff bellard
   pFinal = pBase;
287 00406dff bellard
   if (BIT_UP_SET(opcode))
288 00406dff bellard
     pFinal += getOffset(opcode);
289 00406dff bellard
   else
290 00406dff bellard
     pFinal -= getOffset(opcode);
291 00406dff bellard
292 00406dff bellard
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
293 00406dff bellard
294 00406dff bellard
   Fd = getFd(opcode);
295 00406dff bellard
   for (i=getRegisterCount(opcode);i>0;i--)
296 00406dff bellard
   {
297 00406dff bellard
     loadMultiple(Fd,pAddress);
298 00406dff bellard
     pAddress += 3; Fd++;
299 00406dff bellard
     if (Fd == 8) Fd = 0;
300 00406dff bellard
   }
301 00406dff bellard
302 00406dff bellard
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
303 00406dff bellard
   return 1;
304 00406dff bellard
}
305 00406dff bellard
306 00406dff bellard
unsigned int PerformSFM(const unsigned int opcode)
307 00406dff bellard
{
308 00406dff bellard
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
309 00406dff bellard
     write_back = WRITE_BACK(opcode);
310 00406dff bellard
   
311 00406dff bellard
   pBase = (unsigned int*)readRegister(getRn(opcode));
312 00406dff bellard
   if (REG_PC == getRn(opcode))
313 00406dff bellard
   {
314 00406dff bellard
     pBase += 2;
315 00406dff bellard
     write_back = 0;
316 00406dff bellard
   }
317 00406dff bellard
   
318 00406dff bellard
   pFinal = pBase;
319 00406dff bellard
   if (BIT_UP_SET(opcode))
320 00406dff bellard
     pFinal += getOffset(opcode);
321 00406dff bellard
   else
322 00406dff bellard
     pFinal -= getOffset(opcode);
323 00406dff bellard
324 00406dff bellard
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
325 00406dff bellard
326 00406dff bellard
   Fd = getFd(opcode);
327 00406dff bellard
   for (i=getRegisterCount(opcode);i>0;i--)
328 00406dff bellard
   {
329 00406dff bellard
     storeMultiple(Fd,pAddress);
330 00406dff bellard
     pAddress += 3; Fd++;
331 00406dff bellard
     if (Fd == 8) Fd = 0;
332 00406dff bellard
   }
333 00406dff bellard
334 00406dff bellard
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
335 00406dff bellard
   return 1;
336 00406dff bellard
}
337 00406dff bellard
338 00406dff bellard
#if 1
339 00406dff bellard
unsigned int EmulateCPDT(const unsigned int opcode)
340 00406dff bellard
{
341 00406dff bellard
  unsigned int nRc = 0;
342 00406dff bellard
343 00406dff bellard
  //printk("EmulateCPDT(0x%08x)\n",opcode);
344 00406dff bellard
  
345 00406dff bellard
  if (LDF_OP(opcode))
346 00406dff bellard
  {
347 00406dff bellard
    nRc = PerformLDF(opcode);
348 00406dff bellard
  }
349 00406dff bellard
  else if (LFM_OP(opcode))
350 00406dff bellard
  {
351 00406dff bellard
    nRc = PerformLFM(opcode);
352 00406dff bellard
  }
353 00406dff bellard
  else if (STF_OP(opcode))
354 00406dff bellard
  {
355 00406dff bellard
    nRc = PerformSTF(opcode);
356 00406dff bellard
  } 
357 00406dff bellard
  else if (SFM_OP(opcode))
358 00406dff bellard
  {
359 00406dff bellard
    nRc = PerformSFM(opcode);
360 00406dff bellard
  }
361 00406dff bellard
  else
362 00406dff bellard
  {
363 00406dff bellard
    nRc = 0;
364 00406dff bellard
  }
365 00406dff bellard
  
366 00406dff bellard
  return nRc;
367 00406dff bellard
}
368 00406dff bellard
#endif