xref: /netbsd-src/external/gpl3/gdb/dist/sim/erc32/float.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*
2  * This file is part of SIS.
3  *
4  * SIS, SPARC instruction simulator. Copyright (C) 1995 Jiri Gaisler, European
5  * Space Agency
6  *
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 3 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  *
21  * This file implements the interface between the host and the simulated
22  * FPU. IEEE trap handling is done as follows:
23  * 1. In the host, all IEEE traps are masked
24  * 2. After each simulated FPU instruction, check if any exception occured
25  *    by reading the exception bits from the host FPU status register
26  *    (get_accex()).
27  * 3. Propagate any exceptions to the simulated FSR.
28  * 4. Clear host exception bits
29  *
30  *
31  * This can also be done using ieee_flags() library routine on sun.
32  */
33 
34 #include "config.h"
35 #include "sis.h"
36 
37 /* Forward declarations */
38 
39 extern uint32	_get_sw (void);
40 extern uint32	_get_cw (void);
41 static void	__setfpucw (unsigned short fpu_control);
42 
43 /* This host dependent routine should return the accrued exceptions */
44 int
45 get_accex()
46 {
47 #ifdef sparc
48     return ((_get_fsr_raw() >> 5) & 0x1F);
49 #elif i386
50     uint32 accx;
51 
52     accx = _get_sw() & 0x3f;
53     accx = ((accx & 1) << 4) | ((accx & 2) >> 1) | ((accx & 4) >> 1) |
54 	   (accx & 8) | ((accx & 16) >> 2) | ((accx & 32) >> 5);
55     return(accx);
56 #else
57     return(0);
58 #warning no fpu trap support for this target
59 #endif
60 
61 }
62 
63 /* How to clear the accrued exceptions */
64 void
65 clear_accex()
66 {
67 #ifdef sparc
68     set_fsr((_get_fsr_raw() & ~0x3e0));
69 #elif i386
70     asm("\n"
71 ".text\n"
72 "	fnclex\n"
73 "\n"
74 "    ");
75 #else
76 #warning no fpu trap support for this target
77 #endif
78 }
79 
80 /* How to map SPARC FSR onto the host */
81 void
82 set_fsr(fsr)
83 uint32 fsr;
84 {
85 #ifdef sparc
86 	_set_fsr_raw(fsr & ~0x0f800000);
87 #elif i386
88      void __setfpucw(unsigned short fpu_control);
89      uint32 rawfsr;
90 
91      fsr >>= 30;
92      switch (fsr) {
93 	case 0:
94 	case 2:
95 	  break;
96 
97 	case 1:
98 	  fsr = 3;
99 	  break;
100 
101 	case 3:
102 	  fsr = 1;
103 	  break;
104      }
105      rawfsr = _get_cw();
106      rawfsr |= (fsr << 10) | 0x3ff;
107      __setfpucw(rawfsr);
108 #else
109 #warning no fpu trap support for this target
110 #endif
111 }
112 
113 
114 /* Host dependent support functions */
115 
116 #ifdef sparc
117 
118     asm("\n"
119 "\n"
120 ".text\n"
121 "        .align 4\n"
122 "        .global __set_fsr_raw,_set_fsr_raw\n"
123 "__set_fsr_raw:\n"
124 "_set_fsr_raw:\n"
125 "        save %sp,-104,%sp\n"
126 "        st %i0,[%fp+68]\n"
127 "        ld [%fp+68], %fsr\n"
128 "        mov 0,%i0\n"
129 "        ret\n"
130 "        restore\n"
131 "\n"
132 "        .align 4\n"
133 "        .global __get_fsr_raw\n"
134 "        .global _get_fsr_raw\n"
135 "__get_fsr_raw:\n"
136 "_get_fsr_raw:\n"
137 "        save %sp,-104,%sp\n"
138 "        st %fsr,[%fp+68]\n"
139 "        ld [%fp+68], %i0\n"
140 "        ret\n"
141 "        restore\n"
142 "\n"
143 "    ");
144 
145 #elif i386
146 
147     asm("\n"
148 "\n"
149 ".text\n"
150 "        .align 8\n"
151 ".globl _get_sw,__get_sw\n"
152 "__get_sw:\n"
153 "_get_sw:\n"
154 "        pushl %ebp\n"
155 "        movl %esp,%ebp\n"
156 "        movl $0,%eax\n"
157 "        fnstsw %ax\n"
158 "        movl %ebp,%esp\n"
159 "        popl %ebp\n"
160 "        ret\n"
161 "\n"
162 "        .align 8\n"
163 ".globl _get_cw,__get_cw\n"
164 "__get_cw:\n"
165 "_get_cw:\n"
166 "        pushl %ebp\n"
167 "        movl %esp,%ebp\n"
168 "        subw $2,%esp\n"
169 "        fnstcw -2(%ebp)\n"
170 "        movw -2(%ebp),%eax\n"
171 "        movl %ebp,%esp\n"
172 "        popl %ebp\n"
173 "        ret\n"
174 "\n"
175 "\n"
176 "    ");
177 
178 
179 #else
180 #warning no fpu trap support for this target
181 #endif
182 
183 #if i386
184 /* #if defined _WIN32 || defined __GO32__ */
185 /* This is so floating exception handling works on NT
186    These definitions are from the linux fpu_control.h, which
187    doesn't exist on NT.
188 
189    default to:
190      - extended precision
191      - rounding to nearest
192      - exceptions on overflow, zero divide and NaN
193 */
194 #define _FPU_DEFAULT  0x1372
195 #define _FPU_RESERVED 0xF0C0  /* Reserved bits in cw */
196 
197 static void
198 __setfpucw(unsigned short fpu_control)
199 {
200   volatile unsigned short cw;
201 
202   /* If user supplied _fpu_control, use it ! */
203   if (!fpu_control)
204   {
205     /* use defaults */
206     fpu_control = _FPU_DEFAULT;
207   }
208   /* Get Control Word */
209   __asm__ volatile ("fnstcw %0" : "=m" (cw) : );
210 
211   /* mask in */
212   cw &= _FPU_RESERVED;
213   cw = cw | (fpu_control & ~_FPU_RESERVED);
214 
215   /* set cw */
216   __asm__ volatile ("fldcw %0" :: "m" (cw));
217 }
218 /* #endif */
219 #endif
220