1
0
forked from 0ad/0ad

# add strict VSrc validation in OpenAL interface to track down bug

- required adding C99 insnan() implementation, along with fpclassify

This was SVN commit r3850.
This commit is contained in:
janwas 2006-05-05 05:54:00 +00:00
parent 6a4816a512
commit a35ee9894d
5 changed files with 80 additions and 2 deletions

View File

@ -1827,11 +1827,22 @@ static void vsrc_latch(VSrc* vs)
if(!vs->al_src)
return;
#ifndef NDEBUG
// paranoid value checking; helps determine which parameter is
// the problem when the below AL_CHECK fails.
debug_assert(!isnan(vs->pos[0]) && !isnan(vs->pos[1]) && !isnan(vs->pos[2]));
debug_assert(vs->relative == AL_TRUE || vs->relative == AL_FALSE);
debug_assert(!isnan(vs->gain));
debug_assert(!isnan(vs->pitch) && vs->pitch > 0.0f);
debug_assert(vs->loop == AL_TRUE || vs->loop == AL_FALSE);
#endif
alSourcefv(vs->al_src, AL_POSITION, vs->pos);
alSourcei (vs->al_src, AL_SOURCE_RELATIVE, vs->relative);
alSourcef (vs->al_src, AL_GAIN, vs->gain);
alSourcef (vs->al_src, AL_PITCH, vs->pitch);
alSourcei (vs->al_src, AL_LOOPING, vs->loop);
AL_CHECK;
}

View File

@ -54,6 +54,16 @@ extern i32 ia32_i32_from_float(float f);
extern i32 ia32_i32_from_double(double d);
extern i64 ia32_i64_from_double(double d);
// fpclassify return values
#define IA32_FP_NAN 0x0100
#define IA32_FP_NORMAL 0x0400
#define IA32_FP_INFINITE (IA32_FP_NAN | IA32_FP_NORMAL)
#define IA32_FP_ZERO 0x4000
#define IA32_FP_SUBNORMAL (IA32_FP_NORMAL | IA32_FP_ZERO)
extern uint ia32_fpclassify(double d);
extern uint ia32_fpclassifyf(float f);
extern void* ia32_memcpy(void* dst, const void* src, size_t nbytes); // asm

View File

@ -503,10 +503,10 @@ db 0xf0 ; LOCK prefix
;-------------------------------------------------------------------------------
; misc
; FPU
;-------------------------------------------------------------------------------
; extern "C" uint __cdecl ia32_control87(uint new_cw, uint mask)
; extern "C" uint __cdecl ia32_control87(uint new_cw, uint mask);
global sym(ia32_control87)
sym(ia32_control87):
push eax
@ -525,6 +525,32 @@ sym(ia32_control87):
ret
; possible IA-32 FPU control word flags after FXAM: NAN|NORMAL|ZERO
FP_CLASSIFY_MASK equ 0x4500
; extern "C" uint __cdecl ia32_fpclassify(double d);
global sym(ia32_fpclassify)
sym(ia32_fpclassify):
fld qword [esp+4]
fxam
fnstsw ax
and eax, FP_CLASSIFY_MASK
ret
; extern "C" uint __cdecl ia32_fpclassifyf(float f);
global sym(ia32_fpclassifyf)
sym(ia32_fpclassifyf):
fld dword [esp+4]
fxam
fnstsw ax
and eax, FP_CLASSIFY_MASK
ret
;-------------------------------------------------------------------------------
; misc
;-------------------------------------------------------------------------------
; write the current execution state (e.g. all register values) into
; (Win32::CONTEXT*)pcontext (defined as void* to avoid dependency).
; optimized for size; this must be straight asm because __declspec(naked)

View File

@ -51,6 +51,21 @@ float fmaxf(float a, float b)
return (a > b)? a : b;
}
uint fpclassify(double d)
{
// really sucky stub implementation; doesn't attempt to cover all cases.
if(d != d)
return IA32_FP_NAN;
else
return IA32_FP_NORMAL;
}
uint fpclassifyf(float f)
{
return fpclassify((double)f);
}
#endif
#endif // #if !HAVE_C99

View File

@ -101,13 +101,29 @@ extern void* alloca(size_t size);
# define rint ia32_rint
# define fminf ia32_fminf
# define fmaxf ia32_fmaxf
# define FP_NAN IA32_FP_NAN
# define FP_NORMAL IA32_FP_NORMAL
# define FP_INFINITE (FP_NAN | FP_NORMAL)
# define FP_ZERO IA32_FP_ZERO
# define FP_SUBNORMAL (FP_NORMAL | FP_ZERO)
# define fpclassify ia32_fpclassify
// .. portable C emulation
# else
extern float rintf(float f);
extern double rint(double d);
extern float fminf(float a, float b);
extern float fmaxf(float a, float b);
# define FP_NAN 1
# define FP_NORMAL 2
# define FP_INFINITE (FP_NAN | FP_NORMAL)
# define FP_ZERO 4
# define FP_SUBNORMAL (FP_NORMAL | FP_ZERO)
extern uint fpclassify(double d);
# endif
# define isnan(d) (fpclassify(d) == FP_NAN)
#endif
// finite: return 0 iff the given double is infinite or NaN.