aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/soft-fp/sfp-machine.h
blob: 0411878071032926894d69d4e43a77123b1d44c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#define _FP_W_TYPE_SIZE		32
#define _FP_W_TYPE		unsigned long
#define _FP_WS_TYPE		signed long
#define _FP_I_TYPE		long

#define _FP_MUL_MEAT_S(R,X,Y)				\
  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_D(R,X,Y)				\
  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_Q(R,X,Y)				\
  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)

#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_loop(S,R,X,Y)
#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)

#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
#define _FP_NANSIGN_S		0
#define _FP_NANSIGN_D		0
#define _FP_NANSIGN_Q		0

#define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 0

/* Someone please check this.  */
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
  do {								\
    if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)		\
	&& !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs))	\
      {								\
	R##_s = Y##_s;						\
	_FP_FRAC_COPY_##wc(R,Y);				\
      }								\
    else							\
      {								\
	R##_s = X##_s;						\
	_FP_FRAC_COPY_##wc(R,X);				\
      }								\
    R##_c = FP_CLS_NAN;						\
  } while (0)

#if defined __NO_FPRS__ && !defined _SOFT_FLOAT

/* Exception flags.  We use the bit positions of the appropriate bits
   in the FPEFSCR.  */

# include <fenv_libc.h>
# include <sysdep.h>
# include <sys/prctl.h>

int __feraiseexcept_soft (int);
libc_hidden_proto (__feraiseexcept_soft)

# define FP_EX_INEXACT         SPEFSCR_FINXS
# define FP_EX_INVALID         SPEFSCR_FINVS
# define FP_EX_DIVZERO         SPEFSCR_FDBZS
# define FP_EX_UNDERFLOW       SPEFSCR_FUNFS
# define FP_EX_OVERFLOW        SPEFSCR_FOVFS

# define _FP_DECL_EX \
  int _spefscr __attribute__ ((unused)), _ftrapex __attribute__ ((unused)) = 0
# define FP_INIT_ROUNDMODE						\
  do									\
    {									\
      int _r;								\
      INTERNAL_SYSCALL_DECL (_err);					\
									\
      _spefscr = fegetenv_register ();					\
      _r = INTERNAL_SYSCALL (prctl, _err, 2, PR_GET_FPEXC, &_ftrapex);	\
      if (INTERNAL_SYSCALL_ERROR_P (_r, _err))				\
	_ftrapex = 0;							\
    }									\
  while (0)
# define FP_INIT_EXCEPTIONS /* Empty.  */

# define FP_HANDLE_EXCEPTIONS  __feraiseexcept_soft (_fex)
# define FP_ROUNDMODE          (_spefscr & 0x3)

/* Not correct in general, but sufficient for the uses in soft-fp.  */
# define FP_TRAPPING_EXCEPTIONS (_ftrapex & PR_FP_EXC_UND	\
				 ? FP_EX_UNDERFLOW		\
				 : 0)

#else

/* Exception flags.  We use the bit positions of the appropriate bits
   in the FPSCR, which also correspond to the FE_* bits.  This makes
   everything easier ;-).  */
# define FP_EX_INVALID         (1 << (31 - 2))
# define FP_EX_OVERFLOW        (1 << (31 - 3))
# define FP_EX_UNDERFLOW       (1 << (31 - 4))
# define FP_EX_DIVZERO         (1 << (31 - 5))
# define FP_EX_INEXACT         (1 << (31 - 6))

# define FP_HANDLE_EXCEPTIONS  __simulate_exceptions (_fex)
# define FP_ROUNDMODE          __sim_round_mode
# define FP_TRAPPING_EXCEPTIONS (~__sim_disabled_exceptions & 0x3e000000)

#endif

/* FIXME: these variables should be thread specific (see bugzilla bug
   15483) and ideally preserved across signal handlers, like hardware
   FP status words, but the latter is quite difficult to accomplish in
   userland.  */

extern int __sim_exceptions;
libc_hidden_proto (__sim_exceptions);
extern int __sim_disabled_exceptions;
libc_hidden_proto (__sim_disabled_exceptions);
extern int __sim_round_mode;
libc_hidden_proto (__sim_round_mode);

extern void __simulate_exceptions (int x) attribute_hidden;