1169689Skan/* Software floating-point emulation.
2169689Skan   Copyright (C) 1997,1998,1999,2000,2002,2003,2005,2006
3169689Skan	Free Software Foundation, Inc.
4169689Skan   This file is part of the GNU C Library.
5169689Skan   Contributed by Richard Henderson (rth@cygnus.com),
6169689Skan		  Jakub Jelinek (jj@ultra.linux.cz),
7169689Skan		  David S. Miller (davem@redhat.com) and
8169689Skan		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
9169689Skan
10169689Skan   The GNU C Library is free software; you can redistribute it and/or
11169689Skan   modify it under the terms of the GNU Lesser General Public
12169689Skan   License as published by the Free Software Foundation; either
13169689Skan   version 2.1 of the License, or (at your option) any later version.
14169689Skan
15169689Skan   In addition to the permissions in the GNU Lesser General Public
16169689Skan   License, the Free Software Foundation gives you unlimited
17169689Skan   permission to link the compiled version of this file into
18169689Skan   combinations with other programs, and to distribute those
19169689Skan   combinations without any restriction coming from the use of this
20169689Skan   file.  (The Lesser General Public License restrictions do apply in
21169689Skan   other respects; for example, they cover modification of the file,
22169689Skan   and distribution when not linked into a combine executable.)
23169689Skan
24169689Skan   The GNU C Library is distributed in the hope that it will be useful,
25169689Skan   but WITHOUT ANY WARRANTY; without even the implied warranty of
26169689Skan   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27169689Skan   Lesser General Public License for more details.
28169689Skan
29169689Skan   You should have received a copy of the GNU Lesser General Public
30169689Skan   License along with the GNU C Library; if not, write to the Free
31169689Skan   Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
32169689Skan   MA 02110-1301, USA.  */
33169689Skan
34169689Skan#ifndef SOFT_FP_H
35169689Skan#define SOFT_FP_H
36169689Skan
37169689Skan#ifdef _LIBC
38169689Skan#include <sfp-machine.h>
39169689Skan#else
40169689Skan#include "sfp-machine.h"
41169689Skan#endif
42169689Skan
43169689Skan/* Allow sfp-machine to have its own byte order definitions. */
44169689Skan#ifndef __BYTE_ORDER
45169689Skan#ifdef _LIBC
46169689Skan#include <endian.h>
47169689Skan#else
48169689Skan#error "endianness not defined by sfp-machine.h"
49169689Skan#endif
50169689Skan#endif
51169689Skan
52169689Skan#define _FP_WORKBITS		3
53169689Skan#define _FP_WORK_LSB		((_FP_W_TYPE)1 << 3)
54169689Skan#define _FP_WORK_ROUND		((_FP_W_TYPE)1 << 2)
55169689Skan#define _FP_WORK_GUARD		((_FP_W_TYPE)1 << 1)
56169689Skan#define _FP_WORK_STICKY		((_FP_W_TYPE)1 << 0)
57169689Skan
58169689Skan#ifndef FP_RND_NEAREST
59169689Skan# define FP_RND_NEAREST		0
60169689Skan# define FP_RND_ZERO		1
61169689Skan# define FP_RND_PINF		2
62169689Skan# define FP_RND_MINF		3
63169689Skan#endif
64169689Skan#ifndef FP_ROUNDMODE
65169689Skan# define FP_ROUNDMODE		FP_RND_NEAREST
66169689Skan#endif
67169689Skan
68169689Skan/* By default don't care about exceptions. */
69169689Skan#ifndef FP_EX_INVALID
70169689Skan#define FP_EX_INVALID		0
71169689Skan#endif
72169689Skan#ifndef FP_EX_OVERFLOW
73169689Skan#define FP_EX_OVERFLOW		0
74169689Skan#endif
75169689Skan#ifndef FP_EX_UNDERFLOW
76169689Skan#define FP_EX_UNDERFLOW		0
77169689Skan#endif
78169689Skan#ifndef FP_EX_DIVZERO
79169689Skan#define FP_EX_DIVZERO		0
80169689Skan#endif
81169689Skan#ifndef FP_EX_INEXACT
82169689Skan#define FP_EX_INEXACT		0
83169689Skan#endif
84169689Skan#ifndef FP_EX_DENORM
85169689Skan#define FP_EX_DENORM		0
86169689Skan#endif
87169689Skan
88169689Skan#ifdef _FP_DECL_EX
89169689Skan#define FP_DECL_EX					\
90169689Skan  int _fex = 0;						\
91169689Skan  _FP_DECL_EX
92169689Skan#else
93169689Skan#define FP_DECL_EX int _fex = 0
94169689Skan#endif
95169689Skan
96169689Skan#ifndef FP_INIT_ROUNDMODE
97169689Skan#define FP_INIT_ROUNDMODE do {} while (0)
98169689Skan#endif
99169689Skan
100169689Skan#ifndef FP_HANDLE_EXCEPTIONS
101169689Skan#define FP_HANDLE_EXCEPTIONS do {} while (0)
102169689Skan#endif
103169689Skan
104169689Skan#ifndef FP_INHIBIT_RESULTS
105169689Skan/* By default we write the results always.
106169689Skan * sfp-machine may override this and e.g.
107169689Skan * check if some exceptions are unmasked
108169689Skan * and inhibit it in such a case.
109169689Skan */
110169689Skan#define FP_INHIBIT_RESULTS 0
111169689Skan#endif
112169689Skan
113169689Skan#define FP_SET_EXCEPTION(ex)				\
114169689Skan  _fex |= (ex)
115169689Skan
116169689Skan#define FP_UNSET_EXCEPTION(ex)				\
117169689Skan  _fex &= ~(ex)
118169689Skan
119169689Skan#define FP_CLEAR_EXCEPTIONS				\
120169689Skan  _fex = 0
121169689Skan
122169689Skan#define _FP_ROUND_NEAREST(wc, X)			\
123169689Skando {							\
124169689Skan    if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND)	\
125169689Skan      _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
126169689Skan} while (0)
127169689Skan
128169689Skan#define _FP_ROUND_ZERO(wc, X)		(void)0
129169689Skan
130169689Skan#define _FP_ROUND_PINF(wc, X)				\
131169689Skando {							\
132169689Skan    if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
133169689Skan      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
134169689Skan} while (0)
135169689Skan
136169689Skan#define _FP_ROUND_MINF(wc, X)				\
137169689Skando {							\
138169689Skan    if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
139169689Skan      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
140169689Skan} while (0)
141169689Skan
142169689Skan#define _FP_ROUND(wc, X)			\
143169689Skando {						\
144169689Skan	if (_FP_FRAC_LOW_##wc(X) & 7)		\
145169689Skan	  FP_SET_EXCEPTION(FP_EX_INEXACT);	\
146169689Skan	switch (FP_ROUNDMODE)			\
147169689Skan	{					\
148169689Skan	  case FP_RND_NEAREST:			\
149169689Skan	    _FP_ROUND_NEAREST(wc,X);		\
150169689Skan	    break;				\
151169689Skan	  case FP_RND_ZERO:			\
152169689Skan	    _FP_ROUND_ZERO(wc,X);		\
153169689Skan	    break;				\
154169689Skan	  case FP_RND_PINF:			\
155169689Skan	    _FP_ROUND_PINF(wc,X);		\
156169689Skan	    break;				\
157169689Skan	  case FP_RND_MINF:			\
158169689Skan	    _FP_ROUND_MINF(wc,X);		\
159169689Skan	    break;				\
160169689Skan	}					\
161169689Skan} while (0)
162169689Skan
163169689Skan#define FP_CLS_NORMAL		0
164169689Skan#define FP_CLS_ZERO		1
165169689Skan#define FP_CLS_INF		2
166169689Skan#define FP_CLS_NAN		3
167169689Skan
168169689Skan#define _FP_CLS_COMBINE(x,y)	(((x) << 2) | (y))
169169689Skan
170169689Skan#include "op-1.h"
171169689Skan#include "op-2.h"
172169689Skan#include "op-4.h"
173169689Skan#include "op-8.h"
174169689Skan#include "op-common.h"
175169689Skan
176169689Skan/* Sigh.  Silly things longlong.h needs.  */
177169689Skan#define UWtype		_FP_W_TYPE
178169689Skan#define W_TYPE_SIZE	_FP_W_TYPE_SIZE
179169689Skan
180169689Skantypedef int QItype __attribute__((mode(QI)));
181169689Skantypedef int SItype __attribute__((mode(SI)));
182169689Skantypedef int DItype __attribute__((mode(DI)));
183169689Skantypedef unsigned int UQItype __attribute__((mode(QI)));
184169689Skantypedef unsigned int USItype __attribute__((mode(SI)));
185169689Skantypedef unsigned int UDItype __attribute__((mode(DI)));
186169689Skan#if _FP_W_TYPE_SIZE == 32
187169689Skantypedef unsigned int UHWtype __attribute__((mode(HI)));
188169689Skan#elif _FP_W_TYPE_SIZE == 64
189169689Skantypedef USItype UHWtype;
190169689Skan#endif
191169689Skan
192169689Skan#define SI_BITS		(__CHAR_BIT__ * (int)sizeof(SItype))
193169689Skan#define DI_BITS		(__CHAR_BIT__ * (int)sizeof(DItype))
194169689Skan
195169689Skan#ifndef umul_ppmm
196169689Skan#ifdef _LIBC
197169689Skan#include <stdlib/longlong.h>
198169689Skan#else
199169689Skan#include "longlong.h"
200169689Skan#endif
201169689Skan#endif
202169689Skan
203169689Skan#ifdef _LIBC
204169689Skan#include <stdlib.h>
205169689Skan#else
206169689Skanextern void abort (void);
207169689Skan#endif
208169689Skan
209169689Skan#endif
210