master
h 229 lines 8.67 KB
Raw
1 /*
2 * Floating point intermediate representation
3 *
4 * The code in this source file is derived from release 2a of the SoftFloat
5 * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
6 * some later contributions) are provided under that license, as detailed below.
7 * It has subsequently been modified by contributors to the QEMU Project,
8 * so some portions are provided under:
9 * the SoftFloat-2a license
10 * the BSD license
11 * GPL-v2-or-later
12 *
13 * Any future contributions to this file after December 1st 2014 will be
14 * taken to be licensed under the Softfloat-2a license unless specifically
15 * indicated otherwise.
16 */
17
18 #ifndef SOFTFLOAT_PARTS_H
19 #define SOFTFLOAT_PARTS_H
20
21 /* Format-specific handling of exp == exp_max */
22 typedef enum __attribute__((__packed__)) {
23 /* exp==max, frac==0 ? infinity : nan; this is ieee standard. */
24 float_expmax_ieee,
25 /* exp==max is a normal number; no infinity or nan representation. */
26 float_expmax_normal,
27 /* exp==max, frac==max ? nan : normal; no infinity representation. */
28 float_expmax_e4m3,
29 } FloatFmtExpMaxKind;
30
31 /*
32 * Structure holding all of the relevant parameters for a format.
33 * exp_size: the size of the exponent field
34 * exp_bias: the offset applied to the exponent field
35 * exp_max: the maximum normalised exponent
36 * frac_size: the size of the fraction field
37 * frac_shift: shift to normalise the fraction with DECOMPOSED_BINARY_POINT
38 * The following are computed based the size of fraction
39 * round_mask: bits below lsb which must be rounded
40 * The following optional modifiers are available:
41 * exp_max_kind: affects how exp == exp_max is interpreted
42 * has_explicit_bit: has an explicit integer bit; this affects whether
43 * the float_status floatx80_behaviour handling applies
44 * overflow_raises_invalid: for float_expmax_normal, raise invalid
45 * instead of overflow.
46 */
47 typedef struct {
48 int exp_size;
49 int exp_bias;
50 int exp_re_bias;
51 int exp_max;
52 int frac_size;
53 int frac_shift;
54 FloatFmtExpMaxKind exp_max_kind;
55 bool has_explicit_bit;
56 bool overflow_raises_invalid;
57 uint64_t round_mask;
58 } FloatFmt;
59
60 extern const FloatFmt float4_e2m1_params;
61 extern const FloatFmt float8_e4m3_params;
62 extern const FloatFmt float8_e5m2_params;
63 extern const FloatFmt float16_params;
64 extern const FloatFmt bfloat16_params;
65 extern const FloatFmt float32_params;
66 extern const FloatFmt float64_params;
67 extern const FloatFmt float128_params;
68
69 /*
70 * Classify a floating point number. Everything above float_class_qnan
71 * is a NaN so cls >= float_class_qnan is any NaN.
72 *
73 * Note that we canonicalize denormals, so most code should treat
74 * class_normal and class_denormal identically.
75 */
76
77 typedef enum __attribute__ ((__packed__)) {
78 float_class_unclassified,
79 float_class_zero,
80 float_class_normal,
81 float_class_denormal, /* input was a non-squashed denormal */
82 float_class_inf,
83 float_class_qnan, /* all NaNs from here */
84 float_class_snan,
85 } FloatClass;
86
87 #define float_cmask(bit) (1u << (bit))
88
89 enum {
90 float_cmask_zero = float_cmask(float_class_zero),
91 float_cmask_normal = float_cmask(float_class_normal),
92 float_cmask_denormal = float_cmask(float_class_denormal),
93 float_cmask_inf = float_cmask(float_class_inf),
94 float_cmask_qnan = float_cmask(float_class_qnan),
95 float_cmask_snan = float_cmask(float_class_snan),
96
97 float_cmask_infzero = float_cmask_zero | float_cmask_inf,
98 float_cmask_anynan = float_cmask_qnan | float_cmask_snan,
99 float_cmask_anynorm = float_cmask_normal | float_cmask_denormal,
100 };
101
102 /*
103 * Structure holding all of the decomposed parts of a float.
104 * The exponent is unbiased and the fraction is normalized.
105 *
106 * The fraction words are stored in big-endian word ordering,
107 * so that truncation from a larger format to a smaller format
108 * can be done simply by ignoring subsequent elements.
109 */
110
111 typedef struct {
112 FloatClass cls;
113 bool sign;
114 int32_t exp;
115 union {
116 /* Routines that know the structure may reference the singular name. */
117 uint64_t frac;
118 /*
119 * Routines expanded with multiple structures reference "hi" and "lo"
120 * depending on the operation. In FloatParts64, "hi" and "lo" are
121 * both the same word and aliased here.
122 */
123 uint64_t frac_hi;
124 uint64_t frac_lo;
125 };
126 } FloatParts64;
127
128 typedef struct {
129 FloatClass cls;
130 bool sign;
131 int32_t exp;
132 uint64_t frac_hi;
133 uint64_t frac_lo;
134 } FloatParts128;
135
136 /*
137 * Unpack routines from a specific floating-point format.
138 */
139
140 FloatParts64 float4_e2m1_unpack_canonical(float4_e2m1 f, float_status *s);
141 FloatParts64 float8_e4m3_unpack_canonical(float8_e4m3 f, float_status *s);
142 FloatParts64 float8_e5m2_unpack_canonical(float8_e5m2 f, float_status *s);
143 FloatParts64 float16_unpack_canonical(float16 f, float_status *s);
144 FloatParts64 bfloat16_unpack_canonical(bfloat16 f, float_status *s);
145 FloatParts64 float32_unpack_canonical(float32 f, float_status *s);
146 FloatParts64 float64_unpack_canonical(float64 f, float_status *s);
147 FloatParts128 float128_unpack_canonical(float128 f, float_status *s);
148 /* Returns false if the encoding is invalid. */
149 bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f, float_status *s);
150
151 /*
152 * Pack routines to a specific floating-point format.
153 */
154
155 float8_e4m3 float8_e4m3_round_pack_canonical(FloatParts64 *p, float_status *s,
156 bool saturate);
157 float8_e5m2 float8_e5m2_round_pack_canonical(FloatParts64 *p, float_status *s,
158 bool saturate);
159 float16 float16_round_pack_canonical(FloatParts64 *p, float_status *s);
160 bfloat16 bfloat16_round_pack_canonical(FloatParts64 *p, float_status *s);
161 float32 float32_round_pack_canonical(FloatParts64 *p, float_status *s);
162 float64 float64_round_pack_canonical(FloatParts64 *p, float_status *s);
163 float128 float128_round_pack_canonical(FloatParts128 *p, float_status *s);
164 floatx80 floatx80_round_pack_canonical(FloatParts128 *p, float_status *s);
165
166 /*
167 * NaN handling
168 */
169
170 FloatParts64 parts64_default_nan(float_status *status);
171 FloatParts128 parts128_default_nan(float_status *status);
172
173 FloatParts64 parts64_pick_nan(const FloatParts64 *, const FloatParts64 *,
174 float_status *);
175 FloatParts128 parts128_pick_nan(const FloatParts128 *, const FloatParts128 *,
176 float_status *);
177
178 FloatParts64 parts64_return_nan(const FloatParts64 *a, float_status *s);
179 FloatParts128 parts128_return_nan(const FloatParts128 *a, float_status *s);
180
181 /*
182 * Operations
183 */
184
185 FloatParts64 parts64_addsub(const FloatParts64 *a, const FloatParts64 *b,
186 float_status *s, bool subtract);
187 FloatParts128 parts128_addsub(const FloatParts128 *a, const FloatParts128 *b,
188 float_status *s, bool subtract);
189
190 FloatRelation parts64_compare(const FloatParts64 *a, const FloatParts64 *b,
191 float_status *s, bool quiet);
192 FloatRelation parts128_compare(const FloatParts128 *a, const FloatParts128 *b,
193 float_status *s, bool quiet);
194
195 FloatParts64 parts64_div(const FloatParts64 *a, const FloatParts64 *b,
196 float_status *s);
197 FloatParts128 parts128_div(const FloatParts128 *a, const FloatParts128 *b,
198 float_status *s);
199
200 FloatParts64 parts64_mul(const FloatParts64 *a, const FloatParts64 *b,
201 float_status *s);
202 FloatParts128 parts128_mul(const FloatParts128 *a, const FloatParts128 *b,
203 float_status *s);
204
205 FloatParts64 parts64_muladd(const FloatParts64 *a,
206 const FloatParts64 *b,
207 const FloatParts64 *c,
208 int flags, float_status *s);
209 FloatParts128 parts128_muladd(const FloatParts128 *a,
210 const FloatParts128 *b,
211 const FloatParts128 *c,
212 int flags, float_status *s);
213
214 FloatParts64 parts64_round_to_int(const FloatParts64 *a,
215 FloatRoundMode rmode,
216 int scale, float_status *s,
217 const FloatFmt *fmt);
218 FloatParts128 parts128_round_to_int(const FloatParts128 *a,
219 FloatRoundMode rmode,
220 int scale, float_status *s,
221 const FloatFmt *fmt);
222
223 FloatParts64 parts64_round_to_fmt(const FloatParts64 *p, float_status *s,
224 const FloatFmt *fmt);
225
226 FloatParts64 parts64_scalbn(const FloatParts64 *a, int n, float_status *s);
227 FloatParts128 parts128_scalbn(const FloatParts128 *a, int n, float_status *s);
228
229 #endif