Statistics
| Branch: | Revision:

root / target-arm / nwfpe / fpa11_cpdt.c @ d3c61721

History | View | Annotate | Download (8.5 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
   get_user(p[0], &pMem[1]);
47
   get_user(p[1], &pMem[0]); /* sign & exponent */
48
}   
49

    
50
static inline
51
void 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

    
62
static inline
63
void 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

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

    
107
      case typeExtended: 
108
         val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
109
      break;
110

    
111
      default: val = fpa11->fpreg[Fn].fSingle;
112
   }
113
  
114
   put_user(p[0], pMem);
115
}   
116

    
117
static inline
118
void storeDouble(const unsigned int Fn,unsigned int *pMem)
119
{
120
   FPA11 *fpa11 = GET_FPA11();
121
   float64 val;
122
   register unsigned int *p = (unsigned int*)&val;
123

    
124
   switch (fpa11->fType[Fn])
125
   {
126
      case typeSingle: 
127
         val = float32_to_float64(fpa11->fpreg[Fn].fSingle);
128
      break;
129

    
130
      case typeExtended:
131
         val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
132
      break;
133

    
134
      default: val = fpa11->fpreg[Fn].fDouble;
135
   }
136
   put_user(p[1], &pMem[0]);        /* msw */
137
   put_user(p[0], &pMem[1]);        /* lsw */
138
}   
139

    
140
static inline
141
void storeExtended(const unsigned int Fn,unsigned int *pMem)
142
{
143
   FPA11 *fpa11 = GET_FPA11();
144
   floatx80 val;
145
   register unsigned int *p = (unsigned int*)&val;
146
   
147
   switch (fpa11->fType[Fn])
148
   {
149
      case typeSingle: 
150
         val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
151
      break;
152

    
153
      case typeDouble: 
154
         val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
155
      break;
156

    
157
      default: val = fpa11->fpreg[Fn].fExtended;
158
   }
159
   
160
   put_user(p[0], &pMem[0]); /* sign & exp */
161
   put_user(p[1], &pMem[2]);
162
   put_user(p[2], &pMem[1]); /* msw */
163
}   
164

    
165
static inline
166
void storeMultiple(const unsigned int Fn,unsigned int *pMem)
167
{
168
   FPA11 *fpa11 = GET_FPA11();
169
   register unsigned int nType, *p;
170
   
171
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
172
   nType = fpa11->fType[Fn];
173
   
174
   switch (nType)
175
   {
176
      case typeSingle:
177
      case typeDouble:
178
      {
179
         put_user(p[0], &pMem[2]); /* single */
180
         put_user(p[1], &pMem[1]); /* double msw */
181
         put_user(nType << 14, &pMem[0]);
182
      }
183
      break; 
184
   
185
      case typeExtended:
186
      {
187
         put_user(p[2], &pMem[1]); /* msw */
188
         put_user(p[1], &pMem[2]);
189
         put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
190
      }
191
      break;
192
   }
193
}
194

    
195
unsigned int PerformLDF(const unsigned int opcode)
196
{
197
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
198
     write_back = WRITE_BACK(opcode);
199

    
200
   //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
201

    
202
   pBase = (unsigned int*)readRegister(getRn(opcode));
203
   if (REG_PC == getRn(opcode))
204
   {
205
     pBase += 2;
206
     write_back = 0;
207
   }
208

    
209
   pFinal = pBase;
210
   if (BIT_UP_SET(opcode))
211
     pFinal += getOffset(opcode);
212
   else
213
     pFinal -= getOffset(opcode);
214

    
215
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
216

    
217
   switch (opcode & MASK_TRANSFER_LENGTH)
218
   {
219
      case TRANSFER_SINGLE  : loadSingle(getFd(opcode),pAddress);   break;
220
      case TRANSFER_DOUBLE  : loadDouble(getFd(opcode),pAddress);   break;
221
      case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
222
      default: nRc = 0;
223
   }
224
   
225
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
226
   return nRc;
227
}
228

    
229
unsigned int PerformSTF(const unsigned int opcode)
230
{
231
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
232
     write_back = WRITE_BACK(opcode);
233
   
234
   //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
235
   SetRoundingMode(ROUND_TO_NEAREST);
236
   
237
   pBase = (unsigned int*)readRegister(getRn(opcode));
238
   if (REG_PC == getRn(opcode))
239
   {
240
     pBase += 2;
241
     write_back = 0;
242
   }
243

    
244
   pFinal = pBase;
245
   if (BIT_UP_SET(opcode))
246
     pFinal += getOffset(opcode);
247
   else
248
     pFinal -= getOffset(opcode);
249

    
250
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
251

    
252
   switch (opcode & MASK_TRANSFER_LENGTH)
253
   {
254
      case TRANSFER_SINGLE  : storeSingle(getFd(opcode),pAddress);   break;
255
      case TRANSFER_DOUBLE  : storeDouble(getFd(opcode),pAddress);   break;
256
      case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
257
      default: nRc = 0;
258
   }
259
   
260
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
261
   return nRc;
262
}
263

    
264
unsigned int PerformLFM(const unsigned int opcode)
265
{
266
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
267
     write_back = WRITE_BACK(opcode);
268

    
269
   pBase = (unsigned int*)readRegister(getRn(opcode));
270
   if (REG_PC == getRn(opcode))
271
   {
272
     pBase += 2;
273
     write_back = 0;
274
   }
275

    
276
   pFinal = pBase;
277
   if (BIT_UP_SET(opcode))
278
     pFinal += getOffset(opcode);
279
   else
280
     pFinal -= getOffset(opcode);
281

    
282
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
283

    
284
   Fd = getFd(opcode);
285
   for (i=getRegisterCount(opcode);i>0;i--)
286
   {
287
     loadMultiple(Fd,pAddress);
288
     pAddress += 3; Fd++;
289
     if (Fd == 8) Fd = 0;
290
   }
291

    
292
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
293
   return 1;
294
}
295

    
296
unsigned int PerformSFM(const unsigned int opcode)
297
{
298
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
299
     write_back = WRITE_BACK(opcode);
300
   
301
   pBase = (unsigned int*)readRegister(getRn(opcode));
302
   if (REG_PC == getRn(opcode))
303
   {
304
     pBase += 2;
305
     write_back = 0;
306
   }
307
   
308
   pFinal = pBase;
309
   if (BIT_UP_SET(opcode))
310
     pFinal += getOffset(opcode);
311
   else
312
     pFinal -= getOffset(opcode);
313

    
314
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
315

    
316
   Fd = getFd(opcode);
317
   for (i=getRegisterCount(opcode);i>0;i--)
318
   {
319
     storeMultiple(Fd,pAddress);
320
     pAddress += 3; Fd++;
321
     if (Fd == 8) Fd = 0;
322
   }
323

    
324
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
325
   return 1;
326
}
327

    
328
#if 1
329
unsigned int EmulateCPDT(const unsigned int opcode)
330
{
331
  unsigned int nRc = 0;
332

    
333
  //printk("EmulateCPDT(0x%08x)\n",opcode);
334
  
335
  if (LDF_OP(opcode))
336
  {
337
    nRc = PerformLDF(opcode);
338
  }
339
  else if (LFM_OP(opcode))
340
  {
341
    nRc = PerformLFM(opcode);
342
  }
343
  else if (STF_OP(opcode))
344
  {
345
    nRc = PerformSTF(opcode);
346
  } 
347
  else if (SFM_OP(opcode))
348
  {
349
    nRc = PerformSFM(opcode);
350
  }
351
  else
352
  {
353
    nRc = 0;
354
  }
355
  
356
  return nRc;
357
}
358
#endif