Hi, Here is a test program. Thanks, James
#include <stdio.h> #include <stdbool.h> #include <math.h> #include <float.h>
//#define APIENTRY __stdcall #define APIENTRY //#define FASTCALL __fastcall #define FASTCALL
#ifdef __GNUC__ #define FLOAT_TO_INT(in,out) \ __asm__ __volatile__ ("fistpl %0" : "=m" (out) : "t" (in) : "st"); #else #define FLOAT_TO_INT(in,out) \ __asm fld in \ __asm fistp out #endif
/* the following deal with IEEE single-precision numbers */ #define EXCESS 126L #define SIGNBIT 0x80000000L #define SIGN(fp) ((fp) & SIGNBIT) #define EXP(fp) (((fp) >> 23L) & 0xFF) #define MANT(fp) ((fp) & 0x7FFFFFL) #define PACK(s,e,m) ((s) | ((e) << 23L) | (m))
typedef union // float_long { float f; unsigned long l; char c[4]; } gxf_long;
#ifdef _X86_ typedef long FLOATL; #else /* !_X86_ */ typedef float FLOATL; #endif
typedef struct _FLOATOBJ { unsigned long ul1; unsigned long ul2; } FLOATOBJ, *PFLOATOBJ;
typedef struct _EFLOAT_S { long lMant; long lExp; } EFLOAT_S;
//// //// void FASTCALL EF_Negate(EFLOAT_S * efp) { efp->lMant = -efp->lMant; }
long FASTCALL EFtoF( EFLOAT_S * efp) { long Mant, Exp, Sign = 0;
if (!efp->lMant) return 0; printf("EFtoF %x : %x\n", efp->lMant, efp->lExp);
Mant = efp->lMant; Exp = efp->lExp; Sign = SIGN(efp->lMant); //// M$ storage emulation if( Sign ) Mant = -Mant; Mant = ((Mant & 0x3fffffff)>>7); Exp += (EXCESS-1); //// Mant = MANT(Mant); return PACK(Sign, Exp, Mant); }
void FASTCALL FtoEF( EFLOAT_S * efp, FLOATL f) { long Mant, Exp, Sign = 0; gxf_long worker; printf("FtoEF\n"); #ifdef _X86_ worker.l = f; // It's a float stored in a long. #else worker.f = f; #endif
Exp = EXP(worker.l); Mant = MANT(worker.l); if (SIGN(worker.l)) Sign = -1; //// M$ storage emulation Mant = ((Mant << 7) | 0x40000000); Mant ^= Sign; // invert/mask it Mant -= Sign; // sub it Exp -= (EXCESS-1); //// efp->lMant = Mant; efp->lExp = Exp; }
void APIENTRY FLOATOBJ_Neg ( PFLOATOBJ pf ) { EFLOAT_S * efp = (EFLOAT_S *)pf; EF_Negate(efp); }
long APIENTRY FLOATOBJ_GetFloat ( PFLOATOBJ pf ) { EFLOAT_S * efp = (EFLOAT_S *)pf; return EFtoF(efp); }
void APIENTRY FLOATOBJ_SetFloat( PFLOATOBJ pf, FLOATL f ) { EFLOAT_S * efp = (EFLOAT_S *)pf; FtoEF( efp, f); }
long APIENTRY FLOATOBJ_GetLong( PFLOATOBJ pf ) { EFLOAT_S * efp = (EFLOAT_S *)pf; gxf_long f; long l;
f.l = EFtoF( efp ); FLOAT_TO_INT(f.f, l); // Let FPP handle it the fasty haxy way.
return l; }
void APIENTRY FLOATOBJ_SetLong( PFLOATOBJ pf, long l ) { EFLOAT_S * efp = (EFLOAT_S *)pf; gxf_long f; f.f = (float) l; // Convert it now. #ifdef _X86_ FtoEF( efp, f.l ); #else FtoEF( efp, f.f ); #endif }
long FT_FixedFromFloat(float f) { short value = f; unsigned short fract = (f - value) * 0xFFFF; return (long)((long)value << 16 | (unsigned long)fract); }
double F2F(PFLOATOBJ f) { printf("F2F --> %x : %x\n", f->ul1, f->ul2); if(SIGN(f->ul1)) // negate mant return (double) -(-f->ul1 * pow(2,(double)f->ul2-32)); else return (double) f->ul1 * pow(2,(double)f->ul2-32); }
void Test_It(float fx) { FLOATOBJ pf; gxf_long f;
f.f = fx;
printf("Start 1 %f\n", f.f); printf(" 2 %x\n", f.l);
#ifdef _X86_ FLOATOBJ_SetFloat( &pf, f.l ); #else FLOATOBJ_SetFloat( &pf, f.f ); #endif // FLOATOBJ_Neg ( &pf );
f.l = FLOATOBJ_GetFloat ( &pf ); printf("Fin 1 %f\n",f.f); printf("Fin 2 %x\n",f.l);
printf("F2F --> %f\n\n",F2F( &pf )); }
// // gcc -Os fpms.c -o f -lm // or // gcc -Os -D_X86_ fpms.c -o f -lm // main() { gxf_long f;
f.f = 1.0; Test_It(f.f);
f.f = -1.0; Test_It(f.f);
f.f = 2.0; Test_It(f.f);
f.f = -2.0; Test_It(f.f);
f.f = 1.5; Test_It(f.f);
f.f = -1.5; Test_It(f.f);
f.f = 1235.0; Test_It(f.f);
f.f = -1235.0; Test_It(f.f);
f.f = 1235678.9; // Max it Test_It(f.f);
f.f = -1235678.9; Test_It(f.f);
}