patch-2.3.7 linux/arch/arm/nwfpe/fpa11_cpdo.c
Next file: linux/arch/arm/nwfpe/fpa11_cpdt.c
Previous file: linux/arch/arm/nwfpe/fpa11.inl
Back to the patch index
Back to the overall index
- Lines: 118
- Date:
Thu Jun 17 01:11:35 1999
- Orig file:
v2.3.6/linux/arch/arm/nwfpe/fpa11_cpdo.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.6/linux/arch/arm/nwfpe/fpa11_cpdo.c linux/arch/arm/nwfpe/fpa11_cpdo.c
@@ -0,0 +1,117 @@
+/*
+ NetWinder Floating Point Emulator
+ (c) Corel Computer Corporation, 1998
+
+ Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "config.h"
+#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 EmulateCPDO(const unsigned int opcode)
+{
+ unsigned int Fd, nType, nDest, nRc = 1;
+
+ //fp_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->fpreg[getFn(opcode)].fType;
+
+ if (!CONSTANT_FM(opcode))
+ {
+ register unsigned int Fm = getFm(opcode);
+ if (nType < fpa11->fpreg[Fm].fType)
+ {
+ nType = fpa11->fpreg[Fm].fType;
+ }
+ }
+
+ 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->fpreg[Fd].fType;
+ if ((0 != nRc) && (nDest != nType))
+ {
+ switch (nDest)
+ {
+ case typeSingle:
+ {
+ if (typeDouble == nType)
+ fpa11->fpreg[Fd].fValue.fSingle =
+ float64_to_float32(fpa11->fpreg[Fd].fValue.fDouble);
+ else
+ fpa11->fpreg[Fd].fValue.fSingle =
+ floatx80_to_float32(fpa11->fpreg[Fd].fValue.fExtended);
+ }
+ break;
+
+ case typeDouble:
+ {
+ if (typeSingle == nType)
+ fpa11->fpreg[Fd].fValue.fDouble =
+ float32_to_float64(fpa11->fpreg[Fd].fValue.fSingle);
+ else
+ fpa11->fpreg[Fd].fValue.fDouble =
+ floatx80_to_float64(fpa11->fpreg[Fd].fValue.fExtended);
+ }
+ break;
+
+ case typeExtended:
+ {
+ if (typeSingle == nType)
+ fpa11->fpreg[Fd].fValue.fExtended =
+ float32_to_floatx80(fpa11->fpreg[Fd].fValue.fSingle);
+ else
+ fpa11->fpreg[Fd].fValue.fExtended =
+ float64_to_floatx80(fpa11->fpreg[Fd].fValue.fDouble);
+ }
+ break;
+ }
+
+ fpa11->fpreg[Fd].fType = nDest;
+ }
+
+ return nRc;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)