1 /* $Id: ieee754-misc.c,v 1.3 2006/11/16 01:05:56 fredette Exp $ */
2 
3 /* ic/ieee754/ieee754-misc.c - IEEE 754 miscellaneous: */
4 
5 /*
6  * Copyright (c) 2004 Matt Fredette
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Matt Fredette.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <tme/common.h>
37 _TME_RCSID("$Id: ieee754-misc.c,v 1.3 2006/11/16 01:05:56 fredette Exp $");
38 
39 /* includes: */
40 #include <tme/ic/ieee754.h>
41 
42 /* constants: */
43 
44 const tme_uint32_t tme_ieee754_single_constant_pi = 0x40490fdb;
45 const tme_uint32_t tme_ieee754_single_constant_log10_2 = 0x3e9a209b;
46 const tme_uint32_t tme_ieee754_single_constant_e = 0x402df854;
47 const tme_uint32_t tme_ieee754_single_constant_log2_e = 0x3fb8aa3b;
48 const tme_uint32_t tme_ieee754_single_constant_log10_e = 0x3ede5bd9;
49 const tme_uint32_t tme_ieee754_single_constant_zero = 0x00000000;
50 const tme_uint32_t tme_ieee754_single_constant_ln_2 = 0x3f317218;
51 const tme_uint32_t tme_ieee754_single_constant_ln_10 = 0x40135d8e;
52 const tme_uint32_t tme_ieee754_single_constant_one = 0x3f800000;
53 const struct tme_ieee754_double_constant tme_ieee754_double_constant_pi = { 0x400921fb, 0x5421d100 };
54 const struct tme_ieee754_double_constant tme_ieee754_double_constant_log10_2 = { 0x3fd34413, 0x509f79ff };
55 const struct tme_ieee754_double_constant tme_ieee754_double_constant_e = { 0x4005bf0a, 0x8b145769 };
56 const struct tme_ieee754_double_constant tme_ieee754_double_constant_log2_e = { 0x3ff71547, 0x652b82fe };
57 const struct tme_ieee754_double_constant tme_ieee754_double_constant_log10_e = { 0x3fdbcb7b, 0x1526e50e };
58 const struct tme_ieee754_double_constant tme_ieee754_double_constant_zero = { 0x00000000, 0x00000000 };
59 const struct tme_ieee754_double_constant tme_ieee754_double_constant_ln_2 = { 0x3fe62e42, 0xfefa39ef };
60 const struct tme_ieee754_double_constant tme_ieee754_double_constant_ln_10 = { 0x40026bb1, 0xbbb55516 };
61 const struct tme_ieee754_double_constant tme_ieee754_double_constant_one = { 0x3ff00000, 0x00000000 };
62 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_pi = { 0x4000, 0xc90fdaa2, 0x2168c000 };
63 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_log10_2 = { 0x3ffd, 0x9a209a84, 0xfbcff800 };
64 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_e = { 0x4000, 0xadf85458, 0xa2bb4800 };
65 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_log2_e = { 0x3fff, 0xb8aa3b29, 0x5c17f000 };
66 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_log10_e = { 0x3ffd, 0xde5bd8a9, 0x37287000 };
67 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_zero = { 0x0000, 0x00000000, 0x00000000 };
68 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_ln_2 = { 0x3ffe, 0xb17217f7, 0xd1cf7800 };
69 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_ln_10 = { 0x4000, 0x935d8ddd, 0xaaa8b000 };
70 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_one = { 0x3fff, 0x80000000, 0x00000000 };
71 
72 /* IEEE 754 single precision values of the form 2^x, where x is a power of two: */
73 const tme_uint32_t tme_ieee754_single_constant_2e2ex[] = {
74 
75   /* 2^1: */
76   0x40000000,
77 
78   /* 2^2: */
79   0x40800000,
80 
81   /* 2^4: */
82   0x41800000,
83 
84   /* 2^8: */
85   0x43800000,
86 
87   /* 2^16: */
88   0x47800000,
89 
90   /* 2^32: */
91   0x4f800000,
92 
93   /* 2^64: */
94   0x5f800000
95 };
96 
97 /* IEEE 754 single precision values of the form 2^-x, where x is a power of two: */
98 const tme_uint32_t tme_ieee754_single_constant_2e_minus_2ex[] = {
99 
100   /* 2^-1: */
101   0x3f000000,
102 
103   /* 2^-2: */
104   0x3e800000,
105 
106   /* 2^-4: */
107   0x3d800000,
108 
109   /* 2^-8: */
110   0x3b800000,
111 
112   /* 2^-16: */
113   0x37800000,
114 
115   /* 2^-32: */
116   0x2f800000,
117 
118   /* 2^-64: */
119   0x1f800000
120 };
121 
122 /* IEEE 754 single precision values of the form 10^x, where x is a power of two: */
123 const tme_uint32_t tme_ieee754_single_constant_10e2ex[] = {
124 
125   /* 10^1: */
126   0x41200000,
127 
128   /* 10^2: */
129   0x42c80000,
130 
131   /* 10^4: */
132   0x461c4000,
133 
134   /* 10^8: */
135   0x4cbebc20,
136 
137   /* 10^16: */
138   0x5a0e1bca,
139 
140   /* 10^32: */
141   0x749dc5ae
142 };
143 
144 /* IEEE 754 single precision values of the form 10^-x, where x is a power of two: */
145 const tme_uint32_t tme_ieee754_single_constant_10e_minus_2ex[] = {
146 
147   /* 10^-1: */
148   0x3dcccccd,
149 
150   /* 10^-2: */
151   0x3c23d70b,
152 
153   /* 10^-4: */
154   0x38d1b719,
155 
156   /* 10^-8: */
157   0x322bcc7a,
158 
159   /* 10^-16: */
160   0x24e6959d,
161 
162   /* 10^-32: */
163   0x0a4fb12e
164 };
165 
166 /* IEEE 754 double precision values of the form 2^x, where x is a power of two: */
167 const struct tme_ieee754_double_constant tme_ieee754_double_constant_2e2ex[] = {
168 
169   /* 2^1: */
170   { 0x40000000, 0x00000000 },
171 
172   /* 2^2: */
173   { 0x40100000, 0x00000000 },
174 
175   /* 2^4: */
176   { 0x40300000, 0x00000000 },
177 
178   /* 2^8: */
179   { 0x40700000, 0x00000000 },
180 
181   /* 2^16: */
182   { 0x40f00000, 0x00000000 },
183 
184   /* 2^32: */
185   { 0x41f00000, 0x00000000 },
186 
187   /* 2^64: */
188   { 0x43f00000, 0x00000000 },
189 
190   /* 2^128: */
191   { 0x47f00000, 0x00000000 },
192 
193   /* 2^256: */
194   { 0x4ff00000, 0x00000000 },
195 
196   /* 2^512: */
197   { 0x5ff00000, 0x00000000 }
198 };
199 
200 /* IEEE 754 double precision values of the form 2^-x, where x is a power of two: */
201 const struct tme_ieee754_double_constant tme_ieee754_double_constant_2e_minus_2ex[] = {
202 
203   /* 2^-1: */
204   { 0x3fe00000, 0x00000000 },
205 
206   /* 2^-2: */
207   { 0x3fd00000, 0x00000000 },
208 
209   /* 2^-4: */
210   { 0x3fb00000, 0x00000000 },
211 
212   /* 2^-8: */
213   { 0x3f700000, 0x00000000 },
214 
215   /* 2^-16: */
216   { 0x3ef00000, 0x00000000 },
217 
218   /* 2^-32: */
219   { 0x3df00000, 0x00000000 },
220 
221   /* 2^-64: */
222   { 0x3bf00000, 0x00000000 },
223 
224   /* 2^-128: */
225   { 0x37f00000, 0x00000000 },
226 
227   /* 2^-256: */
228   { 0x2ff00000, 0x00000000 },
229 
230   /* 2^-512: */
231   { 0x1ff00000, 0x00000000 }
232 };
233 
234 /* IEEE 754 double precision values of the form 10^x, where x is a power of two: */
235 const struct tme_ieee754_double_constant tme_ieee754_double_constant_10e2ex[] = {
236 
237   /* 10^1: */
238   { 0x40240000, 0x00000000 },
239 
240   /* 10^2: */
241   { 0x40590000, 0x00000000 },
242 
243   /* 10^4: */
244   { 0x40c38800, 0x00000000 },
245 
246   /* 10^8: */
247   { 0x4197d784, 0x00000000 },
248 
249   /* 10^16: */
250   { 0x4341c379, 0x37e08000 },
251 
252   /* 10^32: */
253   { 0x4693b8b5, 0xb5056e17 },
254 
255   /* 10^64: */
256   { 0x4d384f03, 0xe93ff9f6 },
257 
258   /* 10^128: */
259   { 0x5a827748, 0xf9301d33 },
260 
261   /* 10^256: */
262   { 0x75154fdd, 0x7f73bf3f }
263 };
264 
265 /* IEEE 754 double precision values of the form 10^-x, where x is a power of two: */
266 const struct tme_ieee754_double_constant tme_ieee754_double_constant_10e_minus_2ex[] = {
267 
268   /* 10^-1: */
269   { 0x3fb99999, 0x9999999a },
270 
271   /* 10^-2: */
272   { 0x3f847ae1, 0x47ae147c },
273 
274   /* 10^-4: */
275   { 0x3f1a36e2, 0xeb1c4330 },
276 
277   /* 10^-8: */
278   { 0x3e45798e, 0xe2308c3f },
279 
280   /* 10^-16: */
281   { 0x3c9cd2b2, 0x97d889ca },
282 
283   /* 10^-32: */
284   { 0x3949f623, 0xd5a8a74c },
285 
286   /* 10^-64: */
287   { 0x32a50ffd, 0x44f4a766 },
288 
289   /* 10^-128: */
290   { 0x255bba08, 0xcf8c9808 },
291 
292   /* 10^-256: */
293   { 0x0ac80628, 0x64ac6ffd }
294 };
295 
296 /* IEEE 754 extended80 precision values of the form 2^x, where x is a power of two: */
297 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_2e2ex[] = {
298 
299   /* 2^1: */
300   { 0x4000, 0x80000000, 0x00000000 },
301 
302   /* 2^2: */
303   { 0x4001, 0x80000000, 0x00000000 },
304 
305   /* 2^4: */
306   { 0x4003, 0x80000000, 0x00000000 },
307 
308   /* 2^8: */
309   { 0x4007, 0x80000000, 0x00000000 },
310 
311   /* 2^16: */
312   { 0x400f, 0x80000000, 0x00000000 },
313 
314   /* 2^32: */
315   { 0x401f, 0x80000000, 0x00000000 },
316 
317   /* 2^64: */
318   { 0x403f, 0x80000000, 0x00000000 },
319 
320   /* 2^128: */
321   { 0x407f, 0x80000000, 0x00000000 },
322 
323   /* 2^256: */
324   { 0x40ff, 0x80000000, 0x00000000 },
325 
326   /* 2^512: */
327   { 0x41ff, 0x80000000, 0x00000000 },
328 
329   /* 2^1024: */
330   { 0x43ff, 0x80000000, 0x00000000 },
331 
332   /* 2^2048: */
333   { 0x47ff, 0x80000000, 0x00000000 },
334 
335   /* 2^4096: */
336   { 0x4fff, 0x80000000, 0x00000000 },
337 
338   /* 2^8192: */
339   { 0x5fff, 0x80000000, 0x00000000 }
340 };
341 
342 /* IEEE 754 extended80 precision values of the form 2^-x, where x is a power of two: */
343 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_2e_minus_2ex[] = {
344 
345   /* 2^-1: */
346   { 0x3ffe, 0x80000000, 0x00000000 },
347 
348   /* 2^-2: */
349   { 0x3ffd, 0x80000000, 0x00000000 },
350 
351   /* 2^-4: */
352   { 0x3ffb, 0x80000000, 0x00000000 },
353 
354   /* 2^-8: */
355   { 0x3ff7, 0x80000000, 0x00000000 },
356 
357   /* 2^-16: */
358   { 0x3fef, 0x80000000, 0x00000000 },
359 
360   /* 2^-32: */
361   { 0x3fdf, 0x80000000, 0x00000000 },
362 
363   /* 2^-64: */
364   { 0x3fbf, 0x80000000, 0x00000000 },
365 
366   /* 2^-128: */
367   { 0x3f7f, 0x80000000, 0x00000000 },
368 
369   /* 2^-256: */
370   { 0x3eff, 0x80000000, 0x00000000 },
371 
372   /* 2^-512: */
373   { 0x3dff, 0x80000000, 0x00000000 },
374 
375   /* 2^-1024: */
376   { 0x3bff, 0x80000000, 0x00000000 },
377 
378   /* 2^-2048: */
379   { 0x37ff, 0x80000000, 0x00000000 },
380 
381   /* 2^-4096: */
382   { 0x2fff, 0x80000000, 0x00000000 },
383 
384   /* 2^-8192: */
385   { 0x1fff, 0x80000000, 0x00000000 }
386 };
387 
388 /* IEEE 754 extended80 precision values of the form 10^x, where x is a power of two: */
389 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_10e2ex[] = {
390 
391   /* 10^1: */
392   { 0x4002, 0xa0000000, 0x00000000 },
393 
394   /* 10^2: */
395   { 0x4005, 0xc8000000, 0x00000000 },
396 
397   /* 10^4: */
398   { 0x400c, 0x9c400000, 0x00000000 },
399 
400   /* 10^8: */
401   { 0x4019, 0xbebc2000, 0x00000000 },
402 
403   /* 10^16: */
404   { 0x4034, 0x8e1bc9bf, 0x04000000 },
405 
406   /* 10^32: */
407   { 0x4069, 0x9dc5ada8, 0x2b70b800 },
408 
409   /* 10^64: */
410   { 0x40d3, 0xc2781f49, 0xffcfb000 },
411 
412   /* 10^128: */
413   { 0x41a8, 0x93ba47c9, 0x80e99800 },
414 
415   /* 10^256: */
416   { 0x4351, 0xaa7eebfb, 0x9df9f800 },
417 
418   /* 10^512: */
419   { 0x46a3, 0xe319a0ae, 0xa60ed800 },
420 
421   /* 10^1024: */
422   { 0x4d48, 0xc9767586, 0x81758800 },
423 
424   /* 10^2048: */
425   { 0x5a92, 0x9e8b3b5d, 0xc53e2000 },
426 
427   /* 10^4096: */
428   { 0x7525, 0xc4605202, 0x8a227800 }
429 };
430 
431 /* IEEE 754 extended80 precision values of the form 10^-x, where x is a power of two: */
432 const struct tme_ieee754_extended80_constant tme_ieee754_extended80_constant_10e_minus_2ex[] = {
433 
434   /* 10^-1: */
435   { 0x3ffb, 0xcccccccc, 0xccccd000 },
436 
437   /* 10^-2: */
438   { 0x3ff8, 0xa3d70a3d, 0x70a3e000 },
439 
440   /* 10^-4: */
441   { 0x3ff1, 0xd1b71758, 0xe2198000 },
442 
443   /* 10^-8: */
444   { 0x3fe4, 0xabcc7711, 0x8461f800 },
445 
446   /* 10^-16: */
447   { 0x3fc9, 0xe69594be, 0xc44e5000 },
448 
449   /* 10^-32: */
450   { 0x3f94, 0xcfb11ead, 0x453a6000 },
451 
452   /* 10^-64: */
453   { 0x3f2a, 0xa87fea27, 0xa53b3000 },
454 
455   /* 10^-128: */
456   { 0x3e55, 0xddd0467c, 0x64c04000 },
457 
458   /* 10^-256: */
459   { 0x3cac, 0xc0314325, 0x637fe800 },
460 
461   /* 10^-512: */
462   { 0x395a, 0x9049ee32, 0xdb2c8800 },
463 
464   /* 10^-1024: */
465   { 0x32b5, 0xa2a682a5, 0xda6b6800 },
466 
467   /* 10^-2048: */
468   { 0x256b, 0xceae534f, 0x34682000 },
469 
470   /* 10^-4096: */
471   { 0x0ad8, 0xa6dd04c8, 0xd31f4800 }
472 };
473 
474 /* the native floating-point exception function: */
475 void
tme_ieee754_exception_float(int exceptions,void * _ieee754_ctl)476 tme_ieee754_exception_float(int exceptions, void *_ieee754_ctl)
477 {
478   struct tme_ieee754_ctl *ieee754_ctl;
479 
480   /* recover our global control: */
481   ieee754_ctl = (struct tme_ieee754_ctl *) _ieee754_ctl;
482 
483   /* signal the exception: */
484   (*ieee754_ctl->tme_ieee754_ctl_exception)(ieee754_ctl, exceptions);
485 }
486 
487 /* the softfloat unlock function: */
488 int
tme_ieee754_unlock_softfloat(void)489 tme_ieee754_unlock_softfloat(void)
490 {
491   int exceptions;
492 
493   tme_ieee754_global_ctl = NULL;
494   exceptions = tme_ieee754_global_exceptions;
495   tme_mutex_unlock(&tme_ieee754_global_mutex);
496   return (exceptions);
497 }
498 
499 /* for processors that manage a fundamentally single-precision
500    floating-point register file, but that allow size-aligned sets of
501    registers to combine into double- and quad-precision registers,
502    this manages the register set and converts register contents
503    between formats: */
504 void
tme_ieee754_fpreg_format(struct tme_float * fpregs,unsigned int * fpreg_sizes,unsigned int fpreg_number,unsigned int fpreg_size_new)505 tme_ieee754_fpreg_format(struct tme_float *fpregs,
506 			 unsigned int *fpreg_sizes,
507 			 unsigned int fpreg_number,
508 			 unsigned int fpreg_size_new)
509 {
510   unsigned int flags;
511   unsigned int fpreg_size_old;
512   unsigned int format_new_ieee754;
513   const unsigned int formats_ieee754[] =
514   { 0,
515     TME_FLOAT_FORMAT_IEEE754_SINGLE,
516     TME_FLOAT_FORMAT_IEEE754_DOUBLE,
517     0,
518     TME_FLOAT_FORMAT_IEEE754_QUAD };
519   unsigned int fpreg_i;
520   unsigned int fpreg_j;
521   unsigned int single_word_i;
522   unsigned int single_word_i_mask;
523   tme_uint32_t value_single_buffer;
524   const union tme_value64 *value_double;
525   union tme_value64 value_double_buffer;
526   const struct tme_float_ieee754_quad *value_quad;
527   struct tme_float_ieee754_quad value_quad_buffer;
528   tme_uint32_t single_words[sizeof(struct tme_float_ieee754_quad) / sizeof(tme_uint32_t)];
529 
530   /* remove the flags from the size: */
531   flags = (fpreg_size_new & (TME_IEEE754_FPREG_FORMAT_BUILTIN | TME_IEEE754_FPREG_FORMAT_ENDIAN_BIG));
532   fpreg_size_new ^= flags;
533 
534   /* the size of the new IEEE754 format must be a power of two: */
535   assert (fpreg_size_new > 0
536 	  && fpreg_size_new < TME_ARRAY_ELS(single_words)
537 	  && (fpreg_size_new & (fpreg_size_new - 1)) == 0);
538 
539   /* the register number must be aligned: */
540   assert ((fpreg_number & (fpreg_size_new - 1)) == 0);
541 
542   /* if this register is not already the right size: */
543   fpreg_size_old = fpreg_sizes[fpreg_number];
544   if (__tme_predict_false(fpreg_size_old != fpreg_size_new)) {
545 
546     /* convert all of the registers that contain any part of this
547        register's value into single-precision format: */
548     fpreg_j = TME_MAX(fpreg_size_old, fpreg_size_new);
549     fpreg_i = fpreg_number & (0 - fpreg_j);
550     fpreg_j += fpreg_i;
551     do {
552 
553       /* get the current size of this register and its
554 	 single-precision words: */
555       fpreg_size_old = fpreg_sizes[fpreg_i];
556       switch (fpreg_size_old) {
557 
558       default: assert(FALSE);
559 
560 	/* a single-precision register: */
561       case (sizeof(tme_uint32_t) / sizeof(tme_uint32_t)):
562 	single_words[0] = *tme_ieee754_single_value_get(&fpregs[fpreg_i], &value_single_buffer);
563 	break;
564 
565 	/* a double-precision register: */
566       case (sizeof(union tme_value64) / sizeof(tme_uint32_t)):
567 	value_double = tme_ieee754_double_value_get(&fpregs[fpreg_i], &value_double_buffer);
568 	single_words[0] = value_double->tme_value64_uint32_lo;
569 	single_words[1] = value_double->tme_value64_uint32_hi;
570 	break;
571 
572 	/* a quad-precision register: */
573       case (sizeof(struct tme_float_ieee754_quad) / sizeof(tme_uint32_t)):
574 	value_quad = tme_ieee754_quad_value_get(&fpregs[fpreg_i], &value_quad_buffer);
575 	single_words[0] = value_quad->tme_float_ieee754_quad_lo.tme_value64_uint32_lo;
576 	single_words[1] = value_quad->tme_float_ieee754_quad_lo.tme_value64_uint32_hi;
577 	single_words[2] = value_quad->tme_float_ieee754_quad_hi.tme_value64_uint32_lo;
578 	single_words[3] = value_quad->tme_float_ieee754_quad_hi.tme_value64_uint32_hi;
579 	break;
580       }
581 
582       /* if this floating-point register file is organized in
583 	 little-endian fashion, the least significant single-precision
584 	 word goes with the first register, else the most significant
585 	 single-precision word goes with the first register: */
586       single_word_i_mask
587 	= (((flags & TME_IEEE754_FPREG_FORMAT_ENDIAN_BIG) == 0)
588 	   ? 0
589 	   : (fpreg_size_old - 1));
590 
591       /* make all of the covered floating-point registers single
592          precision: */
593       single_word_i = 0;
594       do {
595 	fpregs[fpreg_i].tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE;
596 	fpregs[fpreg_i].tme_float_value_ieee754_single = single_words[single_word_i ^ single_word_i_mask];
597 	fpreg_sizes[fpreg_i] = sizeof(tme_uint32_t) / sizeof(tme_uint32_t);
598 	single_word_i++;
599 	fpreg_i++;
600       } while (--fpreg_size_old > 0);
601     } while (fpreg_i < fpreg_j);
602 
603     /* if the desired format isn't single-precision: */
604     if (fpreg_size_new != (sizeof(tme_uint32_t) / sizeof(tme_uint32_t))) {
605 
606       /* collect the single-precision words from the covered
607 	 floating-point registers, and mark all of them as now
608 	 belonging to this larger register: */
609       fpreg_i = fpreg_number;
610       fpreg_j = fpreg_i + fpreg_size_new;
611       do {
612 	single_words[fpreg_i - fpreg_number]
613 	  = *tme_ieee754_single_value_get(&fpregs[fpreg_i], &value_single_buffer);
614 	fpreg_sizes[fpreg_i] = fpreg_size_new;
615 	fpreg_i++;
616       } while (fpreg_i < fpreg_j);
617 
618       /* if this floating-point register file is organized in
619 	 little-endian fashion, the first single-precision register
620 	 provides the least significant word, else the first
621 	 single-precision register provides the most significant word: */
622       single_word_i_mask
623 	= (((flags & TME_IEEE754_FPREG_FORMAT_ENDIAN_BIG) == 0)
624 	   ? 0
625 	   : (fpreg_size_new - 1));
626 
627       switch (fpreg_size_new) {
628 
629       default: assert(FALSE);
630 
631 	/* a double-precision register: */
632       case (sizeof(union tme_value64) / sizeof(tme_uint32_t)):
633 	fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_DOUBLE;
634 	fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint32_lo
635 	  = single_words[0 ^ single_word_i_mask];
636 	fpregs[fpreg_number].tme_float_value_ieee754_double.tme_value64_uint32_hi
637 	  = single_words[1 ^ single_word_i_mask];
638 	break;
639 
640 	/* a quad-precision register: */
641       case (sizeof(struct tme_float_ieee754_quad) / sizeof(tme_uint32_t)):
642 	fpregs[fpreg_number].tme_float_format = TME_FLOAT_FORMAT_IEEE754_QUAD;
643 	fpregs[fpreg_number].tme_float_value_ieee754_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_lo
644 	  = single_words[0 ^ single_word_i_mask];
645 	fpregs[fpreg_number].tme_float_value_ieee754_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_hi
646 	  = single_words[1 ^ single_word_i_mask];
647 	fpregs[fpreg_number].tme_float_value_ieee754_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_lo
648 	  = single_words[2 ^ single_word_i_mask];
649 	fpregs[fpreg_number].tme_float_value_ieee754_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_hi
650 	  = single_words[3 ^ single_word_i_mask];
651 	break;
652       }
653     }
654   }
655 
656   /* if the register must be in the exact IEEE754 format (as opposed
657      to the best-match, but different, builtin type), and it isn't in
658      that format: */
659   format_new_ieee754 = formats_ieee754[fpreg_size_new];
660   if (__tme_predict_false((flags & TME_IEEE754_FPREG_FORMAT_BUILTIN) == 0
661 			  && fpregs[fpreg_number].tme_float_format != format_new_ieee754)) {
662 
663     /* convert from the builtin type to the IEEE754 format: */
664     switch (format_new_ieee754) {
665     default: assert(FALSE);
666     case TME_FLOAT_FORMAT_IEEE754_SINGLE:
667       fpregs[fpreg_number].tme_float_value_ieee754_single
668 	= *tme_ieee754_single_value_get(&fpregs[fpreg_number], &value_single_buffer);
669       break;
670     case TME_FLOAT_FORMAT_IEEE754_DOUBLE:
671       fpregs[fpreg_number].tme_float_value_ieee754_double
672 	= *tme_ieee754_double_value_get(&fpregs[fpreg_number], &value_double_buffer);
673       break;
674     case TME_FLOAT_FORMAT_IEEE754_QUAD:
675       fpregs[fpreg_number].tme_float_value_ieee754_quad
676 	= *tme_ieee754_quad_value_get(&fpregs[fpreg_number], &value_quad_buffer);
677       break;
678     }
679     fpregs[fpreg_number].tme_float_format = format_new_ieee754;
680   }
681 }
682 
683 #include "ieee754-misc-auto.c"
684