|
|
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
18: along with this program; if not, write to the Free Software
19: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20: */
21:
22: #include "fpa11.h"
23: #include "fpopcode.h"
24:
25: unsigned int SingleCPDO(const unsigned int opcode);
26: unsigned int DoubleCPDO(const unsigned int opcode);
27: unsigned int ExtendedCPDO(const unsigned int opcode);
28:
29: unsigned int EmulateCPDO(const unsigned int opcode)
30: {
31: FPA11 *fpa11 = GET_FPA11();
32: unsigned int Fd, nType, nDest, nRc = 1;
33:
34: //printk("EmulateCPDO(0x%08x)\n",opcode);
35:
36: /* Get the destination size. If not valid let Linux perform
37: an invalid instruction trap. */
38: nDest = getDestinationSize(opcode);
39: if (typeNone == nDest) return 0;
40:
41: SetRoundingMode(opcode);
42:
43: /* Compare the size of the operands in Fn and Fm.
44: Choose the largest size and perform operations in that size,
45: in order to make use of all the precision of the operands.
46: If Fm is a constant, we just grab a constant of a size
47: matching the size of the operand in Fn. */
48: if (MONADIC_INSTRUCTION(opcode))
49: nType = nDest;
50: else
51: nType = fpa11->fType[getFn(opcode)];
52:
53: if (!CONSTANT_FM(opcode))
54: {
55: register unsigned int Fm = getFm(opcode);
56: if (nType < fpa11->fType[Fm])
57: {
58: nType = fpa11->fType[Fm];
59: }
60: }
61:
62: switch (nType)
63: {
64: case typeSingle : nRc = SingleCPDO(opcode); break;
65: case typeDouble : nRc = DoubleCPDO(opcode); break;
66: case typeExtended : nRc = ExtendedCPDO(opcode); break;
67: default : nRc = 0;
68: }
69:
70: /* If the operation succeeded, check to see if the result in the
71: destination register is the correct size. If not force it
72: to be. */
73: Fd = getFd(opcode);
74: nType = fpa11->fType[Fd];
75: if ((0 != nRc) && (nDest != nType))
76: {
77: switch (nDest)
78: {
79: case typeSingle:
80: {
81: if (typeDouble == nType)
82: fpa11->fpreg[Fd].fSingle =
83: float64_to_float32(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
84: else
85: fpa11->fpreg[Fd].fSingle =
86: floatx80_to_float32(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
87: }
88: break;
89:
90: case typeDouble:
91: {
92: if (typeSingle == nType)
93: fpa11->fpreg[Fd].fDouble =
94: float32_to_float64(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
95: else
96: fpa11->fpreg[Fd].fDouble =
97: floatx80_to_float64(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
98: }
99: break;
100:
101: case typeExtended:
102: {
103: if (typeSingle == nType)
104: fpa11->fpreg[Fd].fExtended =
105: float32_to_floatx80(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
106: else
107: fpa11->fpreg[Fd].fExtended =
108: float64_to_floatx80(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
109: }
110: break;
111: }
112:
113: fpa11->fType[Fd] = nDest;
114: }
115:
116: return nRc;
117: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.