]> git.proxmox.com Git - qemu.git/blame - target-arm/nwfpe/fpa11_cpdo.c
find -type f | xargs sed -i 's/[\t ]$//g' # on most files
[qemu.git] / target-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
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
25unsigned int SingleCPDO(const unsigned int opcode);
26unsigned int DoubleCPDO(const unsigned int opcode);
27unsigned int ExtendedCPDO(const unsigned int opcode);
28
29unsigned int EmulateCPDO(const unsigned int opcode)
30{
31 FPA11 *fpa11 = GET_FPA11();
32 unsigned int Fd, nType, nDest, nRc = 1;
5fafdf24 33
00406dff
FB
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;
5fafdf24 40
00406dff 41 SetRoundingMode(opcode);
5fafdf24 42
00406dff
FB
43 /* Compare the size of the operands in Fn and Fm.
44 Choose the largest size and perform operations in that size,
5fafdf24
TS
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
00406dff
FB
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)];
5fafdf24 52
00406dff
FB
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)
5fafdf24 82 fpa11->fpreg[Fd].fSingle =
20495218 83 float64_to_float32(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
00406dff 84 else
5fafdf24 85 fpa11->fpreg[Fd].fSingle =
20495218 86 floatx80_to_float32(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
00406dff
FB
87 }
88 break;
5fafdf24 89
00406dff
FB
90 case typeDouble:
91 {
92 if (typeSingle == nType)
5fafdf24 93 fpa11->fpreg[Fd].fDouble =
20495218 94 float32_to_float64(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
00406dff 95 else
5fafdf24 96 fpa11->fpreg[Fd].fDouble =
20495218 97 floatx80_to_float64(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status);
00406dff
FB
98 }
99 break;
5fafdf24 100
00406dff
FB
101 case typeExtended:
102 {
103 if (typeSingle == nType)
5fafdf24 104 fpa11->fpreg[Fd].fExtended =
20495218 105 float32_to_floatx80(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status);
00406dff 106 else
5fafdf24 107 fpa11->fpreg[Fd].fExtended =
20495218 108 float64_to_floatx80(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status);
00406dff
FB
109 }
110 break;
111 }
5fafdf24 112
00406dff
FB
113 fpa11->fType[Fd] = nDest;
114 }
5fafdf24 115
00406dff
FB
116 return nRc;
117}