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 2 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, write to the Free Software Foundation, Inc., 675
19 * Mass Ave, Cambridge, MA 02139, USA.
20 *
21 *
22 * This file implements the interface between the host and the simulated
23 * FPU. IEEE trap handling is done as follows:
24 * 1. In the host, all IEEE traps are masked
25 * 2. After each simulated FPU instruction, check if any exception occured
26 *    by reading the exception bits from the host FPU status register
27 *    (get_accex()).
28 * 3. Propagate any exceptions to the simulated FSR.
29 * 4. Clear host exception bits
30 *
31 *
32 * This can also be done using ieee_flags() library routine on sun.
33 */
34
35#include "sis.h"
36
37/* Forward declarations */
38
39extern uint32	_get_sw PARAMS ((void));
40extern uint32	_get_cw PARAMS ((void));
41static void	__setfpucw PARAMS ((unsigned short fpu_control));
42
43/* This host dependent routine should return the accrued exceptions */
44int
45get_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 */
64void
65clear_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 */
81void
82set_fsr(fsr)
83uint32 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: break;
95	case 1: fsr = 3;
96	case 3: fsr = 1;
97     }
98     rawfsr = _get_cw();
99     rawfsr |= (fsr << 10) | 0x3ff;
100     __setfpucw(rawfsr);
101#else
102#warning no fpu trap support for this target
103#endif
104}
105
106
107/* Host dependent support functions */
108
109#ifdef sparc
110
111    asm("\n"
112"\n"
113".text\n"
114"        .align 4\n"
115"        .global __set_fsr_raw,_set_fsr_raw\n"
116"__set_fsr_raw:\n"
117"_set_fsr_raw:\n"
118"        save %sp,-104,%sp\n"
119"        st %i0,[%fp+68]\n"
120"        ld [%fp+68], %fsr\n"
121"        mov 0,%i0\n"
122"        ret\n"
123"        restore\n"
124"\n"
125"        .align 4\n"
126"        .global __get_fsr_raw\n"
127"        .global _get_fsr_raw\n"
128"__get_fsr_raw:\n"
129"_get_fsr_raw:\n"
130"        save %sp,-104,%sp\n"
131"        st %fsr,[%fp+68]\n"
132"        ld [%fp+68], %i0\n"
133"        ret\n"
134"        restore\n"
135"\n"
136"    ");
137
138#elif i386
139
140    asm("\n"
141"\n"
142".text\n"
143"        .align 8\n"
144".globl _get_sw,__get_sw\n"
145"__get_sw:\n"
146"_get_sw:\n"
147"        pushl %ebp\n"
148"        movl %esp,%ebp\n"
149"        movl $0,%eax\n"
150"        fnstsw %ax\n"
151"        movl %ebp,%esp\n"
152"        popl %ebp\n"
153"        ret\n"
154"\n"
155"        .align 8\n"
156".globl _get_cw,__get_cw\n"
157"__get_cw:\n"
158"_get_cw:\n"
159"        pushl %ebp\n"
160"        movl %esp,%ebp\n"
161"        subw $2,%esp\n"
162"        fnstcw -2(%ebp)\n"
163"        movw -2(%ebp),%eax\n"
164"        movl %ebp,%esp\n"
165"        popl %ebp\n"
166"        ret\n"
167"\n"
168"\n"
169"    ");
170
171
172#else
173#warning no fpu trap support for this target
174#endif
175
176#if i386
177/* #if defined _WIN32 || defined __GO32__ */
178/* This is so floating exception handling works on NT
179   These definitions are from the linux fpu_control.h, which
180   doesn't exist on NT.
181
182   default to:
183     - extended precision
184     - rounding to nearest
185     - exceptions on overflow, zero divide and NaN
186*/
187#define _FPU_DEFAULT  0x1372
188#define _FPU_RESERVED 0xF0C0  /* Reserved bits in cw */
189
190static void
191__setfpucw(unsigned short fpu_control)
192{
193  volatile unsigned short cw;
194
195  /* If user supplied _fpu_control, use it ! */
196  if (!fpu_control)
197  {
198    /* use defaults */
199    fpu_control = _FPU_DEFAULT;
200  }
201  /* Get Control Word */
202  __asm__ volatile ("fnstcw %0" : "=m" (cw) : );
203
204  /* mask in */
205  cw &= _FPU_RESERVED;
206  cw = cw | (fpu_control & ~_FPU_RESERVED);
207
208  /* set cw */
209  __asm__ volatile ("fldcw %0" :: "m" (cw));
210}
211/* #endif */
212#endif
213