Statistics
| Branch: | Revision:

root / linux-user / arm / nwfpe / fpa11_cpdt.c @ d084469c

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