1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "fpa11.h"
24#include "fpopcode.h"
25
26unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
27unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
28unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd);
29
30unsigned int EmulateCPDO(const unsigned int opcode)
31{
32 FPA11 *fpa11 = GET_FPA11();
33 FPREG *rFd;
34 unsigned int nType, nDest, nRc;
35 struct roundingData roundData;
36
37
38
39 nDest = getDestinationSize(opcode);
40 if (typeNone == nDest)
41 return 0;
42
43 roundData.mode = SetRoundingMode(opcode);
44 roundData.precision = SetRoundingPrecision(opcode);
45 roundData.exception = 0;
46
47
48
49
50
51
52 if (MONADIC_INSTRUCTION(opcode))
53 nType = nDest;
54 else
55 nType = fpa11->fType[getFn(opcode)];
56
57 if (!CONSTANT_FM(opcode)) {
58 register unsigned int Fm = getFm(opcode);
59 if (nType < fpa11->fType[Fm]) {
60 nType = fpa11->fType[Fm];
61 }
62 }
63
64 rFd = &fpa11->fpreg[getFd(opcode)];
65
66 switch (nType) {
67 case typeSingle:
68 nRc = SingleCPDO(&roundData, opcode, rFd);
69 break;
70 case typeDouble:
71 nRc = DoubleCPDO(&roundData, opcode, rFd);
72 break;
73#ifdef CONFIG_FPE_NWFPE_XP
74 case typeExtended:
75 nRc = ExtendedCPDO(&roundData, opcode, rFd);
76 break;
77#endif
78 default:
79 nRc = 0;
80 }
81
82
83
84
85 if (nRc != 0) {
86
87
88
89
90 fpa11->fType[getFd(opcode)] = nDest;
91
92#ifdef CONFIG_FPE_NWFPE_XP
93 if (nDest != nType) {
94 switch (nDest) {
95 case typeSingle:
96 {
97 if (typeDouble == nType)
98 rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
99 else
100 rFd->fSingle = floatx80_to_float32(&roundData, rFd->fExtended);
101 }
102 break;
103
104 case typeDouble:
105 {
106 if (typeSingle == nType)
107 rFd->fDouble = float32_to_float64(rFd->fSingle);
108 else
109 rFd->fDouble = floatx80_to_float64(&roundData, rFd->fExtended);
110 }
111 break;
112
113 case typeExtended:
114 {
115 if (typeSingle == nType)
116 rFd->fExtended = float32_to_floatx80(rFd->fSingle);
117 else
118 rFd->fExtended = float64_to_floatx80(rFd->fDouble);
119 }
120 break;
121 }
122 }
123#else
124 if (nDest != nType) {
125 if (nDest == typeSingle)
126 rFd->fSingle = float64_to_float32(&roundData, rFd->fDouble);
127 else
128 rFd->fDouble = float32_to_float64(rFd->fSingle);
129 }
130#endif
131 }
132
133 if (roundData.exception)
134 float_raise(roundData.exception);
135
136 return nRc;
137}
138