Statistics
| Branch: | Revision:

root / target-arm / nwfpe / fpa11_cpdt.c @ 3b46e624

History | View | Annotate | Download (9.1 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
   fpa11->fpreg[Fn].fSingle = tget32(addr);
38
}
39

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

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

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

    
78
   p = (unsigned int*)&(fpa11->fpreg[Fn]);
79
   x = tget32(addr);
80
   fpa11->fType[Fn] = (x >> 14) & 0x00000003;
81

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

    
93
      case typeExtended:
94
      {
95
         p[1] = tget32(addr + 8);
96
         p[2] = tget32(addr + 4);  /* msw */
97
         p[0] = (x & 0x80003fff);
98
      }
99
      break;
100
   }
101
}
102

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

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

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

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

    
124
   tput32(addr, p[0]);
125
}
126

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

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

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

    
145
      default: val = fpa11->fpreg[Fn].fDouble;
146
   }
147
#ifdef WORDS_BIGENDIAN
148
   tput32(addr, p[0]);        /* msw */
149
   tput32(addr + 4, p[1]);        /* lsw */
150
#else
151
   tput32(addr, p[1]);        /* msw */
152
   tput32(addr + 4, p[0]);        /* lsw */
153
#endif
154
}
155

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

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

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

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

    
177
   tput32(addr, p[0]); /* sign & exp */
178
   tput32(addr + 8, p[1]);
179
   tput32(addr + 4, p[2]); /* msw */
180
}
181

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

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

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

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

    
213
unsigned int PerformLDF(const unsigned int opcode)
214
{
215
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
216
     write_back = WRITE_BACK(opcode);
217

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

    
220
   pBase = (unsigned int*)readRegister(getRn(opcode));
221
   if (REG_PC == getRn(opcode))
222
   {
223
     pBase += 2;
224
     write_back = 0;
225
   }
226

    
227
   pFinal = pBase;
228
   if (BIT_UP_SET(opcode))
229
     pFinal += getOffset(opcode);
230
   else
231
     pFinal -= getOffset(opcode);
232

    
233
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
234

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

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

    
247
unsigned int PerformSTF(const unsigned int opcode)
248
{
249
   unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
250
     write_back = WRITE_BACK(opcode);
251

    
252
   //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
253
   SetRoundingMode(ROUND_TO_NEAREST);
254

    
255
   pBase = (unsigned int*)readRegister(getRn(opcode));
256
   if (REG_PC == getRn(opcode))
257
   {
258
     pBase += 2;
259
     write_back = 0;
260
   }
261

    
262
   pFinal = pBase;
263
   if (BIT_UP_SET(opcode))
264
     pFinal += getOffset(opcode);
265
   else
266
     pFinal -= getOffset(opcode);
267

    
268
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
269

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

    
278
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
279
   return nRc;
280
}
281

    
282
unsigned int PerformLFM(const unsigned int opcode)
283
{
284
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
285
     write_back = WRITE_BACK(opcode);
286

    
287
   pBase = (unsigned int*)readRegister(getRn(opcode));
288
   if (REG_PC == getRn(opcode))
289
   {
290
     pBase += 2;
291
     write_back = 0;
292
   }
293

    
294
   pFinal = pBase;
295
   if (BIT_UP_SET(opcode))
296
     pFinal += getOffset(opcode);
297
   else
298
     pFinal -= getOffset(opcode);
299

    
300
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
301

    
302
   Fd = getFd(opcode);
303
   for (i=getRegisterCount(opcode);i>0;i--)
304
   {
305
     loadMultiple(Fd,pAddress);
306
     pAddress += 3; Fd++;
307
     if (Fd == 8) Fd = 0;
308
   }
309

    
310
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
311
   return 1;
312
}
313

    
314
unsigned int PerformSFM(const unsigned int opcode)
315
{
316
   unsigned int i, Fd, *pBase, *pAddress, *pFinal,
317
     write_back = WRITE_BACK(opcode);
318

    
319
   pBase = (unsigned int*)readRegister(getRn(opcode));
320
   if (REG_PC == getRn(opcode))
321
   {
322
     pBase += 2;
323
     write_back = 0;
324
   }
325

    
326
   pFinal = pBase;
327
   if (BIT_UP_SET(opcode))
328
     pFinal += getOffset(opcode);
329
   else
330
     pFinal -= getOffset(opcode);
331

    
332
   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
333

    
334
   Fd = getFd(opcode);
335
   for (i=getRegisterCount(opcode);i>0;i--)
336
   {
337
     storeMultiple(Fd,pAddress);
338
     pAddress += 3; Fd++;
339
     if (Fd == 8) Fd = 0;
340
   }
341

    
342
   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
343
   return 1;
344
}
345

    
346
#if 1
347
unsigned int EmulateCPDT(const unsigned int opcode)
348
{
349
  unsigned int nRc = 0;
350

    
351
  //printk("EmulateCPDT(0x%08x)\n",opcode);
352

    
353
  if (LDF_OP(opcode))
354
  {
355
    nRc = PerformLDF(opcode);
356
  }
357
  else if (LFM_OP(opcode))
358
  {
359
    nRc = PerformLFM(opcode);
360
  }
361
  else if (STF_OP(opcode))
362
  {
363
    nRc = PerformSTF(opcode);
364
  }
365
  else if (SFM_OP(opcode))
366
  {
367
    nRc = PerformSFM(opcode);
368
  }
369
  else
370
  {
371
    nRc = 0;
372
  }
373

    
374
  return nRc;
375
}
376
#endif