Mail Archives: djgpp-workers/2003/05/10/18:03:23
Heloo.
C99 means we should make a fpclassify macro. Easy:
#define fpclassify(x) ((sizeof(x)==sizeof(float))? __fpclassifyf(x) : \
(sizeof(x)==sizeof(double))? __fpclassifyd(x) : \
__fpclassifyld(x))
This returns FP_INFINITE, FP_NAN, FP_NORMAL, FP_SUBNORMAL or FP_ZERO,
or FP_UNNORMAL (extension allowed), depending on value of x.
This will be used in these C99 macros:
#define isfinite(x) (fpclassify(x)==FP_NORMAL || \
fpclassify(x)==FP_SUBNORMAL || \
fpclassify(x)==FP_ZERO)
#define isinf(x) (fpclassify(x)==FP_INFINITE)
#define isnan(x) (fpclassify(x)==FP_NAN)
#define isnormal(x) (fpclassify(x)==FP_NORMAL)
As you can see it calls the helper functions __fpclassifyf(),
__fpclassifyd() and __fpclassifyld().
I've coded them in assembly (for fun and to improve my
assembly). Here's __fpclassifyf() for illustration purposes:
/*
* File fpclassf.S.
*
* Copyright (C) 2003 Martin Str@"omberg <ams AT ludd DOT luth DOT se>.
*
* This software may be used freely so long as this copyright notice is
* left intact. There is no warranty on this software.
*
*/
#include <sys/math_def.h>
/*
* Bits: 31 (sign), 30-23 (exponent), 22-0 (fraction)
* Zero: +/- 0 0
* Subnormal +/- 0 !=0
* Normal +/- !=0, <0xff any
* Infinity: +/- 0xff 0
* NaN: any 0xff !=0
*/
.globl ___fpclassifyf
___fpclassifyf:
movl 4(%esp), %eax
movl %eax, %edx
andl $0x7f800000, %eax
jz zero_exponent
cmpl $0x7f800000, %eax
je all_ones_exponent
movl $FP_NORMAL, %eax
ret
zero_exponent:
movl $FP_ZERO, %eax
testl $0x7fffff, %edx
jz zero
movl $FP_SUBNORMAL, %eax
zero:
ret
all_ones_exponent:
movl $FP_INFINITE, %eax
testl $0x7fffff, %edx
jz infinity
movl $FP_NAN, %eax
infinity:
ret
Now, as you can see this includes <sys/math_def.h> which I created,
because #including <math.h> made as very unhappy. Here's the start of
what I get if I try to include <math,h>:
E:/DJGPP/BIN/make.exe -C c99/math
gcc ... -c fpclassf.S
t:\tmp\cc2qguYe.s: Assembler messages:
t:\tmp\cc2qguYe.s:32: Error: no such instruction: `extern double __dj_huge_val'
t:\tmp\cc2qguYe.s:36: Error: no such instruction: `double acos(double _x)'
t:\tmp\cc2qguYe.s:37: Error: no such instruction: `double asin(double _x)'
t:\tmp\cc2qguYe.s:38: Error: no such instruction: `double atan(double _x)'
t:\tmp\cc2qguYe.s:39: Error: no such instruction: `double atan2(double _y,double _x)'
Clearly the prototypes mess it up.
<math.h> includes <sys/math_def.h> too of course. <sys/math_def.h> is:
#ifndef __dj_include_sys_math_def_h_
#define __dj_include_sys_math_def_h_
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
|| !defined(__STRICT_ANSI__)
#define FP_INFINITE 0
#define FP_NAN 1
#define FP_NORMAL 2
#define FP_SUBNORMAL 3
#define FP_ZERO 4
/* Extended with Unnormals (for long doubles). */
#define FP_UNNORMAL 1024
#endif /* (__STDC_VERSION__ >= 199901L) || !__STRICT_ANSI__ */
#endif /* !__dj_include_sys_math_def_h_ */
The reason for all this is that I need the #defines of FP_* in my
assembly.
Is there a better way to do it?
Right,
MartinS
- Raw text -