|
|
1.1 root 1: #! /bin/sh
2:
3: # $Id: ieee754-ops-auto.sh,v 1.2 2005/03/23 11:47:37 fredette Exp $
4:
5: # ic/ieee754/ieee754-misc-auto.sh - automatically generates C code
6: # for IEEE 754 emulation operations:
7:
8: #
9: # Copyright (c) 2004 Matt Fredette
10: # All rights reserved.
11: #
12: # Redistribution and use in source and binary forms, with or without
13: # modification, are permitted provided that the following conditions
14: # are met:
15: # 1. Redistributions of source code must retain the above copyright
16: # notice, this list of conditions and the following disclaimer.
17: # 2. Redistributions in binary form must reproduce the above copyright
18: # notice, this list of conditions and the following disclaimer in the
19: # documentation and/or other materials provided with the distribution.
20: # 3. All advertising materials mentioning features or use of this software
21: # must display the following acknowledgement:
22: # This product includes software developed by Matt Fredette.
23: # 4. The name of the author may not be used to endorse or promote products
24: # derived from this software without specific prior written permission.
25: #
26: # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27: # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28: # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29: # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
30: # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31: # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32: # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34: # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35: # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: # POSSIBILITY OF SUCH DAMAGE.
37: #
38:
39: header=false
40:
41: for option
42: do
43: case $option in
44: --header) header=true ;;
45: esac
46: done
47:
48: PROG=`basename $0`
49: cat <<EOF
50: /* automatically generated by $PROG, do not edit! */
51: #include <tme/common.h>
52: _TME_RCSID("\$Id: ieee754-ops-auto.sh,v 1.2 2005/03/23 11:47:37 fredette Exp $");
53:
54: EOF
55: if $header; then
56: :
57: else
58: cat <<EOF
59: #include "softfloat-tme.h"
60: #include <math.h>
61: EOF
62: fi
63:
64: # the precision information helper script:
65: #
66: ieee754_precision_sh=`echo $0 | sed -e "s/$PROG/ieee754-precision.sh/"`
67:
68: # the different compliance levels:
69: #
70: levels="strict partial unknown"
71:
72: # permute for the different compliance levels:
73: #
74: for level in ${levels}; do
75:
76: # permute for functions or for a set:
77: #
78: for what in funcs set; do
79:
80: # if we're generating headers:
81: #
82: if $header; then
83:
84: # if we're doing the strict-level functions, start the
85: # operations struct type:
86: #
87: if test "${level}-${what}" = strict-funcs; then
88: echo "/* the IEEE 754 operations: */"
89: echo "struct tme_ieee754_ops {"
90: echo ""
91: echo " /* the version of this structure: */"
92: echo " tme_uint32_t tme_ieee754_ops_version;"
93:
94:
95: # otherwise, if we're doing a set, just declare the set
96: # and continue:
97: #
98: elif test ${what} = set; then
99: echo ""
100: echo "/* the ${level} compliance operations: */"
101: echo "extern _tme_const struct tme_ieee754_ops tme_ieee754_ops_${level};"
102: continue
103: fi
104:
105: # otherwise, if we're doing a set:
106: #
107: elif test ${what} = set; then
108:
109: # start the operations set for this level:
110: #
111: echo ""
112: echo "/* the ${level} compliance operations: */"
113: echo "_tme_const struct tme_ieee754_ops tme_ieee754_ops_${level} = {"
114: echo ""
115: echo " /* the version of this structure: */"
116: echo " TME_X_VERSION(0, 0),"
117: fi
118:
119: # permute for the different precisions:
120: #
121: for precision in single double extended80 quad; do
122:
123: # get information about this precision:
124: #
125: eval `sh ${ieee754_precision_sh} ${precision}`
126:
127: # generate the operations:
128: #
129: for name in add sub mul div \
130: rem sqrt abs neg move \
131: rint \
132: cos acos cosh \
133: sin asin sinh \
134: tan atan tanh atanh \
135: exp expm1 log10 log log1p \
136: getexp getman scale \
137: pow \
138: from_single from_double from_extended80 from_quad \
139: to_int32 to_int64 \
140: ; do
141:
142: # get the characteristics of this operation that are the
143: # same at all compliance levels:
144: #
145: monadic=true
146: case "${name}" in
147: add | sub | mul | div | rem | pow | scale)
148: monadic=false
149: ;;
150: esac
151: dst_type="struct tme_float"
152: case "${name}" in
153: to_int32) dst_type="tme_int32_t" ;;
154: esac
155:
156: # we don't need a function to convert from the same
157: # precision to this precision:
158: #
159: from_precision=
160: case "${name}" in
161: from_*)
162: from_precision=`echo ${name} | sed -e 's/^from_//'`
163: if test ${from_precision} = ${precision}; then
164: continue
165: fi
166: ;;
167: esac
168:
169: # if we're generating headers:
170: #
171: if $header; then
172:
173: # only emit this header information if we're
174: # doing the strict level functions:
175: #
176: if test "${level}-${what}" = strict-funcs; then
177: echo ""
178: echo " /* this does a ${precision}-precision "`echo ${name} | tr _ -`": */"
179: echo -n " void (*tme_ieee754_ops_${precision}_${name}) _TME_P((struct tme_ieee754_ctl *, "
180: if $monadic; then :; else
181: echo -n "_tme_const struct tme_float *, "
182: fi
183: echo "_tme_const struct tme_float *, ${dst_type} *));"
184: fi
185:
186: continue
187: fi
188:
189: # start with no function for this set:
190: #
191: func_set=' NULL,'
192:
193: # permute for the stricter compliance levels:
194: #
195: for level_stricter in ${levels}; do
196:
197: # form this function name:
198: #
199: func="_tme_ieee754_${level_stricter}_${precision}_${name}"
200:
201: # the function type is normally determined by
202: # whether or not a softfloat function, libm
203: # function, or C operator is given. it can be
204: # overridden:
205: #
206: type=
207: func_softfloat=
208: func_libm=
209: func_libm_has_f=true
210: op_builtin=
211:
212: # any preprocessor condition controlling whether or not
213: # the function can be emitted is normally determined by
214: # the function type. it can be overridden:
215: #
216: cond=
217:
218: # assume that we will use the operands as passed
219: # in. the precisions will later default to the
220: # precision of the result, if they are not
221: # overridden:
222: #
223: op0=src0
224: op0_precision=
225: if $monadic; then op1= ; else op1=src1 ; fi
226: op1_precision=
227:
228: # miscellaneous attributes:
229: #
230: src0_buffer=
231: src0_precision=
232: src1_buffer=
233: src1_precision=
234: check_nan=
235: check_inf_src0=
236: enter_softfloat=
237: enter_native=
238:
239: # characterize this operation at this compliance level:
240: #
241: case "${level_stricter}-${name}" in
242: strict-add | strict-sub | strict-mul | strict-div | strict-rem | strict-sqrt)
243: func_softfloat="${name}"
244: ;;
245: *-add) op_builtin='+' ;;
246: *-sub) op_builtin='-' ;;
247: *-mul) op_builtin='*' ;;
248: *-div) op_builtin='/' ;;
249: *-sqrt) func_libm=sqrt ;;
250: partial-abs | unknown-abs) func_libm=fabs ;;
251: strict-neg) op0=0 ; func_softfloat=sub ; op1=src0 ;;
252: partial-neg | unknown-neg) op0=0 ; op_builtin='-'; op1=src0 ;;
253: strict-move) func_softfloat=add ; op1=0 ;;
254: *-move) type="${level_stricter}-move" ; src0_buffer=false ;;
255: strict-rint) func_softfloat=round_to_int ;;
256: partial-pow | unknown-pow) func_libm="${name}" ;;
257: partial-log | unknown-log) func_libm="${name}" ;;
258: partial-exp | unknown-exp) func_libm="${name}" ;;
259: partial-log10 | unknown-log10) func_libm="${name}" ;;
260: partial-scale | unknown-scale) func_libm=scalbn ;;
261: strict-getexp | strict-getman) type="${level_stricter}-${name}" ; check_nan=true ; check_inf_src0=return-nan ;;
262: strict-from_*) func_softfloat="OP0_PRECISION_SF_to_${precision_sf}" ; op0_precision="${from_precision}" ;;
263: strict-to_int32) type="${level_stricter}-${name}" ; func_softfloat="${precision_sf}_${name}" ;;
264: esac
265:
266: # finish typing this function:
267: #
268: if test "x${type}" = x; then
269: if test "x${func_softfloat}" != x; then
270: type=softfloat
271: elif test "x${func_libm}" != x; then
272: type=libm
273: elif test "x${op_builtin}" != x; then
274: type=builtin
275: else
276: type=none
277: fi
278: fi
279:
280: # finish the preprocessor condition controlling
281: # whether or not the function can be emitted:
282: #
283: if test "x${cond}" = x; then
284: case "${precision}-${level_stricter}-${type}" in
285:
286: # a function with a none type can't be emitted:
287: #
288: *-*-none) cond=0 ;;
289:
290: # extended80 or quad precision softfloat
291: # functions are conditional on a 64-bit
292: # integral type:
293: #
294: extended80-*-softfloat | quad-*-softfloat) cond="defined(TME_HAVE_INT64_T)" ;;
295:
296: # partial compliance functions are conditional
297: # on the builtin type being an exact match for
298: # the IEEE 754 type:
299: #
300: *-partial-*) cond="(TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_IEEE754_${capprecision})" ;;
301:
302: # assume that anything else can be unconditionally emitted:
303: #
304: *) cond=1 ;;
305: esac
306: fi
307:
308: # finish the operands:
309: #
310: for _opn in 0 1; do
311: eval "opn=\$op${_opn}"
312: if test "x${opn}" = x; then
313: continue
314: fi
315: eval "opn_precision=\$op${_opn}_precision"
316: if test "x${opn_precision}" = x; then
317: opn_precision="${precision}"
318: fi
319: eval `sh ${ieee754_precision_sh} ${opn_precision} opn_`
320: case "${opn}" in
321: src[01])
322: eval "${opn}_precision=\$opn_precision"
323: if test "x${func_softfloat}" != x || test "x${func_libm}${op_builtin}" = x; then
324: eval "srcn_buffer=\$${opn}_buffer"
325: if test "x${srcn_buffer}" = x; then
326: eval "${opn}_buffer=true"
327: fi
328: opn="tme_ieee754_${opn_precision}_value_get(${opn}, &${opn}_buffer)"
329: if test "x${func_softfloat}" != x; then
330: opn="((const ${opn_precision_sf} *) ${opn})"
331: fi
332: opn="(*${opn})"
333: else
334: opn="tme_ieee754_${opn_precision}_value_builtin_get(${opn})"
335: fi
336: ;;
337: [0-9])
338: if test "x${func_softfloat}" != x; then
339: opn="int32_to_${opn_precision_sf}(${opn})"
340: fi
341: ;;
342: esac
343: eval "op${_opn}=\$opn"
344: eval "op${_opn}_precision=\$opn_precision"
345: eval "op${_opn}_precision_sf=\$opn_precision_sf"
346: eval "op${_opn}_integral=\$opn_integral"
347: done
348:
349: # finish the miscellaneous attributes:
350: #
351: if test "x${src0_buffer}" = x; then
352: src0_buffer=false
353: fi
354: if test "x${src1_buffer}" = x; then
355: src1_buffer=false
356: fi
357: if test "x${check_nan}" = x; then
358: if test "${level_stricter}" = partial; then
359: check_nan=true
360: else
361: check_nan=false
362: fi
363: fi
364: if test "x${enter_softfloat}" = x; then
365: if test "x${func_softfloat}" != x; then
366: enter_softfloat=true
367: else
368: enter_softfloat=false
369: fi
370: fi
371: if test "x${enter_native}" = x; then
372: if test "${level_stricter}" = partial; then
373: enter_native=true
374: else
375: enter_native=false
376: fi
377: fi
378:
379: # if we're making functions, and we're at the
380: # right level to emit this function, and this
381: # function can be emitted:
382: #
383: if test ${what} = funcs && test ${level_stricter} = ${level} && test "${cond}" != 0; then
384:
385: # start any conditional:
386: #
387: if test "${cond}" != 1; then
388: echo ""
389: echo "#if ${cond}"
390: fi
391:
392: # start the function:
393: #
394: echo ""
395: echo "/* this does a ${level} compliance ${precision}-precision "`echo ${name} | tr _ -`": */"
396: echo "static void"
397: echo -n "${func}(struct tme_ieee754_ctl *ieee754_ctl, const struct tme_float *src0, "
398: if $monadic; then :; else
399: echo -n "const struct tme_float *src1, "
400: fi
401: echo "${dst_type} *dst)"
402: echo "{"
403:
404: # emit locals:
405: #
406: if ${src0_buffer}; then
407: echo " ${op0_integral} src0_buffer;"
408: fi
409: if ${src1_buffer}; then
410: echo " ${op1_integral} src1_buffer;"
411: fi
412: echo " int exceptions;"
413:
414: # check the operand(s):
415: #
416: if ${check_nan}; then
417: echo ""
418: echo " /* check for a NaN operand: */"
419: if $monadic; then nanf=monadic; src1= ; else nanf=dyadic; src1=", src1"; fi
420: echo " if (__tme_predict_false(tme_ieee754_${src0_precision}_check_nan_${nanf}(ieee754_ctl, src0${src1}, dst))) {"
421: echo " return;"
422: echo " }"
423: fi
424: if test "x${check_inf_src0}" != x; then
425: echo ""
426: echo " /* if the operand is an infinity: */"
427: echo " if (tme_ieee754_${precision}_is_inf(src0)) {"
428: echo ""
429: case "${check_inf_src0}" in
430: return-nan)
431: echo " /* return a NaN: */"
432: echo " dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_${capprecision};"
433: echo " dst->tme_float_value_ieee754_${precision} = ieee754_ctl->tme_ieee754_ctl_default_nan_${precision};"
434: echo " return;"
435: ;;
436: esac
437: echo " }"
438: fi
439:
440: # enter the operation mode:
441: #
442: if ${enter_softfloat}; then
443: echo ""
444: echo " /* enter softfloat operation: */"
445: echo " tme_mutex_lock(&tme_ieee754_global_mutex);"
446: echo " tme_ieee754_global_ctl = ieee754_ctl;"
447: echo " tme_ieee754_global_exceptions = 0;"
448: echo " ieee754_ctl->tme_ieee754_ctl_lock_unlock = tme_ieee754_unlock_softfloat;"
449: fi
450: if ${enter_native}; then
451: echo ""
452: echo " /* enter native floating-point operation: */"
453: echo " tme_float_enter(ieee754_ctl->tme_ieee754_ctl_rounding_mode, tme_ieee754_exception_float, ieee754_ctl);"
454: echo " ieee754_ctl->tme_ieee754_ctl_lock_unlock = tme_float_leave;"
455: fi
456:
457: # assume that this operation raises no exceptions:
458: #
459: echo ""
460: echo " /* assume that this operation raises no exceptions: */"
461: echo " exceptions = 0;"
462:
463: # the operation:
464: #
465: echo ""
466: echo " /* the operation: */"
467: case "${type}" in
468:
469: # a move operation:
470: #
471: *-move)
472: echo " *dst = *src0;"
473: ;;
474:
475: # a getexp operation:
476: #
477: strict-getexp)
478: echo ""
479: echo " /* if the operand is a zero, return a zero: */"
480: echo " if (tme_ieee754_${precision}_is_zero(src0)) {"
481: echo " tme_ieee754_${precision}_value_builtin_set(dst, TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN, 0);"
482: echo " }"
483: echo ""
484: echo " /* otherwise, return the unbiased exponent: */"
485: echo " else {"
486: echo " tme_ieee754_${precision}_value_builtin_set(dst, TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN, TME_FIELD_MASK_EXTRACTU(${op0}${sexp}, ${mask_exp}) - ${exp_bias});"
487: echo " }"
488: ;;
489:
490: # a getman operation:
491: #
492: strict-getman)
493: echo ""
494: echo " /* if the operand is a zero, return it: */"
495: echo " if (tme_ieee754_${precision}_is_zero(src0)) {"
496: echo " *dst = *src0;"
497: echo " }"
498: echo ""
499: echo " /* otherwise, return the operand, with its exponent set to biased zero: */"
500: echo " else {"
501: echo " tme_ieee754_${precision}_value_set(dst, ${op0});"
502: echo " TME_FIELD_MASK_DEPOSITU(dst->tme_float_value_ieee754_${precision}${sexp}, ${mask_exp}, ${exp_bias});"
503: echo " }"
504: ;;
505:
506: # a strict to-integer conversion operation:
507: #
508: strict-to_int32 | strict-to_int64)
509: echo " *dst = ${precision_sf}_${name}(${op0});"
510: ;;
511:
512: # a softfloat operation:
513: #
514: softfloat)
515: echo " _tme_ieee754_${precision}_value_set(dst, ${precision_sf},"
516: func_softfloat_raw="${func_softfloat}"
517: func_softfloat=`echo ${func_softfloat} | sed -e "s/OP0_PRECISION_SF/${op0_precision_sf}/g"`
518: func_softfloat=`echo ${func_softfloat} | sed -e "s/OP1_PRECISION_SF/${op0_precision_sf}/g"`
519: if test "${func_softfloat}" = "${func_softfloat_raw}"; then
520: func_softfloat="${precision_sf}_${func_softfloat}"
521: fi
522: echo -n " ${func_softfloat}(${op0}"
523: if test "x${op1}" != x; then
524: echo ","
525: echo -n " ${op1}"
526: fi
527: echo "));"
528: ;;
529:
530: # a libm operation:
531: #
532: libm)
533: if test "x${op1}" = x; then ops="${op0}"; else ops="${op0}, ${op1}"; fi
534: # if there is a float variant of this libm function:
535: #
536: if ${func_libm_has_f}; then
537: echo "#if (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN == TME_FLOAT_FORMAT_FLOAT)"
538: echo " tme_ieee754_${precision}_value_builtin_set(dst, TME_FLOAT_FORMAT_FLOAT, ${func_libm}f(${ops}));"
539: echo "#else /* (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN != TME_FLOAT_FORMAT_FLOAT) */"
540: fi
541: echo " tme_ieee754_${precision}_value_builtin_set(dst, TME_FLOAT_FORMAT_DOUBLE, ${func_libm}(${ops}));"
542: if ${func_libm_has_f}; then
543: echo "#endif /* (TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN != TME_FLOAT_FORMAT_FLOAT) */"
544: fi
545: ;;
546:
547: # a builtin operation:
548: #
549: builtin)
550: echo " tme_ieee754_${precision}_value_builtin_set(dst, TME_FLOAT_FORMAT_IEEE754_${capprecision}_BUILTIN, ${op0} ${op_builtin} ${op1});"
551: ;;
552:
553: *)
554: echo "$PROG internal error: don't know how to generate a ${type} type operation" 1>&2
555: exit 1
556: ;;
557: esac
558:
559: # leave the operation mode:
560: #
561: if ${enter_native}; then
562: echo ""
563: echo " /* leave native floating-point operation: */"
564: echo " exceptions |= tme_float_leave();"
565: fi
566: if ${enter_softfloat}; then
567: echo ""
568: echo " /* leave softfloat operation: */"
569: echo " tme_ieee754_global_ctl = NULL;"
570: echo " exceptions |= tme_ieee754_global_exceptions;"
571: echo " tme_mutex_unlock(&tme_ieee754_global_mutex);"
572: fi
573: echo " ieee754_ctl->tme_ieee754_ctl_lock_unlock = NULL;"
574:
575: # signal any exceptions:
576: #
577: echo ""
578: echo " /* signal any exceptions: */"
579: echo " if (exceptions != 0) {"
580: echo " (*ieee754_ctl->tme_ieee754_ctl_exception)(ieee754_ctl, exceptions);"
581: echo " }"
582:
583: # end the function:
584: #
585: echo "}"
586:
587: # close any conditional:
588: #
589: if test "${cond}" != 1; then
590: echo ""
591: echo "#endif /* ${cond} */"
592: fi
593: fi
594:
595: # update the function for this set:
596: #
597: case "${cond}" in
598: 0) ;;
599: 1) func_set=" ${func}," ;;
600: *) func_set="#if (${cond})@ ${func},@#else /* !(${cond}) */@${func_set}@#endif /* !(${cond}) */" ;;
601: esac
602:
603: # stop now if we just did this level:
604: #
605: if test ${level_stricter} = ${level}; then
606: break
607: fi
608: done
609:
610: # if we're making a set:
611: #
612: if test ${what} = set; then
613: echo ""
614: echo " /* this does a ${level} compliance ${precision}-precision ${name}: */"
615: echo "${func_set}" | tr '@' '\n'
616: fi
617:
618: done
619: done
620:
621: # if we're generating headers:
622: #
623: if $header; then
624:
625: # if we're doing the strict-level functions, close the
626: # operations struct type:
627: #
628: if test "${level}-${what}" = strict-funcs; then
629: echo "};"
630: fi
631:
632: # otherwise, if we're doing a set:
633: #
634: elif test ${what} = set; then
635:
636: # close the operations set for this level:
637: #
638: echo "};"
639: fi
640:
641: done
642:
643: done
644:
645: # if we're not generating headers:
646: #
647: if $header; then :; else
648:
649: echo ""
650: echo "/* this looks up an operations structure: */"
651: echo "const struct tme_ieee754_ops *"
652: echo "tme_ieee754_ops_lookup(const char *compliance)"
653: echo "{"
654: echo ""
655: for level in ${levels}; do
656: echo " if (TME_ARG_IS(compliance, \"${level}\")) { "
657: echo " return (&tme_ieee754_ops_${level});"
658: echo " }"
659: done
660: echo " return (NULL);"
661: echo "}"
662:
663: echo ""
664: echo "/* this is a compliance options string: */"
665: echo -n "const char * const tme_ieee754_compliance_options = \"{ ";
666: sep=
667: for level in ${levels}; do
668: echo -n "${sep}${level}"
669: sep=' | '
670: done
671: echo " }\";"
672: fi
673:
674: # done:
675: #
676: exit 0;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.