OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [arm/] [nwfpe/] [fpa11_cpdo.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
    NetWinder Floating Point Emulator
3
    (c) Rebel.COM, 1998,1999
4
    (c) Philip Blundell, 2001
5
 
6
    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
7
 
8
    This program is free software; you can redistribute it and/or modify
9
    it under the terms of the GNU General Public License as published by
10
    the Free Software Foundation; either version 2 of the License, or
11
    (at your option) any later version.
12
 
13
    This program is distributed in the hope that it will be useful,
14
    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
    GNU General Public License for more details.
17
 
18
    You should have received a copy of the GNU General Public License
19
    along with this program; if not, write to the Free Software
20
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
*/
22
 
23
#include "fpa11.h"
24
#include "fpopcode.h"
25
 
26
unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd);
27
unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd);
28
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd);
29
 
30
unsigned int EmulateCPDO(const unsigned int opcode)
31
{
32
        FPA11 *fpa11 = GET_FPA11();
33
        FPREG *rFd;
34
        unsigned int nType, nDest, nRc;
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)
40
                return 0;
41
 
42
        SetRoundingMode(opcode);
43
 
44
        /* Compare the size of the operands in Fn and Fm.
45
           Choose the largest size and perform operations in that size,
46
           in order to make use of all the precision of the operands.
47
           If Fm is a constant, we just grab a constant of a size
48
           matching the size of the operand in Fn. */
49
        if (MONADIC_INSTRUCTION(opcode))
50
                nType = nDest;
51
        else
52
                nType = fpa11->fType[getFn(opcode)];
53
 
54
        if (!CONSTANT_FM(opcode)) {
55
                register unsigned int Fm = getFm(opcode);
56
                if (nType < fpa11->fType[Fm]) {
57
                        nType = fpa11->fType[Fm];
58
                }
59
        }
60
 
61
        rFd = &fpa11->fpreg[getFd(opcode)];
62
 
63
        switch (nType) {
64
        case typeSingle:
65
                nRc = SingleCPDO(opcode, rFd);
66
                break;
67
        case typeDouble:
68
                nRc = DoubleCPDO(opcode, rFd);
69
                break;
70
#ifdef CONFIG_FPE_NWFPE_XP
71
        case typeExtended:
72
                nRc = ExtendedCPDO(opcode, rFd);
73
                break;
74
#endif
75
        default:
76
                nRc = 0;
77
        }
78
 
79
        /* The CPDO functions used to always set the destination type
80
           to be the same as their working size. */
81
 
82
        if (nRc != 0) {
83
                /* If the operation succeeded, check to see if the result in the
84
                   destination register is the correct size.  If not force it
85
                   to be. */
86
 
87
                fpa11->fType[getFd(opcode)] = nDest;
88
 
89
#ifdef CONFIG_FPE_NWFPE_XP
90
                if (nDest != nType) {
91
                        switch (nDest) {
92
                        case typeSingle:
93
                                {
94
                                        if (typeDouble == nType)
95
                                                rFd->fSingle = float64_to_float32(rFd->fDouble);
96
                                        else
97
                                                rFd->fSingle = floatx80_to_float32(rFd->fExtended);
98
                                }
99
                                break;
100
 
101
                        case typeDouble:
102
                                {
103
                                        if (typeSingle == nType)
104
                                                rFd->fDouble = float32_to_float64(rFd->fSingle);
105
                                        else
106
                                                rFd->fDouble = floatx80_to_float64(rFd->fExtended);
107
                                }
108
                                break;
109
 
110
                        case typeExtended:
111
                                {
112
                                        if (typeSingle == nType)
113
                                                rFd->fExtended = float32_to_floatx80(rFd->fSingle);
114
                                        else
115
                                                rFd->fExtended = float64_to_floatx80(rFd->fDouble);
116
                                }
117
                                break;
118
                        }
119
                }
120
#else
121
                if (nDest != nType) {
122
                        if (nDest == typeSingle)
123
                                rFd->fSingle = float64_to_float32(rFd->fDouble);
124
                        else
125
                                rFd->fDouble = float32_to_float64(rFd->fSingle);
126
                }
127
#endif
128
        }
129
 
130
        return nRc;
131
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.