Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (8.7 kB)

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

    
31
static inline
32
void 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

    
39
static inline
40
void 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
#ifdef WORDS_BIGENDIAN
47
   get_user(p[0], &pMem[0]); /* sign & exponent */
48
   get_user(p[1], &pMem[1]);
49
#else
50
   get_user(p[0], &pMem[1]);
51
   get_user(p[1], &pMem[0]); /* sign & exponent */
52
#endif
53
}   
54

    
55
static inline
56
void loadExtended(const unsigned int Fn,const unsigned int *pMem)
57
{
58
   FPA11 *fpa11 = GET_FPA11();
59
   unsigned int *p;
60
   p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
61
   fpa11->fType[Fn] = typeExtended;
62
   get_user(p[0], &pMem[0]);  /* sign & exponent */
63
   get_user(p[1], &pMem[2]);  /* ls bits */
64
   get_user(p[2], &pMem[1]);  /* ms bits */
65
}   
66

    
67
static inline
68
void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
69
{
70
   FPA11 *fpa11 = GET_FPA11();
71
   register unsigned int *p;
72
   unsigned long x;
73

    
74
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
75
   get_user(x, &pMem[0]);
76
   fpa11->fType[Fn] = (x >> 14) & 0x00000003;
77
   
78
   switch (fpa11->fType[Fn])
79
   {
80
      case typeSingle:
81
      case typeDouble:
82
      {
83
         get_user(p[0], &pMem[2]);  /* Single */
84
         get_user(p[1], &pMem[1]);  /* double msw */
85
         p[2] = 0;        /* empty */
86
      }
87
      break; 
88
   
89
      case typeExtended:
90
      {
91
         get_user(p[1], &pMem[2]);
92
         get_user(p[2], &pMem[1]);  /* msw */
93
         p[0] = (x & 0x80003fff);      
94
      }
95
      break;
96
   }
97
}
98

    
99
static inline
100
void storeSingle(const unsigned int Fn,unsigned int *pMem)
101
{
102
   FPA11 *fpa11 = GET_FPA11();
103
   float32 val;
104
   register unsigned int *p = (unsigned int*)&val;
105
   
106
   switch (fpa11->fType[Fn])
107
   {
108
      case typeDouble: 
109
         val = float64_to_float32(fpa11->fpreg[Fn].fDouble);
110
      break;
111

    
112
      case typeExtended: 
113
         val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
114
      break;
115

    
116
      default: val = fpa11->fpreg[Fn].fSingle;
117
   }
118
  
119
   put_user(p[0], pMem);
120
}   
121

    
122
static inline
123
void storeDouble(const unsigned int Fn,unsigned int *pMem)
124
{
125
   FPA11 *fpa11 = GET_FPA11();
126
   float64 val;
127
   register unsigned int *p = (unsigned int*)&val;
128

    
129
   switch (fpa11->fType[Fn])
130
   {
131
      case typeSingle: 
132
         val = float32_to_float64(fpa11->fpreg[Fn].fSingle);
133
      break;
134

    
135
      case typeExtended:
136
         val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
137
      break;
138

    
139
      default: val = fpa11->fpreg[Fn].fDouble;
140
   }
141
#ifdef WORDS_BIGENDIAN
142
   put_user(p[0], &pMem[0]);        /* msw */
143
   put_user(p[1], &pMem[1]);        /* lsw */
144
#else
145
   put_user(p[1], &pMem[0]);        /* msw */
146
   put_user(p[0], &pMem[1]);        /* lsw */
147
#endif
148
}   
149

    
150
static inline
151
void storeExtended(const unsigned int Fn,unsigned int *pMem)
152
{
153
   FPA11 *fpa11 = GET_FPA11();
154
   floatx80 val;
155
   register unsigned int *p = (unsigned int*)&val;
156
   
157
   switch (fpa11->fType[Fn])
158
   {
159
      case typeSingle: 
160
         val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
161
      break;
162

    
163
      case typeDouble: 
164
         val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
165
      break;
166

    
167
      default: val = fpa11->fpreg[Fn].fExtended;
168
   }
169
   
170
   put_user(p[0], &pMem[0]); /* sign & exp */
171
   put_user(p[1], &pMem[2]);
172
   put_user(p[2], &pMem[1]); /* msw */
173
}   
174

    
175
static inline
176
void 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

    
205
unsigned 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

    
239
unsigned 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

    
274
unsigned 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

    
306
unsigned 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
339
unsigned 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