Statistics
| Branch: | Revision:

root / linux-user / arm / nwfpe / fpa11_cpdo.c @ b53d44e5

History | View | Annotate | Download (3.4 kB)

1 00406dff bellard
/*
2 00406dff bellard
    NetWinder Floating Point Emulator
3 00406dff bellard
    (c) Rebel.COM, 1998,1999
4 00406dff bellard

5 00406dff bellard
    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6 00406dff bellard

7 00406dff bellard
    This program is free software; you can redistribute it and/or modify
8 00406dff bellard
    it under the terms of the GNU General Public License as published by
9 00406dff bellard
    the Free Software Foundation; either version 2 of the License, or
10 00406dff bellard
    (at your option) any later version.
11 00406dff bellard

12 00406dff bellard
    This program is distributed in the hope that it will be useful,
13 00406dff bellard
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 00406dff bellard
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 00406dff bellard
    GNU General Public License for more details.
16 00406dff bellard

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