2
NetWinder Floating Point Emulator
3
(c) Rebel.com, 1998-1999
4
(c) Philip Blundell, 1998
6
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
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.
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.
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.
24
#include "softfloat.h"
26
//#include "fpmodule.h"
27
//#include "fpmodule.inl"
29
//#include <asm/uaccess.h>
32
void loadSingle(const unsigned int Fn,const unsigned int *pMem)
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);
41
void loadDouble(const unsigned int Fn,const unsigned int *pMem)
43
target_ulong addr = (target_ulong)(long)pMem;
44
FPA11 *fpa11 = GET_FPA11();
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);
52
p[0] = tget32(addr + 4);
53
p[1] = tget32(addr); /* sign & exponent */
58
void loadExtended(const unsigned int Fn,const unsigned int *pMem)
60
target_ulong addr = (target_ulong)(long)pMem;
61
FPA11 *fpa11 = GET_FPA11();
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 */
71
void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
73
target_ulong addr = (target_ulong)(long)pMem;
74
FPA11 *fpa11 = GET_FPA11();
75
register unsigned int *p;
78
p = (unsigned int*)&(fpa11->fpreg[Fn]);
80
fpa11->fType[Fn] = (x >> 14) & 0x00000003;
82
switch (fpa11->fType[Fn])
87
p[0] = tget32(addr + 8); /* Single */
88
p[1] = tget32(addr + 4); /* double msw */
95
p[1] = tget32(addr + 8);
96
p[2] = tget32(addr + 4); /* msw */
97
p[0] = (x & 0x80003fff);
104
void storeSingle(const unsigned int Fn,unsigned int *pMem)
106
target_ulong addr = (target_ulong)(long)pMem;
107
FPA11 *fpa11 = GET_FPA11();
109
register unsigned int *p = (unsigned int*)&val;
111
switch (fpa11->fType[Fn])
114
val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
118
val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
121
default: val = fpa11->fpreg[Fn].fSingle;
128
void storeDouble(const unsigned int Fn,unsigned int *pMem)
130
target_ulong addr = (target_ulong)(long)pMem;
131
FPA11 *fpa11 = GET_FPA11();
133
register unsigned int *p = (unsigned int*)&val;
135
switch (fpa11->fType[Fn])
138
val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
142
val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
145
default: val = fpa11->fpreg[Fn].fDouble;
147
#ifdef WORDS_BIGENDIAN
148
tput32(addr, p[0]); /* msw */
149
tput32(addr + 4, p[1]); /* lsw */
151
tput32(addr, p[1]); /* msw */
152
tput32(addr + 4, p[0]); /* lsw */
157
void storeExtended(const unsigned int Fn,unsigned int *pMem)
159
target_ulong addr = (target_ulong)(long)pMem;
160
FPA11 *fpa11 = GET_FPA11();
162
register unsigned int *p = (unsigned int*)&val;
164
switch (fpa11->fType[Fn])
167
val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
171
val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
174
default: val = fpa11->fpreg[Fn].fExtended;
177
tput32(addr, p[0]); /* sign & exp */
178
tput32(addr + 8, p[1]);
179
tput32(addr + 4, p[2]); /* msw */
183
void storeMultiple(const unsigned int Fn,unsigned int *pMem)
185
target_ulong addr = (target_ulong)(long)pMem;
186
FPA11 *fpa11 = GET_FPA11();
187
register unsigned int nType, *p;
189
p = (unsigned int*)&(fpa11->fpreg[Fn]);
190
nType = fpa11->fType[Fn];
197
tput32(addr + 8, p[0]); /* single */
198
tput32(addr + 4, p[1]); /* double msw */
199
tput32(addr, nType << 14);
205
tput32(addr + 4, p[2]); /* msw */
206
tput32(addr + 8, p[1]);
207
tput32(addr, (p[0] & 0x80003fff) | (nType << 14));
213
unsigned int PerformLDF(const unsigned int opcode)
215
unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
216
write_back = WRITE_BACK(opcode);
218
//printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
220
pBase = (unsigned int*)readRegister(getRn(opcode));
221
if (REG_PC == getRn(opcode))
228
if (BIT_UP_SET(opcode))
229
pFinal += getOffset(opcode);
231
pFinal -= getOffset(opcode);
233
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
235
switch (opcode & MASK_TRANSFER_LENGTH)
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;
243
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
247
unsigned int PerformSTF(const unsigned int opcode)
249
unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
250
write_back = WRITE_BACK(opcode);
252
//printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
253
SetRoundingMode(ROUND_TO_NEAREST);
255
pBase = (unsigned int*)readRegister(getRn(opcode));
256
if (REG_PC == getRn(opcode))
263
if (BIT_UP_SET(opcode))
264
pFinal += getOffset(opcode);
266
pFinal -= getOffset(opcode);
268
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
270
switch (opcode & MASK_TRANSFER_LENGTH)
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;
278
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
282
unsigned int PerformLFM(const unsigned int opcode)
284
unsigned int i, Fd, *pBase, *pAddress, *pFinal,
285
write_back = WRITE_BACK(opcode);
287
pBase = (unsigned int*)readRegister(getRn(opcode));
288
if (REG_PC == getRn(opcode))
295
if (BIT_UP_SET(opcode))
296
pFinal += getOffset(opcode);
298
pFinal -= getOffset(opcode);
300
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
303
for (i=getRegisterCount(opcode);i>0;i--)
305
loadMultiple(Fd,pAddress);
310
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
314
unsigned int PerformSFM(const unsigned int opcode)
316
unsigned int i, Fd, *pBase, *pAddress, *pFinal,
317
write_back = WRITE_BACK(opcode);
319
pBase = (unsigned int*)readRegister(getRn(opcode));
320
if (REG_PC == getRn(opcode))
327
if (BIT_UP_SET(opcode))
328
pFinal += getOffset(opcode);
330
pFinal -= getOffset(opcode);
332
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
335
for (i=getRegisterCount(opcode);i>0;i--)
337
storeMultiple(Fd,pAddress);
342
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
347
unsigned int EmulateCPDT(const unsigned int opcode)
349
unsigned int nRc = 0;
351
//printk("EmulateCPDT(0x%08x)\n",opcode);
355
nRc = PerformLDF(opcode);
357
else if (LFM_OP(opcode))
359
nRc = PerformLFM(opcode);
361
else if (STF_OP(opcode))
363
nRc = PerformSTF(opcode);
365
else if (SFM_OP(opcode))
367
nRc = PerformSFM(opcode);