Statistics
| Branch: | Revision:

root / linux-user / arm / nwfpe / fpa11_cpdt.c @ 70539e18

History | View | Annotate | Download (9.3 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, see <http://www.gnu.org/licenses/>.
20
*/
21

    
22
#include "fpa11.h"
23
#include "softfloat.h"
24
#include "fpopcode.h"
25
//#include "fpmodule.h"
26
//#include "fpmodule.inl"
27

    
28
//#include <asm/uaccess.h>
29

    
30
static inline
31
void loadSingle(const unsigned int Fn, target_ulong addr)
32
{
33
   FPA11 *fpa11 = GET_FPA11();
34
   fpa11->fType[Fn] = typeSingle;
35
   /* FIXME - handle failure of get_user() */
36
   get_user_u32(fpa11->fpreg[Fn].fSingle, addr);
37
}
38

    
39
static inline
40
void loadDouble(const unsigned int Fn, target_ulong addr)
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 HOST_WORDS_BIGENDIAN
47
   /* FIXME - handle failure of get_user() */
48
   get_user_u32(p[0], addr); /* sign & exponent */
49
   get_user_u32(p[1], addr + 4);
50
#else
51
   /* FIXME - handle failure of get_user() */
52
   get_user_u32(p[0], addr + 4);
53
   get_user_u32(p[1], addr); /* sign & exponent */
54
#endif
55
}
56

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

    
70
static inline
71
void loadMultiple(const unsigned int Fn, target_ulong addr)
72
{
73
   FPA11 *fpa11 = GET_FPA11();
74
   register unsigned int *p;
75
   unsigned long x;
76

    
77
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
78
   /* FIXME - handle failure of get_user() */
79
   get_user_u32(x, addr);
80
   fpa11->fType[Fn] = (x >> 14) & 0x00000003;
81

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

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

    
105
static inline
106
void storeSingle(const unsigned int Fn, target_ulong addr)
107
{
108
   FPA11 *fpa11 = GET_FPA11();
109
   float32 val;
110
   register unsigned int *p = (unsigned int*)&val;
111

    
112
   switch (fpa11->fType[Fn])
113
   {
114
      case typeDouble:
115
         val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
116
      break;
117

    
118
      case typeExtended:
119
         val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
120
      break;
121

    
122
      default: val = fpa11->fpreg[Fn].fSingle;
123
   }
124

    
125
   /* FIXME - handle put_user() failures */
126
   put_user_u32(p[0], addr);
127
}
128

    
129
static inline
130
void storeDouble(const unsigned int Fn, target_ulong addr)
131
{
132
   FPA11 *fpa11 = GET_FPA11();
133
   float64 val;
134
   register unsigned int *p = (unsigned int*)&val;
135

    
136
   switch (fpa11->fType[Fn])
137
   {
138
      case typeSingle:
139
         val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
140
      break;
141

    
142
      case typeExtended:
143
         val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
144
      break;
145

    
146
      default: val = fpa11->fpreg[Fn].fDouble;
147
   }
148
   /* FIXME - handle put_user() failures */
149
#ifdef HOST_WORDS_BIGENDIAN
150
   put_user_u32(p[0], addr);        /* msw */
151
   put_user_u32(p[1], addr + 4);        /* lsw */
152
#else
153
   put_user_u32(p[1], addr);        /* msw */
154
   put_user_u32(p[0], addr + 4);        /* lsw */
155
#endif
156
}
157

    
158
static inline
159
void storeExtended(const unsigned int Fn, target_ulong addr)
160
{
161
   FPA11 *fpa11 = GET_FPA11();
162
   floatx80 val;
163
   register unsigned int *p = (unsigned int*)&val;
164

    
165
   switch (fpa11->fType[Fn])
166
   {
167
      case typeSingle:
168
         val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
169
      break;
170

    
171
      case typeDouble:
172
         val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
173
      break;
174

    
175
      default: val = fpa11->fpreg[Fn].fExtended;
176
   }
177

    
178
   /* FIXME - handle put_user() failures */
179
   put_user_u32(p[0], addr); /* sign & exp */
180
   put_user_u32(p[1], addr + 8);
181
   put_user_u32(p[2], addr + 4); /* msw */
182
}
183

    
184
static inline
185
void storeMultiple(const unsigned int Fn, target_ulong addr)
186
{
187
   FPA11 *fpa11 = GET_FPA11();
188
   register unsigned int nType, *p;
189

    
190
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
191
   nType = fpa11->fType[Fn];
192

    
193
   switch (nType)
194
   {
195
      case typeSingle:
196
      case typeDouble:
197
      {
198
         put_user_u32(p[0], addr + 8); /* single */
199
         put_user_u32(p[1], addr + 4); /* double msw */
200
         put_user_u32(nType << 14, addr);
201
      }
202
      break;
203

    
204
      case typeExtended:
205
      {
206
         put_user_u32(p[2], addr + 4); /* msw */
207
         put_user_u32(p[1], addr + 8);
208
         put_user_u32((p[0] & 0x80003fff) | (nType << 14), addr);
209
      }
210
      break;
211
   }
212
}
213

    
214
static unsigned int PerformLDF(const unsigned int opcode)
215
{
216
    target_ulong pBase, pAddress, pFinal;
217
    unsigned int nRc = 1,
218
     write_back = WRITE_BACK(opcode);
219

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

    
222
   pBase = readRegister(getRn(opcode));
223
   if (REG_PC == getRn(opcode))
224
   {
225
     pBase += 8;
226
     write_back = 0;
227
   }
228

    
229
   pFinal = pBase;
230
   if (BIT_UP_SET(opcode))
231
     pFinal += getOffset(opcode) * 4;
232
   else
233
     pFinal -= getOffset(opcode) * 4;
234

    
235
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
236

    
237
   switch (opcode & MASK_TRANSFER_LENGTH)
238
   {
239
      case TRANSFER_SINGLE  : loadSingle(getFd(opcode),pAddress);   break;
240
      case TRANSFER_DOUBLE  : loadDouble(getFd(opcode),pAddress);   break;
241
      case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
242
      default: nRc = 0;
243
   }
244

    
245
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
246
   return nRc;
247
}
248

    
249
static unsigned int PerformSTF(const unsigned int opcode)
250
{
251
   target_ulong pBase, pAddress, pFinal;
252
   unsigned int nRc = 1,
253
     write_back = WRITE_BACK(opcode);
254

    
255
   //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
256
   SetRoundingMode(ROUND_TO_NEAREST);
257

    
258
   pBase = readRegister(getRn(opcode));
259
   if (REG_PC == getRn(opcode))
260
   {
261
     pBase += 8;
262
     write_back = 0;
263
   }
264

    
265
   pFinal = pBase;
266
   if (BIT_UP_SET(opcode))
267
     pFinal += getOffset(opcode) * 4;
268
   else
269
     pFinal -= getOffset(opcode) * 4;
270

    
271
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
272

    
273
   switch (opcode & MASK_TRANSFER_LENGTH)
274
   {
275
      case TRANSFER_SINGLE  : storeSingle(getFd(opcode),pAddress);   break;
276
      case TRANSFER_DOUBLE  : storeDouble(getFd(opcode),pAddress);   break;
277
      case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
278
      default: nRc = 0;
279
   }
280

    
281
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
282
   return nRc;
283
}
284

    
285
static unsigned int PerformLFM(const unsigned int opcode)
286
{
287
   unsigned int i, Fd,
288
     write_back = WRITE_BACK(opcode);
289
   target_ulong pBase, pAddress, pFinal;
290

    
291
   pBase = readRegister(getRn(opcode));
292
   if (REG_PC == getRn(opcode))
293
   {
294
     pBase += 8;
295
     write_back = 0;
296
   }
297

    
298
   pFinal = pBase;
299
   if (BIT_UP_SET(opcode))
300
     pFinal += getOffset(opcode) * 4;
301
   else
302
     pFinal -= getOffset(opcode) * 4;
303

    
304
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
305

    
306
   Fd = getFd(opcode);
307
   for (i=getRegisterCount(opcode);i>0;i--)
308
   {
309
     loadMultiple(Fd,pAddress);
310
     pAddress += 12; Fd++;
311
     if (Fd == 8) Fd = 0;
312
   }
313

    
314
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
315
   return 1;
316
}
317

    
318
static unsigned int PerformSFM(const unsigned int opcode)
319
{
320
   unsigned int i, Fd,
321
     write_back = WRITE_BACK(opcode);
322
   target_ulong pBase, pAddress, pFinal;
323

    
324
   pBase = readRegister(getRn(opcode));
325
   if (REG_PC == getRn(opcode))
326
   {
327
     pBase += 8;
328
     write_back = 0;
329
   }
330

    
331
   pFinal = pBase;
332
   if (BIT_UP_SET(opcode))
333
     pFinal += getOffset(opcode) * 4;
334
   else
335
     pFinal -= getOffset(opcode) * 4;
336

    
337
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
338

    
339
   Fd = getFd(opcode);
340
   for (i=getRegisterCount(opcode);i>0;i--)
341
   {
342
     storeMultiple(Fd,pAddress);
343
     pAddress += 12; Fd++;
344
     if (Fd == 8) Fd = 0;
345
   }
346

    
347
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
348
   return 1;
349
}
350

    
351
#if 1
352
unsigned int EmulateCPDT(const unsigned int opcode)
353
{
354
  unsigned int nRc = 0;
355

    
356
  //printk("EmulateCPDT(0x%08x)\n",opcode);
357

    
358
  if (LDF_OP(opcode))
359
  {
360
    nRc = PerformLDF(opcode);
361
  }
362
  else if (LFM_OP(opcode))
363
  {
364
    nRc = PerformLFM(opcode);
365
  }
366
  else if (STF_OP(opcode))
367
  {
368
    nRc = PerformSTF(opcode);
369
  }
370
  else if (SFM_OP(opcode))
371
  {
372
    nRc = PerformSFM(opcode);
373
  }
374
  else
375
  {
376
    nRc = 0;
377
  }
378

    
379
  return nRc;
380
}
381
#endif