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"
27 #include "fpmodule.inl"
29 #include <asm/uaccess.h>
32 void loadSingle(const unsigned int Fn
,const unsigned int *pMem
)
34 FPA11
*fpa11
= GET_FPA11();
35 fpa11
->fType
[Fn
] = typeSingle
;
36 get_user(fpa11
->fpreg
[Fn
].fSingle
, pMem
);
40 void loadDouble(const unsigned int Fn
,const unsigned int *pMem
)
42 FPA11
*fpa11
= GET_FPA11();
44 p
= (unsigned int*)&fpa11
->fpreg
[Fn
].fDouble
;
45 fpa11
->fType
[Fn
] = typeDouble
;
46 get_user(p
[0], &pMem
[1]);
47 get_user(p
[1], &pMem
[0]); /* sign & exponent */
51 void loadExtended(const unsigned int Fn
,const unsigned int *pMem
)
53 FPA11
*fpa11
= GET_FPA11();
55 p
= (unsigned int*)&fpa11
->fpreg
[Fn
].fExtended
;
56 fpa11
->fType
[Fn
] = typeExtended
;
57 get_user(p
[0], &pMem
[0]); /* sign & exponent */
58 get_user(p
[1], &pMem
[2]); /* ls bits */
59 get_user(p
[2], &pMem
[1]); /* ms bits */
63 void loadMultiple(const unsigned int Fn
,const unsigned int *pMem
)
65 FPA11
*fpa11
= GET_FPA11();
66 register unsigned int *p
;
69 p
= (unsigned int*)&(fpa11
->fpreg
[Fn
]);
70 get_user(x
, &pMem
[0]);
71 fpa11
->fType
[Fn
] = (x
>> 14) & 0x00000003;
73 switch (fpa11
->fType
[Fn
])
78 get_user(p
[0], &pMem
[2]); /* Single */
79 get_user(p
[1], &pMem
[1]); /* double msw */
86 get_user(p
[1], &pMem
[2]);
87 get_user(p
[2], &pMem
[1]); /* msw */
88 p
[0] = (x
& 0x80003fff);
95 void storeSingle(const unsigned int Fn
,unsigned int *pMem
)
97 FPA11
*fpa11
= GET_FPA11();
104 switch (fpa11
->fType
[Fn
])
107 val
.f
= float64_to_float32(fpa11
->fpreg
[Fn
].fDouble
);
111 val
.f
= floatx80_to_float32(fpa11
->fpreg
[Fn
].fExtended
);
114 default: val
.f
= fpa11
->fpreg
[Fn
].fSingle
;
117 put_user(val
.i
[0], pMem
);
121 void storeDouble(const unsigned int Fn
,unsigned int *pMem
)
123 FPA11
*fpa11
= GET_FPA11();
130 switch (fpa11
->fType
[Fn
])
133 val
.f
= float32_to_float64(fpa11
->fpreg
[Fn
].fSingle
);
137 val
.f
= floatx80_to_float64(fpa11
->fpreg
[Fn
].fExtended
);
140 default: val
.f
= fpa11
->fpreg
[Fn
].fDouble
;
143 put_user(val
.i
[1], &pMem
[0]); /* msw */
144 put_user(val
.i
[0], &pMem
[1]); /* lsw */
148 void storeExtended(const unsigned int Fn
,unsigned int *pMem
)
150 FPA11
*fpa11
= GET_FPA11();
157 switch (fpa11
->fType
[Fn
])
160 val
.f
= float32_to_floatx80(fpa11
->fpreg
[Fn
].fSingle
);
164 val
.f
= float64_to_floatx80(fpa11
->fpreg
[Fn
].fDouble
);
167 default: val
.f
= fpa11
->fpreg
[Fn
].fExtended
;
170 put_user(val
.i
[0], &pMem
[0]); /* sign & exp */
171 put_user(val
.i
[1], &pMem
[2]);
172 put_user(val
.i
[2], &pMem
[1]); /* msw */
176 void storeMultiple(const unsigned int Fn
,unsigned int *pMem
)
178 FPA11
*fpa11
= GET_FPA11();
179 register unsigned int nType
, *p
;
181 p
= (unsigned int*)&(fpa11
->fpreg
[Fn
]);
182 nType
= fpa11
->fType
[Fn
];
189 put_user(p
[0], &pMem
[2]); /* single */
190 put_user(p
[1], &pMem
[1]); /* double msw */
191 put_user(nType
<< 14, &pMem
[0]);
197 put_user(p
[2], &pMem
[1]); /* msw */
198 put_user(p
[1], &pMem
[2]);
199 put_user((p
[0] & 0x80003fff) | (nType
<< 14), &pMem
[0]);
205 unsigned int PerformLDF(const unsigned int opcode
)
207 unsigned int *pBase
, *pAddress
, *pFinal
, nRc
= 1,
208 write_back
= WRITE_BACK(opcode
);
210 //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
212 pBase
= (unsigned int*)readRegister(getRn(opcode
));
213 if (REG_PC
== getRn(opcode
))
220 if (BIT_UP_SET(opcode
))
221 pFinal
+= getOffset(opcode
);
223 pFinal
-= getOffset(opcode
);
225 if (PREINDEXED(opcode
)) pAddress
= pFinal
; else pAddress
= pBase
;
227 switch (opcode
& MASK_TRANSFER_LENGTH
)
229 case TRANSFER_SINGLE
: loadSingle(getFd(opcode
),pAddress
); break;
230 case TRANSFER_DOUBLE
: loadDouble(getFd(opcode
),pAddress
); break;
231 case TRANSFER_EXTENDED
: loadExtended(getFd(opcode
),pAddress
); break;
235 if (write_back
) writeRegister(getRn(opcode
),(unsigned int)pFinal
);
239 unsigned int PerformSTF(const unsigned int opcode
)
241 unsigned int *pBase
, *pAddress
, *pFinal
, nRc
= 1,
242 write_back
= WRITE_BACK(opcode
);
244 //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
245 SetRoundingMode(ROUND_TO_NEAREST
);
247 pBase
= (unsigned int*)readRegister(getRn(opcode
));
248 if (REG_PC
== getRn(opcode
))
255 if (BIT_UP_SET(opcode
))
256 pFinal
+= getOffset(opcode
);
258 pFinal
-= getOffset(opcode
);
260 if (PREINDEXED(opcode
)) pAddress
= pFinal
; else pAddress
= pBase
;
262 switch (opcode
& MASK_TRANSFER_LENGTH
)
264 case TRANSFER_SINGLE
: storeSingle(getFd(opcode
),pAddress
); break;
265 case TRANSFER_DOUBLE
: storeDouble(getFd(opcode
),pAddress
); break;
266 case TRANSFER_EXTENDED
: storeExtended(getFd(opcode
),pAddress
); break;
270 if (write_back
) writeRegister(getRn(opcode
),(unsigned int)pFinal
);
274 unsigned int PerformLFM(const unsigned int opcode
)
276 unsigned int i
, Fd
, *pBase
, *pAddress
, *pFinal
,
277 write_back
= WRITE_BACK(opcode
);
279 pBase
= (unsigned int*)readRegister(getRn(opcode
));
280 if (REG_PC
== getRn(opcode
))
287 if (BIT_UP_SET(opcode
))
288 pFinal
+= getOffset(opcode
);
290 pFinal
-= getOffset(opcode
);
292 if (PREINDEXED(opcode
)) pAddress
= pFinal
; else pAddress
= pBase
;
295 for (i
=getRegisterCount(opcode
);i
>0;i
--)
297 loadMultiple(Fd
,pAddress
);
302 if (write_back
) writeRegister(getRn(opcode
),(unsigned int)pFinal
);
306 unsigned int PerformSFM(const unsigned int opcode
)
308 unsigned int i
, Fd
, *pBase
, *pAddress
, *pFinal
,
309 write_back
= WRITE_BACK(opcode
);
311 pBase
= (unsigned int*)readRegister(getRn(opcode
));
312 if (REG_PC
== getRn(opcode
))
319 if (BIT_UP_SET(opcode
))
320 pFinal
+= getOffset(opcode
);
322 pFinal
-= getOffset(opcode
);
324 if (PREINDEXED(opcode
)) pAddress
= pFinal
; else pAddress
= pBase
;
327 for (i
=getRegisterCount(opcode
);i
>0;i
--)
329 storeMultiple(Fd
,pAddress
);
334 if (write_back
) writeRegister(getRn(opcode
),(unsigned int)pFinal
);
339 unsigned int EmulateCPDT(const unsigned int opcode
)
341 unsigned int nRc
= 0;
343 //printk("EmulateCPDT(0x%08x)\n",opcode);
347 nRc
= PerformLDF(opcode
);
349 else if (LFM_OP(opcode
))
351 nRc
= PerformLFM(opcode
);
353 else if (STF_OP(opcode
))
355 nRc
= PerformSTF(opcode
);
357 else if (SFM_OP(opcode
))
359 nRc
= PerformSFM(opcode
);