summaryrefslogtreecommitdiffstats
path: root/arch/ppc/math-emu/soft-fp.h
blob: cca39598f873d3e565edec22cfea05b93fa1865a (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
#ifndef SOFT_FP_H
#define SOFT_FP_H

#include "sfp-machine.h"

#define _FP_WORKBITS		3
#define _FP_WORK_LSB		((_FP_W_TYPE)1 << 3)
#define _FP_WORK_ROUND		((_FP_W_TYPE)1 << 2)
#define _FP_WORK_GUARD		((_FP_W_TYPE)1 << 1)
#define _FP_WORK_STICKY		((_FP_W_TYPE)1 << 0)

#ifndef FP_RND_NEAREST
# define FP_RND_NEAREST		0
# define FP_RND_ZERO		1
# define FP_RND_PINF		2
# define FP_RND_MINF		3
#ifndef FP_ROUNDMODE
# define FP_ROUNDMODE		FP_RND_NEAREST
#endif
#endif

#define _FP_ROUND_NEAREST(wc, X)			\
({  int __ret = 0;					\
    int __frac = _FP_FRAC_LOW_##wc(X) & 15;		\
    if (__frac & 7) {					\
      __ret = EFLAG_INEXACT;				\
      if ((__frac & 7) != _FP_WORK_ROUND)		\
        _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
      else if (__frac & _FP_WORK_LSB)			\
        _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
    }							\
    __ret;						\
})

#define _FP_ROUND_ZERO(wc, X)				\
({  int __ret = 0;					\
    if (_FP_FRAC_LOW_##wc(X) & 7)			\
      __ret = EFLAG_INEXACT;				\
    __ret;						\
})

#define _FP_ROUND_PINF(wc, X)				\
({  int __ret = EFLAG_INEXACT;				\
    if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
    else __ret = 0;					\
    __ret;						\
})

#define _FP_ROUND_MINF(wc, X)				\
({  int __ret = EFLAG_INEXACT;				\
    if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
    else __ret = 0;					\
    __ret;						\
})

#define _FP_ROUND(wc, X)			\
({	int __ret = 0;				\
	switch (FP_ROUNDMODE)			\
	{					\
	  case FP_RND_NEAREST:			\
	    __ret |= _FP_ROUND_NEAREST(wc,X);	\
	    break;				\
	  case FP_RND_ZERO:			\
	    __ret |= _FP_ROUND_ZERO(wc,X);	\
	    break;				\
	  case FP_RND_PINF:			\
	    __ret |= _FP_ROUND_PINF(wc,X);	\
	    break;				\
	  case FP_RND_MINF:			\
	    __ret |= _FP_ROUND_MINF(wc,X);	\
	    break;				\
	};					\
	__ret;					\
})

#define FP_CLS_NORMAL		0
#define FP_CLS_ZERO		1
#define FP_CLS_INF		2
#define FP_CLS_NAN		3

#define _FP_CLS_COMBINE(x,y)	(((x) << 2) | (y))

#include "op-1.h"
#include "op-2.h"
#include "op-4.h"
#include "op-common.h"

/* Sigh.  Silly things longlong.h needs.  */
#define UWtype		_FP_W_TYPE
#define W_TYPE_SIZE	_FP_W_TYPE_SIZE

typedef int SItype __attribute__((mode(SI)));
typedef int DItype __attribute__((mode(DI)));
typedef unsigned int USItype __attribute__((mode(SI)));
typedef unsigned int UDItype __attribute__((mode(DI)));
#if _FP_W_TYPE_SIZE == 32
typedef unsigned int UHWtype __attribute__((mode(HI)));
#elif _FP_W_TYPE_SIZE == 64
typedef USItype UHWtype;
#endif

#endif