Commit | Line | Data |
---|---|---|
b1a20bee MW |
1 | dnl -*-autoconf-*- |
2 | ||
3 | ### SYNOPSIS | |
4 | ### | |
5 | ### mdw_PROBE_FLTFMT | |
6 | ### | |
7 | ### DESCRIPTION | |
8 | ### | |
9 | ### Attempts to determine the target system's floating-point formats. | |
10 | ### The macros `FLT_FORMAT', `DBL_FORMAT', and `LDBL_FORMAT' are defined if | |
11 | ### the corresponding formats are recognized. The values of these macros | |
12 | ### are a bitmask: | |
13 | ### | |
14 | ### * `FLTFMT_ORGMASK' is a bitmask covering the `organization' field, | |
15 | ### which identifies the organization which defined the format. | |
16 | ### | |
17 | ### -- `FLTFMT_IEEE' identifies IEEE 754. | |
18 | ### -- `FLTFMT_INTEL' identifies Intel. | |
19 | ### | |
20 | ### * `FLTFMT_TYPEMASK' is a bitmask covering the `type' field, which | |
21 | ### must be interpreted together with the organization field to | |
22 | ### determine the format. | |
23 | ### | |
24 | ### -- `FLTFMT_IEEE_F32' is the IEEE 754 `binary32' format. | |
25 | ### -- `FLTFMT_IEEE_F64' is the IEEE 754 `binary64' format. | |
26 | ### -- `FLTFMT_IEEE_F128' is the IEEE 754 `binary128' format. | |
27 | ### -- `FLTFMT_INTEL_F80' is the Intel x87 80-bit double-extended | |
28 | ### format. | |
29 | ### | |
30 | ### * `FLTFMT_ENDMASK' is a bitmask covering the `endian' field, which | |
31 | ### describes the byte ordering convention used. | |
32 | ### | |
33 | ### -- `FLTFMT_LE' means little-endian format. | |
34 | ### | |
35 | ### -- `FLTFMT_BE' means big-endian format. | |
36 | ### | |
37 | ### -- `FLTFMT_ARME' means `Acorn's ridiculous mixed-endian' format, | |
38 | ### used by the ARM FPA, which stored the a `binary64' value as | |
39 | ### two 32-bit words, most significant word first, but with the | |
40 | ### individual words stored in little-endian byte order. | |
41 | ### | |
42 | ### Other conventions exist and support for them may be added later. | |
43 | ### | |
44 | ### Finally, there are predefined values for relevant combinations of | |
45 | ### format codes and byte orderings: | |
46 | ### | |
47 | ### * `FLTFMT_IEEE_F32_LE' and `FLTFMT_IEEE_F32_BE'; | |
48 | ### * `FLTFMT_IEEE_F64_LE' and `FLTFMT_IEEE_F64_BE'; | |
49 | ### * `FLTFMT_IEEE_F128_LE' and `FLTFMT_IEEE_F128_BE'; | |
50 | ### * `FLTFMT_INTEL_F80_LE' and `FLTFMT_INTEL_F80_BE'. | |
51 | ### | |
52 | ### (I don't know of anything which uses Intel's double-extended format in | |
53 | ### big-endian order, but it was easy enough to check for. The IEEE | |
54 | ### formats are used on ARM64 and z/Architecture with opposite byte order.) | |
55 | ### | |
56 | ### This macro works correctly when cross-compiling. | |
57 | ### | |
58 | ### LICENSE | |
59 | ### | |
60 | ### Copyright (c) 2024 Mark Wooding <mdw@distorted.org.uk> | |
61 | ### | |
62 | ### This program is free software: you can redistribute it and/or modify it | |
63 | ### under the terms of the GNU General Public License as published by the | |
64 | ### Free Software Foundation, either version 2 of the License, or (at your | |
65 | ### option) any later version. | |
66 | ### | |
67 | ### This program is distributed in the hope that it will be useful, but | |
68 | ### WITHOUT ANY WARRANTY; without even the implied warranty of | |
69 | ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
70 | ### General Public License for more details. | |
71 | ### | |
72 | ### You should have received a copy of the GNU General Public License along | |
73 | ### with this program. If not, see <http://www.gnu.org/licenses/>. | |
74 | ### | |
75 | ### In particular, no exception to the GPL is granted regarding generated | |
76 | ### `configure' scripts which are the output of Autoconf. | |
77 | ||
78 | dnl Principle of operation: | |
79 | dnl | |
80 | dnl The essential trick here lies in finding floating-point numbers whose | |
81 | dnl encoding, in various formats of interest, happen to be recognizable | |
82 | dnl diagnostic text strings. The structure definitions provide some space | |
83 | dnl for framing text which allows us to scrape the resulting diagnostic | |
84 | dnl strings from the object file. | |
85 | dnl | |
86 | dnl IEEE formats conveniently don't impose any restrictions on the contents | |
87 | dnl of the fraction field because there's a hidden bit. The Intel x87 | |
88 | dnl double-extended format makes the most significant bit explicit, and also | |
89 | dnl expects normalization, which means that the top bit of the fraction bytes | |
90 | dnl must be set, so everything gets quite ugly. Worse, the actual data is 10 | |
91 | dnl bytes long, but it sits in a 16-byte field to force alignment in vectors, | |
92 | dnl with the result that there are unavoidably zero bytes in our diagnostic | |
93 | dnl output. Different tools respond to these differently; e.g., GNU sed(1) | |
94 | dnl just writes out the zero bytes like they were any other character, while | |
95 | dnl Busybox sed(1) terminates the output line. As a result, we have to be | |
96 | dnl rather more flexible about matching this than I'd really like. (Messing | |
97 | dnl about with compiler-specific hacks for structure packing won't help here | |
98 | dnl because the analysis code still has to cope with compilers which don't | |
99 | dnl have those hacks.) | |
100 | ||
101 | # Serial 1 | |
102 | AC_COPYRIGHT([ | |
103 | Portions copyright (c) 2024 Mark Wooding. | |
104 | ||
105 | This configure script is free software: you can redistribute it and/or | |
106 | modify it under he terms of the GNU General Public License as published | |
107 | by the Free Software Foundation, either version 2 of the License, or | |
108 | (at your option) any later version.]) | |
109 | ||
110 | AC_DEFUN([mdw_PROBE_FLTFMT], | |
111 | [AC_CACHE_CHECK([floating-point representations], [mdw_cv_fltfmt], | |
112 | [mdw_fltfmt=nil mdw_dblfmt=nil mdw_ldblfmt=nil | |
113 | AC_LINK_IFELSE([AC_LANG_SOURCE([ | |
114 | ||
115 | /* The following program is copyright (c) 2024 Mark Wooding. It is free | |
116 | * software: you can redistribute it and/or modify it under the terms of the | |
117 | * GNU General Public License as published by the Free Software Foundation, | |
118 | * either version 2 of the License, or (at your option) any later version. | |
119 | * | |
120 | * This program is distributed in the hope that it will be useful, but | |
121 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
122 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
123 | * for more details. | |
124 | * | |
125 | * You should have received a copy of the GNU General Public License along | |
126 | * with this program. If not, see <http://www.gnu.org/licenses/>. | |
127 | */ | |
128 | ||
129 | @%:@include <float.h> | |
130 | ||
131 | @%:@define DEFFLTDIAG(ty, type) \ | |
132 | struct fltdiag_@%:@@%:@ty { char top@<:@48@:>@; type x; char tail@<:@4@:>@; } | |
133 | ||
134 | DEFFLTDIAG(flt, float); | |
135 | ||
136 | static const struct fltdiag_flt flt_ieee_f32 = { | |
137 | "\0\0\0\0\0\0\0\0\n@@@ mdw-probe-fltfmt float ieee-f32 = >", | |
138 | 781.0352, | |
139 | "<\n\0\0" | |
140 | }; | |
141 | @%:@define DO_FLT_IEEE_F32 DO(flt_ieee_f32) | |
142 | ||
143 | DEFFLTDIAG(dbl, double); | |
144 | ||
145 | @%:@if DBL_MAX_10_EXP > 40 | |
146 | static const struct fltdiag_dbl dbl_ieee_f64 = { | |
147 | "\0\0\0\0\0\0\0\n@@@ mdw-probe-fltfmt double ieee-f64 = >", | |
148 | 1.5839800103804824e40, | |
149 | "<\n\0\0" | |
150 | }; | |
151 | @%:@ define DO_DBL_IEEE_F64 DO(dbl_ieee_f64) | |
152 | @%:@else | |
153 | @%:@ define DO_DBL_IEEE_F64 | |
154 | @%:@endif | |
155 | ||
156 | DEFFLTDIAG(ldbl, long double); | |
157 | ||
158 | @%:@if LDBL_MAX_10_EXP > 40 | |
159 | static const struct fltdiag_ldbl ldbl_ieee_f64 = { | |
160 | "\0\0\n@@@ mdw-probe-fltfmt long-double ieee-f64 = >", | |
161 | 1.5839800103804824e40, | |
162 | "<\n\0\0" | |
163 | }; | |
164 | @%:@ define DO_LDBL_IEEE_F64 DO(ldbl_ieee_f64) | |
165 | @%:@else | |
166 | @%:@ define DO_LDBL_IEEE_F64 | |
167 | @%:@endif | |
168 | ||
169 | @%:@if LDBL_MAX_10_EXP > 1257 | |
170 | static const struct fltdiag_ldbl ldbl_ieee_f128 = { | |
171 | "\0\n@@@ mdw-probe-fltfmt long-double ieee-f128 = >", | |
172 | 1.6487728650847311136108983312706536e+1257L, | |
173 | "<\n\0\0" | |
174 | }; | |
175 | @%:@ define DO_LDBL_IEEE_F128 DO(ldbl_ieee_f128) | |
176 | @%:@else | |
177 | @%:@ define DO_LDBL_IEEE_F128 | |
178 | @%:@endif | |
179 | ||
180 | @%:@if LDBL_MAX_10_EXP > 793 | |
181 | static const struct fltdiag_ldbl ldbl_intel_f80 = { | |
182 | "\0\n@@@ mdw-probe-fltfmt long-double intel-f80 = >", | |
183 | 1.2806567921142816197e+793L, | |
184 | "<\n\0\0" | |
185 | }; | |
186 | @%:@ define DO_LDBL_INTEL_F80 DO(ldbl_intel_f80) | |
187 | @%:@else | |
188 | @%:@ define DO_LDBL_INTEL_F80 | |
189 | @%:@endif | |
190 | ||
191 | @%:@include <stdio.h> | |
192 | int main(void) | |
193 | { | |
194 | @%:@define DO(var) fwrite(&var, sizeof(var), 1, stdout) | |
195 | DO_FLT_IEEE_F32; | |
196 | DO_DBL_IEEE_F64; | |
197 | DO_LDBL_IEEE_F64; | |
198 | DO_LDBL_IEEE_F128; | |
199 | DO_LDBL_IEEE_F128; | |
200 | DO_LDBL_INTEL_F80; | |
201 | @%:@undef DO | |
202 | return (0); | |
203 | } | |
204 | ])], | |
205 | [sed -n "/^@@@ mdw-probe-fltfmt @<:@^ @:>@* @<:@^ @:>@* = >/p" \ | |
206 | conftest$EXEEXT >conftest.out | |
207 | while read _at _tag ty fmt _eq diag; do | |
208 | case $ty,$fmt,$diag in | |
209 | "float,ieee-f32,>ABCD<") mdw_fltfmt=ieee-f32-le ;; | |
210 | "float,ieee-f32,>DCBA<") mdw_fltfmt=ieee-f32-be ;; | |
211 | "double,ieee-f64,>ABCDEFGH<") mdw_dblfmt=ieee-f64-le ;; | |
212 | "double,ieee-f64,>EFGHABCD<") mdw_dblfmt=ieee-f64-arme ;; | |
213 | "double,ieee-f64,>HGFEDCBA<") mdw_dblfmt=ieee-f64-be ;; | |
214 | "long-double,ieee-f64,>ABCDEFGH<") mdw_ldblfmt=ieee-f64-le ;; | |
215 | "long-double,ieee-f64,>HGFEDCBA<") mdw_ldblfmt=ieee-f64-be ;; | |
216 | "long-double,ieee-f128,>ABCDEFGHIJKLMNOP<") | |
217 | mdw_ldblfmt=ieee-f128-le ;; | |
218 | "long-double,ieee-f128,>PONMLKJIHGFEDCBA<") | |
219 | mdw_ldblfmt=ieee-f128-be ;; | |
220 |