Statistics
| Branch: | Revision:

root / target-arm / nwfpe / fpa11_cpdt.c @ 2f619698

History | View | Annotate | Download (9.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
   target_ulong addr = (target_ulong)(long)pMem;
35
   FPA11 *fpa11 = GET_FPA11();
36
   fpa11->fType[Fn] = typeSingle;
37
   /* FIXME - handle failure of get_user() */
38
   get_user_u32(fpa11->fpreg[Fn].fSingle, addr);
39
}
40

    
41
static inline
42
void loadDouble(const unsigned int Fn,const unsigned int *pMem)
43
{
44
   target_ulong addr = (target_ulong)(long)pMem;
45
   FPA11 *fpa11 = GET_FPA11();
46
   unsigned int *p;
47
   p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
48
   fpa11->fType[Fn] = typeDouble;
49
#ifdef WORDS_BIGENDIAN
50
   /* FIXME - handle failure of get_user() */
51
   get_user_u32(p[0], addr); /* sign & exponent */
52
   get_user_u32(p[1], addr + 4);
53
#else
54
   /* FIXME - handle failure of get_user() */
55
   get_user_u32(p[0], addr + 4);
56
   get_user_u32(p[1], addr); /* sign & exponent */
57
#endif
58
}
59

    
60
static inline
61
void loadExtended(const unsigned int Fn,const unsigned int *pMem)
62
{
63
   target_ulong addr = (target_ulong)(long)pMem;
64
   FPA11 *fpa11 = GET_FPA11();
65
   unsigned int *p;
66
   p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
67
   fpa11->fType[Fn] = typeExtended;
68
   /* FIXME - handle failure of get_user() */
69
   get_user_u32(p[0], addr);  /* sign & exponent */
70
   get_user_u32(p[1], addr + 8);  /* ls bits */
71
   get_user_u32(p[2], addr + 4);  /* ms bits */
72
}
73

    
74
static inline
75
void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
76
{
77
   target_ulong addr = (target_ulong)(long)pMem;
78
   FPA11 *fpa11 = GET_FPA11();
79
   register unsigned int *p;
80
   unsigned long x;
81

    
82
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
83
   /* FIXME - handle failure of get_user() */
84
   get_user_u32(x, addr);
85
   fpa11->fType[Fn] = (x >> 14) & 0x00000003;
86

    
87
   switch (fpa11->fType[Fn])
88
   {
89
      case typeSingle:
90
      case typeDouble:
91
      {
92
         /* FIXME - handle failure of get_user() */
93
         get_user_u32(p[0], addr + 8);  /* Single */
94
         get_user_u32(p[1], addr + 4);  /* double msw */
95
         p[2] = 0;        /* empty */
96
      }
97
      break;
98

    
99
      case typeExtended:
100
      {
101
         /* FIXME - handle failure of get_user() */
102
         get_user_u32(p[1], addr + 8);
103
         get_user_u32(p[2], addr + 4);  /* msw */
104
         p[0] = (x & 0x80003fff);
105
      }
106
      break;
107
   }
108
}
109

    
110
static inline
111
void storeSingle(const unsigned int Fn,unsigned int *pMem)
112
{
113
   target_ulong addr = (target_ulong)(long)pMem;
114
   FPA11 *fpa11 = GET_FPA11();
115
   float32 val;
116
   register unsigned int *p = (unsigned int*)&val;
117

    
118
   switch (fpa11->fType[Fn])
119
   {
120
      case typeDouble:
121
         val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
122
      break;
123

    
124
      case typeExtended:
125
         val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
126
      break;
127

    
128
      default: val = fpa11->fpreg[Fn].fSingle;
129
   }
130

    
131
   /* FIXME - handle put_user() failures */
132
   put_user_u32(p[0], addr);
133
}
134

    
135
static inline
136
void storeDouble(const unsigned int Fn,unsigned int *pMem)
137
{
138
   target_ulong addr = (target_ulong)(long)pMem;
139
   FPA11 *fpa11 = GET_FPA11();
140
   float64 val;
141
   register unsigned int *p = (unsigned int*)&val;
142

    
143
   switch (fpa11->fType[Fn])
144
   {
145
      case typeSingle:
146
         val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
147
      break;
148

    
149
      case typeExtended:
150
         val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
151
      break;
152

    
153
      default: val = fpa11->fpreg[Fn].fDouble;
154
   }
155
   /* FIXME - handle put_user() failures */
156
#ifdef WORDS_BIGENDIAN
157
   put_user_u32(p[0], addr);        /* msw */
158
   put_user_u32(p[1], addr + 4);        /* lsw */
159
#else
160
   put_user_u32(p[1], addr);        /* msw */
161
   put_user_u32(p[0], addr + 4);        /* lsw */
162
#endif
163
}
164

    
165
static inline
166
void storeExtended(const unsigned int Fn,unsigned int *pMem)
167
{
168
   target_ulong addr = (target_ulong)(long)pMem;
169
   FPA11 *fpa11 = GET_FPA11();
170
   floatx80 val;
171
   register unsigned int *p = (unsigned int*)&val;
172

    
173
   switch (fpa11->fType[Fn])
174
   {
175
      case typeSingle:
176
         val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
177
      break;
178

    
179
      case typeDouble:
180
         val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
181
      break;
182

    
183
      default: val = fpa11->fpreg[Fn].fExtended;
184
   }
185

    
186
   /* FIXME - handle put_user() failures */
187
   put_user_u32(p[0], addr); /* sign & exp */
188
   put_user_u32(p[1], addr + 8);
189
   put_user_u32(p[2], addr + 4); /* msw */
190
}
191

    
192
static inline
193
void storeMultiple(const unsigned int Fn,unsigned int *pMem)
194
{
195
   target_ulong addr = (target_ulong)(long)pMem;
196
   FPA11 *fpa11 = GET_FPA11();
197
   register unsigned int nType, *p;
198

    
199
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
200
   nType = fpa11->fType[Fn];
201

    
202
   switch (nType)
203
   {
204
      case typeSingle:
205
      case typeDouble:
206
      {
207
         put_user_u32(p[0], addr + 8); /* single */
208
         put_user_u32(p[1], addr + 4); /* double msw */
209
         put_user_u32(nType << 14, addr);
210
      }
211
      break;
212

    
213
      case typeExtended:
214
      {
215
         put_user_u32(p[2], addr + 4); /* msw */
216
         put_user_u32(p[1], addr + 8);
217
         put_user_u32((p[0] & 0x80003fff) | (nType << 14), addr);
218
      }
219
      break;
220
   }
221
}
222

    
223
unsigned int PerformLDF(const unsigned int opcode)
224
{
225
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
226
     write_back = WRITE_BACK(opcode);
227

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

    
230
   pBase = (unsigned int*)readRegister(getRn(opcode));
231
   if (REG_PC == getRn(opcode))
232
   {
233
     pBase += 2;
234
     write_back = 0;
235
   }
236

    
237
   pFinal = pBase;
238
   if (BIT_UP_SET(opcode))
239
     pFinal += getOffset(opcode);
240
   else
241
     pFinal -= getOffset(opcode);
242

    
243
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
244

    
245
   switch (opcode & MASK_TRANSFER_LENGTH)
246
   {
247
      case TRANSFER_SINGLE  : loadSingle(getFd(opcode),pAddress);   break;
248
      case TRANSFER_DOUBLE  : loadDouble(getFd(opcode),pAddress);   break;
249
      case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
250
      default: nRc = 0;
251
   }
252

    
253
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
254
   return nRc;
255
}
256

    
257
unsigned int PerformSTF(const unsigned int opcode)
258
{
259
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
260
     write_back = WRITE_BACK(opcode);
261

    
262
   //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
263
   SetRoundingMode(ROUND_TO_NEAREST);
264

    
265
   pBase = (unsigned int*)readRegister(getRn(opcode));
266
   if (REG_PC == getRn(opcode))
267
   {
268
     pBase += 2;
269
     write_back = 0;
270
   }
271

    
272
   pFinal = pBase;
273
   if (BIT_UP_SET(opcode))
274
     pFinal += getOffset(opcode);
275
   else
276
     pFinal -= getOffset(opcode);
277

    
278
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
279

    
280
   switch (opcode & MASK_TRANSFER_LENGTH)
281
   {
282
      case TRANSFER_SINGLE  : storeSingle(getFd(opcode),pAddress);   break;
283
      case TRANSFER_DOUBLE  : storeDouble(getFd(opcode),pAddress);   break;
284
      case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
285
      default: nRc = 0;
286
   }
287

    
288
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
289
   return nRc;
290
}
291

    
292
unsigned int PerformLFM(const unsigned int opcode)
293
{
294
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
295
     write_back = WRITE_BACK(opcode);
296

    
297
   pBase = (unsigned int*)readRegister(getRn(opcode));
298
   if (REG_PC == getRn(opcode))
299
   {
300
     pBase += 2;
301
     write_back = 0;
302
   }
303

    
304
   pFinal = pBase;
305
   if (BIT_UP_SET(opcode))
306
     pFinal += getOffset(opcode);
307
   else
308
     pFinal -= getOffset(opcode);
309

    
310
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
311

    
312
   Fd = getFd(opcode);
313
   for (i=getRegisterCount(opcode);i>0;i--)
314
   {
315
     loadMultiple(Fd,pAddress);
316
     pAddress += 3; Fd++;
317
     if (Fd == 8) Fd = 0;
318
   }
319

    
320
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
321
   return 1;
322
}
323

    
324
unsigned int PerformSFM(const unsigned int opcode)
325
{
326
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
327
     write_back = WRITE_BACK(opcode);
328

    
329
   pBase = (unsigned int*)readRegister(getRn(opcode));
330
   if (REG_PC == getRn(opcode))
331
   {
332
     pBase += 2;
333
     write_back = 0;
334
   }
335

    
336
   pFinal = pBase;
337
   if (BIT_UP_SET(opcode))
338
     pFinal += getOffset(opcode);
339
   else
340
     pFinal -= getOffset(opcode);
341

    
342
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
343

    
344
   Fd = getFd(opcode);
345
   for (i=getRegisterCount(opcode);i>0;i--)
346
   {
347
     storeMultiple(Fd,pAddress);
348
     pAddress += 3; Fd++;
349
     if (Fd == 8) Fd = 0;
350
   }
351

    
352
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
353
   return 1;
354
}
355

    
356
#if 1
357
unsigned int EmulateCPDT(const unsigned int opcode)
358
{
359
  unsigned int nRc = 0;
360

    
361
  //printk("EmulateCPDT(0x%08x)\n",opcode);
362

    
363
  if (LDF_OP(opcode))
364
  {
365
    nRc = PerformLDF(opcode);
366
  }
367
  else if (LFM_OP(opcode))
368
  {
369
    nRc = PerformLFM(opcode);
370
  }
371
  else if (STF_OP(opcode))
372
  {
373
    nRc = PerformSTF(opcode);
374
  }
375
  else if (SFM_OP(opcode))
376
  {
377
    nRc = PerformSFM(opcode);
378
  }
379
  else
380
  {
381
    nRc = 0;
382
  }
383

    
384
  return nRc;
385
}
386
#endif