Files
glide/swlibs/fxmisc/fx64.h
2004-10-04 09:41:26 +00:00

267 lines
7.2 KiB
C

/*
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
**
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
** THE UNITED STATES.
**
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
**
** $Revision$
** $Date$
*/
#ifndef __FX64_H__
#define __FX64_H__
#include "3dfx.h"
/*
** first figure out what compiler/os we are using and what is supported
*/
/*
** WATCOMC
*/
#if defined(__WATCOMC__)
#define FX_BIT64(n) ( FX_SHL64( i64_one, n ) )
/*
** GCC
*/
#elif defined(__GNUC__)
typedef signed long long FxI64;
typedef unsigned long long FxU64;
#define NATIVE_64_SUPPORT 1
#define FX_MASK64(n) (0xFFFFFFFFFFFFFFFFLL >> (64-(n)))
#define FX_BIT64(n) (((FxI64)1) << (n))
/*
** Microsoft C
*/
#elif defined(_MSC_VER)
typedef signed __int64 FxI64;
typedef unsigned __int64 FxU64;
#define FX_MASK64(n) (0xFFFFFFFFFFFFFFFF >> (64-(n)))
#define FX_BIT64(n) (((FxI64)1) << (n))
#define NATIVE_64_SUPPORT 1
#endif
/*
** The following code is for systems with native 64-bit data types
*/
#ifdef NATIVE_64_SUPPORT
#define FX_ADD64( a, b ) ((a) + (b))
#define FX_AND64( a, b ) ((a) & (b))
#define FX_CMP64( a, b ) error
#define FX_COMP64( a ) (~(a))
#define FX_CREATE64( a, b ) ( (((FxI64) (a)) << 32) | (b) )
#define FX_COPY32( a, b ) a = (b)
#define FX_EQ064( a ) ( (a) == 0 )
#define FX_LO64(a) ((FxI32)(a))
#define FX_HI64(a) ((FxI32)FX_SHR64(a,32))
#define FX_MUL32( a, b ) (( FxI64 )( ( FxI64 ) (a) * ( FxI64 ) (b) ) )
#define FX_MUL64( a, b ) ((a) * (b))
#define FX_NEG64( a ) (-(a))
#define FX_OR64( a, b ) ((a) | (b))
#define FX_SET64( a, b, c ) a = (c) | (((FxI64)(b))<<32)
#define FX_SHL64( a, n ) ((a) << (n)) // n < 64
#define FX_SHR64( a, n ) ((a) >> (n)) // n < 64
#define FX_SUB64( a, b ) ((a) - (b))
#define FX_XOR64( a, b ) ((a) ^ (b))
#define FX_FLOATTO64( a ) ((FxI64)(a))
#define FX_64TOFLOAT( a ) (float)(a)
#define FX_64TODBL( a ) (double)(a)
/*
** The following code is for Watcom C
*/
#else
typedef struct
{
FxI32 hi;
FxU32 lo;
} FxI64;
typedef struct
{
FxU32 hi;
FxU32 lo;
} FxU64;
extern FxI64 i64_one;
extern FxI64 i64_zero;
#define FX_ADD64( a, b ) ( __FX_ADD64( (a).hi, (a).lo, (b).hi, (b).lo ) )
#define FX_AND64( a, b ) ( __FX_AND64( a, b ) )
#define FX_CMP64( a, b ) ( __FX_CMP64( a, b ) )
#define FX_COMP64( a ) ( __FX_COMP64( a ) )
#define FX_CREATE64( a, b ) ( __FX_CREATE64( a, b ) )
#define FX_COPY32( a, b ) ( a = __FX_32TO64( (b) ) )
#define FX_EQ064( a ) ( ( (a).lo == 0 ) && ( (a).hi == 0 ) )
#define FX_HI64( a ) ( (a).hi )
#define FX_LO64( a ) ( (a).lo )
#define FX_MASK64( n ) ( __FX_MASK64( n ) )
#define FX_MUL32( a, b ) ( __FX_MUL32( (a), (b) ) )
#define FX_MUL64( a, b ) ( __FX_MUL64( (a), (b) ) )
#define FX_NEG64( a ) ( __FX_NEG64( (a).hi, (a).lo ) )
#define FX_OR64( a, b ) ( __FX_OR64( a, b ) )
#define FX_SET64( a, b, c ) do {(a).hi = b; (a).lo = c;} while(0)
#define FX_SHL64( a, n ) ( __FX_SHL64( (a).hi, (a).lo, n ) )
#define FX_SHR64( a, n ) ( __FX_SHR64( (a).hi, (a).lo, n ) )
#define FX_SUB64( a, b ) ( __FX_SUB64( (a).hi, (a).lo, (b).hi, (b).lo ) )
#define FX_FLOATTO64( a ) ( __FX_FLOATTO64((a)) )
#define FX_64TOFLOAT( a ) ( __FX_64TOFLOAT((a)) )
/*
** The following functions are implemented as inline assembly
*/
FxI64 __FX_ADD64( FxI32 a_hi, FxU32 a_lo, FxI32 b_hi, FxU32 b_lo );
FxI64 __FX_32TO64( FxI32 value );
FxI64 __FX_MASK64( int n );
FxI64 __FX_MUL32( FxI32 a, FxI32 b );
FxI64 __FX_NEG64( FxI32 hi, FxU32 lo );
FxI64 __FX_SHL64( FxI32 hi, FxU32 lo, int n );
FxI64 __FX_SHR64( FxI32 hi, FxU32 lo, int n );
FxI64 __FX_SUB64( FxI32 a_hi, FxU32 a_lo, FxI32 b_hi, FxU32 b_lo );
/*
** The following functions are implemented as C functions
*/
FxI64 __FX_AND64( FxI64 a, FxI64 b );
int __FX_CMP64( FxI64 a, FxI64 b );
FxI64 __FX_COMP64( FxI64 a );
FxI64 __FX_CREATE64( FxI32 a, FxU32 b );
FxI64 __FX_FLOATTO64( float a );
FxI64 __FX_MUL64( FxI64 a, FxI64 b );
FxI64 __FX_OR64( FxI64 a, FxI64 b );
float __FX_64TOFLOAT( FxI64 );
#pragma aux __FX_32TO64 = \
"cdq" \
"mov [esi], edx" \
"mov [esi+4], eax" \
parm [eax] \
modify [edx] \
value struct struct;
#pragma aux __FX_ADD64 = \
"add eax, ecx" \
"adc edx, ebx" \
"mov [esi], edx" \
"mov [esi+4], eax" \
parm [edx] [eax] [ebx] [ecx] \
value struct struct;
#pragma aux __FX_MUL32 = \
"imul edx" \
"mov [esi], edx" \
"mov [esi+4], eax" \
parm [edx] [eax] \
value struct struct;
#pragma aux __FX_SUB64 = \
"sub eax, ecx" \
"sbb edx, ebx" \
"mov [esi], edx" \
"mov [esi+4], eax" \
parm [edx] [eax] [ebx] [ecx] \
value struct struct;
#pragma aux __FX_SHL64 = \
"cmp cl, 32" \
"jl SHL_LT32" \
"sub cl, 32" \
"mov edx, eax " \
"mov eax, 0 " \
"shl edx, cl" \
"jmp SHL_DONE" \
"SHL_LT32:" \
"shld edx, eax, cl" \
"sal eax, cl" \
"SHL_DONE:" \
"mov [esi], edx" \
"mov [esi+4], eax" \
parm [edx] [eax] [cx] \
value struct struct;
#pragma aux __FX_SHR64 = \
"cmp cl, 32" \
"jl SHR_LT32" \
"sub cl, 32 " \
"mov eax, edx" \
"test edx, 080000000h" \
"jz SHR_GE32_POSITIVE" \
"SHR_GE32_NEGATIVE:" \
"mov edx, 0FFFFFFFFh" \
"or eax, 080000000h" \
"sar eax, cl" \
"jmp SHR_DONE" \
"SHR_GE32_POSITIVE:" \
"mov edx, 0" \
"shr eax, cl" \
"jmp SHR_DONE" \
"SHR_LT32: " \
"shrd eax, edx, cl" \
"sar edx, cl" \
"SHR_DONE: " \
"mov [esi], edx" \
"mov [esi+4], eax" \
parm [edx] [eax] [cx] \
value struct struct;
#pragma aux __FX_NEG64 = \
"neg eax" \
"adc edx, 0" \
"neg edx" \
"mov [esi], edx" \
"mov [esi+4], eax" \
parm [edx] [eax] \
value struct struct;
#pragma aux __FX_MASK64 = \
"mov edx, 64" \
"sub edx, ecx" \
"mov ecx, edx" \
"mov edx, 0ffffffffh" \
"mov eax, 0ffffffffh" \
"cmp cl, 32" \
"jl M64_LT32" \
"sub cl, 32 " \
"mov eax, edx" \
"mov edx, 0" \
"shr eax, cl" \
"jmp M64_DONE" \
"M64_LT32: " \
"shrd eax, edx, cl" \
"shr edx, cl" \
"M64_DONE: " \
"mov [esi], edx" \
"mov [esi+4], eax" \
modify [edx eax] \
parm [ecx] \
value struct struct;
#endif /* __WATCOMC__ */
/*
** The following is shared between NATIVE64 and Watcom
*/
// a | -(a & (1 << n)) branchless, but may not be good implement for PC
// for constant n, does &, -, |
#define FX_SGNEXT64( a, n ) (FX_OR64((a), FX_NEG64(FX_AND64((a), FX_SHL64(FX_CREATE64(0,1), (n))))))
#endif /* __FX64_H__ */