Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / arm / nwfpe / fpa11_cpdo.c
index 1bea674..4a31dfd 100644 (file)
 #include "fpa11.h"
 #include "fpopcode.h"
 
-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 SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
+unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
+unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
 
 unsigned int EmulateCPDO(const unsigned int opcode)
 {
        FPA11 *fpa11 = GET_FPA11();
        FPREG *rFd;
        unsigned int nType, nDest, nRc;
+       struct roundingData roundData;
 
        /* Get the destination size.  If not valid let Linux perform
           an invalid instruction trap. */
@@ -40,7 +41,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
        if (typeNone == nDest)
                return 0;
 
-       SetRoundingMode(opcode);
+       roundData.mode = SetRoundingMode(opcode);
+       roundData.precision = SetRoundingPrecision(opcode);
+       roundData.exception = 0;
 
        /* Compare the size of the operands in Fn and Fm.
           Choose the largest size and perform operations in that size,
@@ -63,14 +66,14 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 
        switch (nType) {
        case typeSingle:
-               nRc = SingleCPDO(opcode, rFd);
+               nRc = SingleCPDO(&roundData, opcode, rFd);
                break;
        case typeDouble:
-               nRc = DoubleCPDO(opcode, rFd);
+               nRc = DoubleCPDO(&roundData, opcode, rFd);
                break;
 #ifdef CONFIG_FPE_NWFPE_XP
        case typeExtended:
-               nRc = ExtendedCPDO(opcode, rFd);
+               nRc = ExtendedCPDO(&roundData, opcode, rFd);
                break;
 #endif
        default:
@@ -93,9 +96,9 @@ unsigned int EmulateCPDO(const unsigned int opcode)
                        case typeSingle:
                                {
                                        if (typeDouble == nType)
-                                               rFd->fSingle = float64_to_float32(rFd->fDouble);
+                                               rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
                                        else
-                                               rFd->fSingle = floatx80_to_float32(rFd->fExtended);
+                                               rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
                                }
                                break;
 
@@ -104,7 +107,7 @@ unsigned int EmulateCPDO(const unsigned int opcode)
                                        if (typeSingle == nType)
                                                rFd->fDouble = float32_to_float64(rFd->fSingle);
                                        else
-                                               rFd->fDouble = floatx80_to_float64(rFd->fExtended);
+                                               rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
                                }
                                break;
 
@@ -121,12 +124,15 @@ unsigned int EmulateCPDO(const unsigned int opcode)
 #else
                if (nDest != nType) {
                        if (nDest == typeSingle)
-                               rFd->fSingle = float64_to_float32(rFd->fDouble);
+                               rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
                        else
                                rFd->fDouble = float32_to_float64(rFd->fSingle);
                }
 #endif
        }
 
+       if (roundData.exception)
+               float_raise(roundData.exception);
+
        return nRc;
 }