patch-2.4.22 linux-2.4.22/arch/arm/nwfpe/fpa11_cpdo.c
Next file: linux-2.4.22/arch/arm/nwfpe/fpa11_cpdt.c
Previous file: linux-2.4.22/arch/arm/nwfpe/fpa11.inl
Back to the patch index
Back to the overall index
- Lines: 207
- Date:
2003-08-25 04:44:39.000000000 -0700
- Orig file:
linux-2.4.21/arch/arm/nwfpe/fpa11_cpdo.c
- Orig date:
2001-08-12 11:13:59.000000000 -0700
diff -urN linux-2.4.21/arch/arm/nwfpe/fpa11_cpdo.c linux-2.4.22/arch/arm/nwfpe/fpa11_cpdo.c
@@ -1,6 +1,7 @@
/*
NetWinder Floating Point Emulator
(c) Rebel.COM, 1998,1999
+ (c) Philip Blundell, 2001
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
@@ -22,96 +23,109 @@
#include "fpa11.h"
#include "fpopcode.h"
-unsigned int SingleCPDO(const unsigned int opcode);
-unsigned int DoubleCPDO(const unsigned int opcode);
-unsigned int ExtendedCPDO(const unsigned int opcode);
+unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);
+unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);
+unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);
unsigned int EmulateCPDO(const unsigned int opcode)
{
- FPA11 *fpa11 = GET_FPA11();
- unsigned int Fd, nType, nDest, nRc = 1;
-
- //printk("EmulateCPDO(0x%08x)\n",opcode);
-
- /* Get the destination size. If not valid let Linux perform
- an invalid instruction trap. */
- nDest = getDestinationSize(opcode);
- if (typeNone == nDest) return 0;
-
- SetRoundingMode(opcode);
-
- /* Compare the size of the operands in Fn and Fm.
- Choose the largest size and perform operations in that size,
- in order to make use of all the precision of the operands.
- If Fm is a constant, we just grab a constant of a size
- matching the size of the operand in Fn. */
- if (MONADIC_INSTRUCTION(opcode))
- nType = nDest;
- else
- nType = fpa11->fType[getFn(opcode)];
-
- if (!CONSTANT_FM(opcode))
- {
- register unsigned int Fm = getFm(opcode);
- if (nType < fpa11->fType[Fm])
- {
- nType = fpa11->fType[Fm];
- }
- }
-
- switch (nType)
- {
- case typeSingle : nRc = SingleCPDO(opcode); break;
- case typeDouble : nRc = DoubleCPDO(opcode); break;
- case typeExtended : nRc = ExtendedCPDO(opcode); break;
- default : nRc = 0;
- }
-
- /* If the operation succeeded, check to see if the result in the
- destination register is the correct size. If not force it
- to be. */
- Fd = getFd(opcode);
- nType = fpa11->fType[Fd];
- if ((0 != nRc) && (nDest != nType))
- {
- switch (nDest)
- {
- case typeSingle:
- {
- if (typeDouble == nType)
- fpa11->fpreg[Fd].fSingle =
- float64_to_float32(fpa11->fpreg[Fd].fDouble);
- else
- fpa11->fpreg[Fd].fSingle =
- floatx80_to_float32(fpa11->fpreg[Fd].fExtended);
- }
- break;
-
- case typeDouble:
- {
- if (typeSingle == nType)
- fpa11->fpreg[Fd].fDouble =
- float32_to_float64(fpa11->fpreg[Fd].fSingle);
- else
- fpa11->fpreg[Fd].fDouble =
- floatx80_to_float64(fpa11->fpreg[Fd].fExtended);
- }
- break;
-
- case typeExtended:
- {
- if (typeSingle == nType)
- fpa11->fpreg[Fd].fExtended =
- float32_to_floatx80(fpa11->fpreg[Fd].fSingle);
- else
- fpa11->fpreg[Fd].fExtended =
- float64_to_floatx80(fpa11->fpreg[Fd].fDouble);
- }
- break;
- }
-
- fpa11->fType[Fd] = nDest;
- }
-
- return nRc;
+ FPA11 *fpa11 = GET_FPA11();
+ FPREG *rFd;
+ unsigned int nType, nDest, nRc;
+
+ /* Get the destination size. If not valid let Linux perform
+ an invalid instruction trap. */
+ nDest = getDestinationSize(opcode);
+ if (typeNone == nDest)
+ return 0;
+
+ SetRoundingMode(opcode);
+
+ /* Compare the size of the operands in Fn and Fm.
+ Choose the largest size and perform operations in that size,
+ in order to make use of all the precision of the operands.
+ If Fm is a constant, we just grab a constant of a size
+ matching the size of the operand in Fn. */
+ if (MONADIC_INSTRUCTION(opcode))
+ nType = nDest;
+ else
+ nType = fpa11->fType[getFn(opcode)];
+
+ if (!CONSTANT_FM(opcode)) {
+ register unsigned int Fm = getFm(opcode);
+ if (nType < fpa11->fType[Fm]) {
+ nType = fpa11->fType[Fm];
+ }
+ }
+
+ rFd = &fpa11->fpreg[getFd(opcode)];
+
+ switch (nType) {
+ case typeSingle:
+ nRc = SingleCPDO(opcode, rFd);
+ break;
+ case typeDouble:
+ nRc = DoubleCPDO(opcode, rFd);
+ break;
+#ifdef CONFIG_FPE_NWFPE_XP
+ case typeExtended:
+ nRc = ExtendedCPDO(opcode, rFd);
+ break;
+#endif
+ default:
+ nRc = 0;
+ }
+
+ /* The CPDO functions used to always set the destination type
+ to be the same as their working size. */
+
+ if (nRc != 0) {
+ /* If the operation succeeded, check to see if the result in the
+ destination register is the correct size. If not force it
+ to be. */
+
+ fpa11->fType[getFd(opcode)] = nDest;
+
+#ifdef CONFIG_FPE_NWFPE_XP
+ if (nDest != nType) {
+ switch (nDest) {
+ case typeSingle:
+ {
+ if (typeDouble == nType)
+ rFd->fSingle = float64_to_float32(rFd->fDouble);
+ else
+ rFd->fSingle = floatx80_to_float32(rFd->fExtended);
+ }
+ break;
+
+ case typeDouble:
+ {
+ if (typeSingle == nType)
+ rFd->fDouble = float32_to_float64(rFd->fSingle);
+ else
+ rFd->fDouble = floatx80_to_float64(rFd->fExtended);
+ }
+ break;
+
+ case typeExtended:
+ {
+ if (typeSingle == nType)
+ rFd->fExtended = float32_to_floatx80(rFd->fSingle);
+ else
+ rFd->fExtended = float64_to_floatx80(rFd->fDouble);
+ }
+ break;
+ }
+ }
+#else
+ if (nDest != nType) {
+ if (nDest == typeSingle)
+ rFd->fSingle = float64_to_float32(rFd->fDouble);
+ else
+ rFd->fDouble = float32_to_float64(rFd->fSingle);
+ }
+#endif
+ }
+
+ return nRc;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)