]> git.proxmox.com Git - qemu.git/blame - linux-user/arm/nwfpe/fpa11_cpdo.c
Update to a hopefully more future proof FSF address
[qemu.git] / linux-user / arm / nwfpe / fpa11_cpdo.c
CommitLineData
00406dff
FB
1/*
2 NetWinder Floating Point Emulator
3 (c) Rebel.COM, 1998,1999
4
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
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
70539e18 18 along with this program; if not, see <http://www.gnu.org/licenses/>.
00406dff
FB
19*/
20
21#include "fpa11.h"
22#include "fpopcode.h"
23
00406dff
FB
24unsigned int EmulateCPDO(const unsigned int opcode)
25{
26 FPA11 *fpa11 = GET_FPA11();
27 unsigned int Fd, nType, nDest, nRc = 1;
3b46e624 28
00406dff
FB
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;
3b46e624 35
00406dff 36 SetRoundingMode(opcode);
3b46e624 37
00406dff
FB
38 /* Compare the size of the operands in Fn and Fm.
39 Choose the largest size and perform operations in that size,
5fafdf24
TS
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
00406dff
FB
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)];
3b46e624 47
00406dff
FB
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)
5fafdf24 77 fpa11->fpreg[Fd].fSingle =
20495218 78 float64_to_float32(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
00406dff 79 else
5fafdf24 80 fpa11->fpreg[Fd].fSingle =
20495218 81 floatx80_to_float32(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
00406dff
FB
82 }
83 break;
3b46e624 84
00406dff
FB
85 case typeDouble:
86 {
87 if (typeSingle == nType)
5fafdf24 88 fpa11->fpreg[Fd].fDouble =
20495218 89 float32_to_float64(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
00406dff 90 else
5fafdf24 91 fpa11->fpreg[Fd].fDouble =
20495218 92 floatx80_to_float64(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
00406dff
FB
93 }
94 break;
3b46e624 95
00406dff
FB
96 case typeExtended:
97 {
98 if (typeSingle == nType)
5fafdf24 99 fpa11->fpreg[Fd].fExtended =
20495218 100 float32_to_floatx80(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
00406dff 101 else
5fafdf24 102 fpa11->fpreg[Fd].fExtended =
20495218 103 float64_to_floatx80(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
00406dff
FB
104 }
105 break;
106 }
3b46e624 107
00406dff
FB
108 fpa11->fType[Fd] = nDest;
109 }
3b46e624 110
00406dff
FB
111 return nRc;
112}