|
|
1.1 root 1: /*
2: NetWinder Floating Point Emulator
3: (c) Rebel.COM, 1998,1999
4:
5: Direct questions, comments to Scott Bambrough <[email protected]>
6:
7: This program is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2 of the License, or
10: (at your option) any later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
1.1.1.3 ! root 18: along with this program; if not, see <http://www.gnu.org/licenses/>.
1.1 root 19: */
20:
21: #include "fpa11.h"
22: #include "fpopcode.h"
23:
24: unsigned int EmulateCPDO(const unsigned int opcode)
25: {
26: FPA11 *fpa11 = GET_FPA11();
27: unsigned int Fd, nType, nDest, nRc = 1;
28:
29: //printk("EmulateCPDO(0x%08x)\n",opcode);
30:
31: /* Get the destination size. If not valid let Linux perform
32: an invalid instruction trap. */
33: nDest = getDestinationSize(opcode);
34: if (typeNone == nDest) return 0;
35:
36: SetRoundingMode(opcode);
37:
38: /* Compare the size of the operands in Fn and Fm.
39: Choose the largest size and perform operations in that size,
40: in order to make use of all the precision of the operands.
41: If Fm is a constant, we just grab a constant of a size
42: matching the size of the operand in Fn. */
43: if (MONADIC_INSTRUCTION(opcode))
44: nType = nDest;
45: else
46: nType = fpa11->fType[getFn(opcode)];
47:
48: if (!CONSTANT_FM(opcode))
49: {
50: register unsigned int Fm = getFm(opcode);
51: if (nType < fpa11->fType[Fm])
52: {
53: nType = fpa11->fType[Fm];
54: }
55: }
56:
57: switch (nType)
58: {
59: case typeSingle : nRc = SingleCPDO(opcode); break;
60: case typeDouble : nRc = DoubleCPDO(opcode); break;
61: case typeExtended : nRc = ExtendedCPDO(opcode); break;
62: default : nRc = 0;
63: }
64:
65: /* If the operation succeeded, check to see if the result in the
66: destination register is the correct size. If not force it
67: to be. */
68: Fd = getFd(opcode);
69: nType = fpa11->fType[Fd];
70: if ((0 != nRc) && (nDest != nType))
71: {
72: switch (nDest)
73: {
74: case typeSingle:
75: {
76: if (typeDouble == nType)
77: fpa11->fpreg[Fd].fSingle =
78: float64_to_float32(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
79: else
80: fpa11->fpreg[Fd].fSingle =
81: floatx80_to_float32(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
82: }
83: break;
84:
85: case typeDouble:
86: {
87: if (typeSingle == nType)
88: fpa11->fpreg[Fd].fDouble =
89: float32_to_float64(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
90: else
91: fpa11->fpreg[Fd].fDouble =
92: floatx80_to_float64(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
93: }
94: break;
95:
96: case typeExtended:
97: {
98: if (typeSingle == nType)
99: fpa11->fpreg[Fd].fExtended =
100: float32_to_floatx80(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
101: else
102: fpa11->fpreg[Fd].fExtended =
103: float64_to_floatx80(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
104: }
105: break;
106: }
107:
108: fpa11->fType[Fd] = nDest;
109: }
110:
111: return nRc;
112: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.