~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to target-arm/nwfpe/fpa11_cpdt.c

  • Committer: bellard
  • Date: 2007-02-05 20:46:55 UTC
  • Revision ID: git-v1:7b9c30c5eecdbfc08ce18e4d386a5486289f0f78
update


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2394 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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