PageRenderTime 62ms CodeModel.GetById 6ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/arm26/nwfpe/fpa11_cpdt.c

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