0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "fpa11.h"
0012 #include "fpopcode.h"
0013
0014 unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
0015 unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
0016 unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
0017
0018 unsigned int EmulateCPDO(const unsigned int opcode)
0019 {
0020 FPA11 *fpa11 = GET_FPA11();
0021 FPREG *rFd;
0022 unsigned int nType, nDest, nRc;
0023 struct roundingData roundData;
0024
0025
0026
0027 nDest = getDestinationSize(opcode);
0028 if (typeNone == nDest)
0029 return 0;
0030
0031 roundData.mode = SetRoundingMode(opcode);
0032 roundData.precision = SetRoundingPrecision(opcode);
0033 roundData.exception = 0;
0034
0035
0036
0037
0038
0039
0040 if (MONADIC_INSTRUCTION(opcode))
0041 nType = nDest;
0042 else
0043 nType = fpa11->fType[getFn(opcode)];
0044
0045 if (!CONSTANT_FM(opcode)) {
0046 register unsigned int Fm = getFm(opcode);
0047 if (nType < fpa11->fType[Fm]) {
0048 nType = fpa11->fType[Fm];
0049 }
0050 }
0051
0052 rFd = &fpa11->fpreg[getFd(opcode)];
0053
0054 switch (nType) {
0055 case typeSingle:
0056 nRc = SingleCPDO(&roundData, opcode, rFd);
0057 break;
0058 case typeDouble:
0059 nRc = DoubleCPDO(&roundData, opcode, rFd);
0060 break;
0061 #ifdef CONFIG_FPE_NWFPE_XP
0062 case typeExtended:
0063 nRc = ExtendedCPDO(&roundData, opcode, rFd);
0064 break;
0065 #endif
0066 default:
0067 nRc = 0;
0068 }
0069
0070
0071
0072
0073 if (nRc != 0) {
0074
0075
0076
0077
0078 fpa11->fType[getFd(opcode)] = nDest;
0079
0080 #ifdef CONFIG_FPE_NWFPE_XP
0081 if (nDest != nType) {
0082 switch (nDest) {
0083 case typeSingle:
0084 {
0085 if (typeDouble == nType)
0086 rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
0087 else
0088 rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
0089 }
0090 break;
0091
0092 case typeDouble:
0093 {
0094 if (typeSingle == nType)
0095 rFd->fDouble = float32_to_float64(rFd->fSingle);
0096 else
0097 rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
0098 }
0099 break;
0100
0101 case typeExtended:
0102 {
0103 if (typeSingle == nType)
0104 rFd->fExtended = float32_to_floatx80(rFd->fSingle);
0105 else
0106 rFd->fExtended = float64_to_floatx80(rFd->fDouble);
0107 }
0108 break;
0109 }
0110 }
0111 #else
0112 if (nDest != nType) {
0113 if (nDest == typeSingle)
0114 rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
0115 else
0116 rFd->fDouble = float32_to_float64(rFd->fSingle);
0117 }
0118 #endif
0119 }
0120
0121 if (roundData.exception)
0122 float_raise(roundData.exception);
0123
0124 return nRc;
0125 }