/*
 enviro64.h
  All-in-one environment include,
   featuring 32 bit macros for 64 bit routines

  Created: 2008.06.16
  Revised: 2026.03.19 - moved int_clamp here

24.12.30 - make sure _ssize_t and envx64 are properly defined
24.11.21, 1.27 - more support for GNUC
23.09.11 - moved s_float80 to ftrig.h
23.08.08 - added int128
23.08.02 - added u_xmm128
21.09.27 - added MK2CC
21.09.25 - clashing calling convention with _bswap
19.03.23 - added va_lexx, va_nexx
18.12.23 - consistent uint16 for 16-bit endian macros
17.12.04 - muls64su32 (added 11.27)
17.11.07 - fixed 32-bit system xint64shx
16.07.17 - __cdecl with POCC64
15.07.02 - fixed some level-2 warnings
14.08.03 - fixed non-68k _xint64shr
14.07.31 - reversexx & _reversexx
4.12 - Use of _bswap intrinsic for ARM.
4.09 - Endian converters are now forcibly lvalues.
4.07 - Modern: int for int32, as 'long' can be 64 bits.
3.13 - Added missing xint64mulx32 HL macros under non-LONG_LONG.
2.20 - Fixed LONG_LONG multipliers - were performing divides!
..
*/
/*
In use:
  The former xintxx_t here are now just xintxx (remove interfering typedefs).
  Try to avoid casts.
  `int` should optimally be 32 bits (4 bytes).

  Some macros may need a (void) cast when result isn't used to avoid warnings.

IMPORTANT:
  Some macros may use any of their parameters more than once; it's recommended that you
use only direct values or variables for those. Let the compiler deal with optimizations.

  Routines/macros that use their parameters only _once_:
	int64hi/int64lo, int64n
	int64addhl/uint64addhl, int64addhls/uint64addhls, int64addu32/uint64addu32
	int64subhl/uint64subhl, int64subu32/uint64subu32
	muls64s32/muls64u32/muls64su32/mulu64s32/mulu64u32

  The 64 bit routines do not saturate result; they may return the lower or higher 32
bits and/or sign depending on application.
*/

#ifndef __ENVIRO64_H

/* pass the int type or identifier for max/min values */
#define IMIN(x)			(-1L<<(sizeof(x)*8-1))
#define IMAX(x)			~IMIN(x)
#define IMIN64			(-9223372036854775808.0)

/* min/max method is faster on i3 and others */
//#define int16Clamp(v)	((v)!=(int16)(v) ? (v)>>31^0x7FFF:(v))
#define INTCLAMP(v,t)		MIN(MAX(v,IMIN(t)),IMAX(t))
#define UINTCLAMP(v,t)		MIN(MAX(v,0),IMAX(t)*2+1u)
#define INT16CLAMP(v)		INTCLAMP(v,int16)
#define UINT16CLAMP(v)		UINTCLAMP(v,uint16)
#define IFRACTCLAMP(v)		MIN(MAX(v,-1<<30),(1<<30)-1)

#define OFFSET(t,f)		(size_t)(&((t*)0)->f)
/* only use direct variables/constants with these */
#define GET_ARRAY_COUNT(a)	(sizeof(a)/sizeof((a)[0]))
#define SGN(v)			((v)?(v)<0?-1:1:0)
#define ABS(v)			((v)>=0?(v):-(v))
#define MAX(a,b)		((a)>(b)?(a):(b))
#define MIN(a,b)		((a)<(b)?(a):(b))
#define PIN(x,l,h)		((x)<(l)?(l):(x)>(h)?(h):(x))
#define SWAP(a,b)		do{if(sizeof(a)==1) {int8 v=a; a=b,b=v;} \
	else if(sizeof(a)==2) {int16 v=a; a=b,b=v;} else if(sizeof(a)==4) \
	{int32 v=*(int32*)&(a); a=b,*(int32*)&(b)=v;} else if(sizeof(a)==8) \
	{int64 v=*(int64*)&(a); a=b,*(int64*)&(b)=v;}}while(0)

/* this part is mostly originally from ConditionalMacros.h */

/* enivonment defines:
	env68k			MC68020+ (Motorola, Inc.)
	envppc			PowerPC 60x compatible (Motorola/IBM)
	envx86			80486+ (Intel Corp.)
	envx64			64-bit, including x86 set
	envarm			ARM (32-bit+ + long multiply)
	envmrx			MIPS MRX000 (Silicon Graphics Inc.)
	envspr			Sparc (Sun Microsystems Inc.)
	envalp			Alpha
*/

#ifdef __MRC__
 #define envppc 1
 #define TARGET_OS_MAC 1
 #define LONG_LONG 1
 #if (__MRC__>0x300) && (__MRC__<0x700)
  #if __option(longlong)
   #define LONG_LONG 1
  #endif
 #endif

#elif defined(__SC__) && (defined(MPW_CPLUS) || defined(MPW_C))
 #define TARGET_OS_MAC 1
 #if __option(mc68020)
  #define env68k 1
 #endif

#elif defined(__MWERKS__)
 #if (__MWERKS__<0x900)||macintosh
  #define TARGET_OS_MAC 1
  #if powerc
   #define envppc 1
  #else
   #define env68k 1
  #endif
 #elif ((__MWERKS__>=0x1900)&&__MIPS__)||((__MWERKS__>=0x2110)&&__MACH__)
  #if __MIPS__
   #define envmrx 1
  #elif __MACH__
   #define envppc 1
   #define TARGET_OS_MAC 1
  #endif
  #if !__option(little_endian)
   #define BIG_ENDIAN 1
  #endif
 #endif

 #if (__MWERKS__>=0x1100)
  #if __option(longlong)
   #define LONG_LONG 1
  #endif
 #endif

#elif defined(SC_PLUS_THINK)||defined(SYMANTEC_CPLUS)||defined(SYMANTEC_C)
 #define TARGET_OS_MAC 1
 #if powerc
  #define envppc 1
 #else
  #define env68k 1
 #endif

#elif defined(__GNUC__)&&(defined(__APPLE_CPP__)||defined(__APPLE_CC__)||defined(__NEXT_CPP__))
 #if defined(__ppc__) || defined(powerpc) || defined(ppc)
  #define envppc 1
 #elif defined(m68k)
  #define env68k 1
 #elif defined(sparc)
  #define envspr 1
 #elif defined(__i386__) || defined(i386) || defined(intel)
  #define envx86 1
 #endif

 #if __GNUC__>=2
  #define LONG_LONG 1
 #endif

#elif defined(__GNUC__)
 #if defined(__APPLE__) || defined(__MACH__)
  #define TARGET_OS_MAC 1
  #if #cpu(powerpc)
   #define envppc 1
  #elif #cpu(m68k)
   #define env68k 1
  #endif
 #elif defined(__x86_64__) || defined(_M_X64)
  #define envx64 1
 #elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
  #define envx86 1
 #endif
 #ifndef __forceinline
  #define __forceinline __attribute__((always_inline))
 #endif

 #ifdef __STDC_VERSION__
  #if __STDC_VERSION__>=199901L
   #define LONG_LONG 1
  #endif
  #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
   #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
    #define BIG_ENDIAN 0
   #endif
  #endif
 #endif
 #if !defined(LONG_LONG) && defined(_LONG_LONG)
  #define LONG_LONG 1
 #else
 #endif
 #ifndef LONG_LONG
  #define LONG_LONG 0
 #endif
 #if defined(_WIN64) || defined(__x86_64) || __x86_64__ || defined(_M_IA64)
  #define envx64 1
 #elif defined(_X86_)
  #define envx86 1
 #endif
#elif defined(__xlc)||defined(__xlC)||defined(__xlC__)||defined(__XLC121__)
 #define envppc 1
 #ifdef _LONG_LONG
  #define LONG_LONG 1
 #else
  #define LONG_LONG 0
 #endif
 #if defined(_AIX)
  #define TARGET_OS_MAC 0
 #else
  #define TARGET_OS_MAC 1
 #endif

#elif defined(__POCC__)
 /* moved here due to weird __POCC__/_MSC_VER combo */
 #define LONG_LONG 1
 #if __POCC_TARGET__==1
  #define envx86 1
 #elif __POCC_TARGET__==2
  #define envarm 1
 #elif __POCC_TARGET__==3
  #define envx64 1
 #endif
#elif defined(_MSC_VER) && !defined(__MWERKS__)
 #ifdef _M_M68K
  #define env68k 1
  #define TARGET_OS_MAC 1
 #elif defined(_M_MPPC)
  #define envppc 1 /* _LONG_LONG unsupported */
  #define TARGET_OS_MAC 1
 #elif defined(_M_PPC)
  #define envppc 1 /* _LONG_LONG unsupported */
  #define TARGET_OS_MAC 0
 #elif defined(_M_IX86)
  #define envx86 1
 #elif defined(_M_X64)||defined(_M_AMD64)||defined(__x86_64__)
  #define envx64 1
 #elif defined(_M_ALPHA)
  #define envalp 1
 #elif defined(_M_MRX000)
  #define envmrx 1
 #endif

#elif defined(__MOTO__)
 #define envppc 1 /* no known way to detect _LONG_LONG */
 #define TARGET_OS_MAC 1

#elif defined(_MIPS_ISA)
 #define envmrx 1

#elif defined(__sparc)
 #define envspr 1

#elif MSVC || defined(__LCC__)
 #define LONG_LONG 1

 /* warning: THINK C/Symantec C++ and MPWC/PPCC are obsolete */
#elif defined(THINK_C)||(defined(applec)&&!defined(__SC__))
  #define env68k 1

#elif defined(__PPCC__)
 #define envppc 1
 #define TARGET_OS_MAC 1

#elif !defined(envx86) && !defined(envx64)
 #error Compiler/environ. could not be identified or is unsupported.
#endif

/* Base types:
  Modern compilers are configured for 32b int.
  Older systems use long.
*/
#if LONG_LONG
typedef int		int32;
typedef unsigned int	uint32;
#else
typedef long		int32;
typedef unsigned long	uint32;
#endif
typedef char		int8; /* note: not always signed! */
typedef signed char	sint8;
typedef short		int16;
typedef int32		ifixed, ifract;
typedef unsigned char	uint8;
typedef unsigned short	uint16;
typedef uint32		ufixed, ufract;

 /* default little endian */
#ifndef BIG_ENDIAN
 #if defined(envppc)||defined(env68k)||defined(envspr)
  #define BIG_ENDIAN 1
 #else
  #define BIG_ENDIAN 0
 #endif
#endif

#define _reverse16(x) (uint16)((uint16)(x)>>8|(uint16)(x)<<8)
#define _reverse32(x) ((uint32)(x)<<24|((uint32)(x)<<8&0xFF0000) \
	|((uint32)(x)>>8&0xFF00)|(uint32)(x)>>24)
#define _reverse64(x) (((x)>>56)|(((x)&0xFF000000000000ULL)>>48) \
	|(((x)&0xFF0000000000ULL)>>40)|(((x)&0xFF00000000ULL)>>32) \
        |(((x)&0xFF000000ULL)<<32)(((x)&0xFF0000)<<40) \
        |(((x)&0xFF00)<<48)|(((x)&255)<<56))

#if envx86 || envx64
 #if __POCC__
  #pragma intrinsic(_bswap)
  unsigned int __cdecl _bswap(unsigned int);
  #define reverse32 _bswap
  #define reverse64 _bswap64
  #if __POCC__>=900
   unsigned __int16 _rotr16(unsigned __int16, unsigned __int8);
   #define reverse16(v) _rotr16(v,8)
  #else /* POCC 7 does not offer ror */
   #define reverse16(v) (reverse32(v)>>16)
  #endif
 #elif __GNUC__
  #define reverse16 __builtin_bswap16
  #define reverse32 __builtin_bswap32
  #define reverse64 __builtin_bswap64
 #elif _MSC_VER>=1300
  #pragma intrinsic(_byteswap_ushort)
  #pragma intrinsic(_byteswap_ulong)
  #pragma intrinsic(_byteswap_uint64)
  #define reverse16 _byteswap_ushort
  #define reverse32 _byteswap_ulong
  #define reverse64 _byteswap_uint64
 #endif
 #define va_be16(s) (s=(void*)((int8*)s+2),reverse16(((uint16*)s)[-1]))
 #define va_be32(s) (s=(void*)((int8*)s+4),reverse32(((uint32*)s)[-1]))
 #define va_le16(s) (s=(void*)((int8*)s+2),0+((uint16*)s)[-1])
 #define va_le32(s) (s=(void*)((int8*)s+4),0+((uint32*)s)[-1])
 #define va_ne16 va_le16
 #define va_ne32 va_le32
#elif envarm
 #if __POCC__
  #pragma intrinsic(_bswap)
  unsigned int __cdecl _bswap(unsigned int);
  #define reverse32 _bswap
 #endif
#endif
#ifndef reverse32
 #define reverse32 _reverse32
#endif
#ifndef reverse16
 #define reverse16 _reverse16
 #define reverse64 _reverse64
#endif
#if BIG_ENDIAN
 #ifndef MK4CC
  #define MK4CC(a,b,c,d) ((a)<<24|(uint8)(b)<<16|(uint8)(c)<<8|(uint8)(d))
  #define MK2CC(a,b) ((uint8)(a)<<8|(uint8)(b))
 #endif
 #define be16_native(v) (uint16)(v)
 #define _be16_native be16_native
 #define be32_native(v) (uint32)(v)
 #define _be32_native be32_native
 #define le16_native reverse16
 #define _le16_native _reverse16
 #define le32_native reverse32
 #define _le32_native _reverse32
 #define va_be16(s) (0+*((const uint16*)s)++)
 #define va_be32(s) (0+*((const uint32*)s)++)
 #define va_le16(s) le16_native(*((const uint16*)s)++)
 #define va_le32(s) be32_native(*((const uint32*)s)++)
 #define va_ne16 va_be16
 #define va_ne32 va_be32
#else
 #ifndef MK4CC
  #define MK4CC(a,b,c,d) ((d)<<24|(uint8)(c)<<16|(uint8)(b)<<8|(uint8)(a))
  #define MK2CC(a,b) ((uint8)(b)<<8|(uint8)(a))
 #endif
 #define be16_native reverse16
 #define _be16_native _reverse16
 #define be32_native reverse32
 #define _be32_native _reverse32
 #define le16_native(v) (uint16)(v)
 #define _le16_native le16_native
 #define le32_native(v) (uint32)(v)
 #define _le32_native le32_native
 #ifndef va_be32
  /* sizeof(*s) must divide evenly into respective sizes to work */
  #define va_be16(s) (s=(void*)((int8*)s+2),((uint8*)s)[-2]<<8|((uint8*)s)[-1])
  #define va_be32(s) (s=(void*)((int8*)s+4),((((uint8*)s)[-4]<<8|((uint8*)s)[-3])<<8|((uint8*)s)[-2])<<8|((uint8*)s)[-1])
  #define va_le16(s) (s=(void*)((int8*)s+2),((uint8*)s)[-1]<<8|((uint8*)s)[-2])
  #define va_le32(s) (s=(void*)((int8*)s+4),((((uint8*)s)[-1]<<8|((uint8*)s)[-2])<<8|((uint8*)s)[-3])<<8|((uint8*)s)[-4])
  #define va_ne16 va_le16
  #define va_ne32 va_le32
 #endif
#endif

/* default no long long support */
#ifndef LONG_LONG
 #define LONG_LONG 0
#endif

/* int64 typedef, macros, inlines for all environs. */

#if !defined(_SIZE_T_DEFINED) && !defined(size_t)
 #define _SIZE_T_DEFINED
 #if TARGET_CPU_PPC64||envx64
  #define size_t uint64
 #endif
 #ifndef size_t
  #define size_t uint32
 #endif
#endif
#if defined(_SSIZE_T_DEFINED) && !defined(__POCC_TARGET__)
 typedef ssize_t _ssize_t;
#else
 #define _SSIZE_T_DEFINED
 #if TARGET_CPU_PPC64 || envx64
  #define _ssize_t int64
 #else
  #define _ssize_t int32
 #endif
#endif

#if LONG_LONG
 #if MSVC
  typedef __int64		int64;
  typedef unsigned __int64	uint64;
 #else
  typedef long long		int64;
  typedef unsigned long long	uint64;
 #endif

/* constant-form */
 #define _int64val(h,l)		(((int64)(h)<<32)+(uint32)(l))
 #define _int64xval(f)		((int64)(f))

 #define _int64xset(x,f)	(void)((x)=(long double)(f))
 #define int64xset(x,f)		(void)((x)=(long long)(long double)(f))
 #define int64qset(x,q)		(void)((void)x,(void)(q),(x)=(uint64)(q)<<16)
 #define int64sethl(x,h,l)	(void)((x)=((int64)(h)<<32)+(uint32)(l))
 #define int64setl(x,y)		(void)((void)x,(x)=(long int)(y))
 #define int64set(x,y)		(void)((void)x,(void)(y),(x)=y)

/* high/low 32 */
 #define int64hi(x)		((x)>>32)
 #define int64lo(x)		(uint32)(x)

/* zero, neg., pos. */
 #define int64z(n)		(n,(n)==0)
 #define int64n(n)		((int64)(n)<0)
 #define int64p(n)		(n,(int64)(n)>0)

 #define int64neg(x)		(int32)((x)=-(int64)(x))
 #define uint64neg(x)		(uint32)((x)=(uint64)-(int64)(uint64)(x))

/* convert */
 #define int64toi(n)		((int32)(n)==(int64)(n)?(int32)(n):0x7FFFFFFF^(int32)((uint64)(n)>>63))
 #define int64tol(n)		(n,(long int)(int64)(n))
 #define int64tox(n)		((void)(n),(long double)(n))

/* compare */
 #define int64eq(x,y)		((void)(x),(void)(y),(x)==(y))
 #define int64eqhl(x,h,l)	((void)(x),(x)==((int64)(h)<<32)+(uint32)(l))
 #define int64gt(x,y)		((void)(x),(void)(y),(x)>(y))
 #define int64gthl(x,h,l)	((void)(x),(void)(h),(x)>((int64)(h)<<32)+(uint32)(l))
 #define int64ge(x,y)		((void)(x),(void)(y),(x)>=(y))
 #define int64gehl(x,h,l)	((void)(x),(void)(h),(x)>=((int64)(h)<<32)+(uint32)(l))
 #define uint64gtu32(x,i)	((void)(x),(uint64)(x)>(uint32)(i))

 #define int64add(x,y)		(((x)+=(y))>>32)
 #define uint64add(x,y)		(((x)+=(y))>>32)
 #define int64sub(x,y)		(((x)-=(y))>>32)
 #define uint64sub(x,y)		(((x)-=(y))>>32)

 #define int64or(x,y)		(uint32)((void)(y),(x)=(int64)(x)|(y))
 #define int64eor(x,y)		(uint32)((void)(y),(x)=(int64)(x)^(y))
 #define int64and(x,y)		(uint32)((void)(y),(x)=(int64)(x)&(y))
 #define int64not(x)		(uint32)((void)(x),(void)(x),(x)=~(x))

/* hi/lo modifier - high 32b result */
 #define int64addhl(x,h,l)	(((x)+=((int64)(h)<<32)+(uint32)(l))>>32)
 #define uint64addhl(x,h,l)	(((x)+=((int64)(h)<<32)+(uint32)(l))>>32)
 #define int64subhl(x,h,l)	(((x)-=((int64)(h)<<32)+(uint32)(l))>>32)
 #define uint64subhl(x,h,l)	(((x)-=((int64)(h)<<32)+(uint32)(l))>>32)
/* result for comparison to zero */
 #define int64addhls(x,h,l)	(int64)((x)+=((int64)(h)<<32)+(uint32)(l))
 #define uint64addhls(x,h,l)	(uint64)((x)+=((int64)(h)<<32)+(uint32)(l))
/* add 32b - high 32b result */
 #define int64addu32(x,l)	(((x)+=(uint32)(l))>>32)
 #define uint64addu32(x,l)	(((x)+=(uint32)(l))>>32)
 #define int64adds32(x,l)	((void)(l),((x)+=(int32)(l))>>32)
 #define uint64adds32(x,l)	((void)(l),((x)+=(int32)(l))>>32)

 #define int64subu32(x,l)	(((x)-=(uint32)(l))>>32)
 #define uint64subu32(x,l)	(((x)-=(uint32)(l))>>32)
 #define int64subs32(x,l)	((void)(l),((x)-=(int32)(l))>>32)
 #define uint64subs32(x,l)	((void)(l),((x)-=(int32)(l))>>32)

 #define int64orhl(x,h,l)	(uint32)((void)(x),((x)|=((int64)(h)<<32)+(uint32)(l))>>32)
 #define int64eorhl(x,h,l)	(uint32)((void)(x),((x)^=((int64)(h)<<32)+(uint32)(l))>>32)
 #define int64andhl(x,h,l)	(uint32)((void)(x),((x)&=((int64)(h)<<32)+(uint32)(l))>>32)

/* mutiply & divide */
 #define int64muls32(x,i)	(int32)(x=(int64)(x)*(int32)(i))
 #define uint64muls32(x,i)	(uint32)(x=(uint64)(x)*(int32)(i))
 #define int64mulu32(x,i)	(int32)(x=(int64)(x)*(uint32)(i))
 #define uint64mulu32(x,i)	(uint32)(x=(uint64)(x)*(uint32)(i))

 #define int64divs32(x,i)	(int32)((void)(i),x=(int64)(x)/(int32)(i))
 #define uint64divs32(x,i)	(int32)((void)(i),x=(uint64)(x)/(int32)(i))
 #define int64divu32(x,i)	(int32)(x=(int64)(x)/(uint32)(i))
 #define uint64divu32(x,i)	(uint32)(x=(uint64)(x)/(uint32)(i))
/* 32x32 to yield 64 (+faster intrinsics) */
 #define muls64s32(x,i,j)	(int32)((x)=(int64)(int32)(i)*(int32)(j))
 #define muls64u32(x,i,j)	(int32)((x)=(uint64)(uint32)(i)*(uint32)(j))
 #define muls64su32(x,i,j)	(int32)((x)=(int64)(int32)(i)*(uint32)(j))
 #define mulu64s32(x,i,j)	(uint32)((x)=(int64)(int32)(i)*(int32)(j))
 #define mulu64u32(x,i,j)	(uint32)((x)=(uint64)(uint32)(i)*(uint32)(j))

/* to yield xint32 */
 #define divi32(x,i)		(int32)((int64)(x)/(int32)(i))
 #define divu32(x,i)		(uint32)((uint64)(x)/(uint32)(i))
/* remainder */
 #define divi32r(x,i)		(int32)((int64)(x)%(int32)(i))
 #define divu32r(x,i)		(uint32)((uint64)(x)%(uint32)(i))

/* multiply & divide in one */
 #define imuldiv(n,m,d)		(((int64)((int32)(n))*(int32)(m))/(int32)(d))
 #define umuldiv(n,m,d)		(((uint64)((uint32)(n))*(uint32)(m))/(uint32)(d))

/* to yield xint32 - these only handle a literal count within [0,32] */
 #define _int64shr32(x,c)	(int32)((void)(x),(int64)(x)>>((c)>32?63:c))
 #define _uint64shr32(x,c)	(uint32)((void)(x),(uint64)(x)>>((c)>32?63:c))

 #define int64shl(x,c)		(void)((x)=(int64)(x)<<c)
 #define int64shr(x,c)		(void)((x)=(int64)(x)>>c)
 #define uint64shr(x,c)		(void)((x)=(uint64)(x)>>c)
/* half (divide by two) */
 #define int64half(x)		(void)((x)=(int64)(x)/2)
 #define uint64half(x)		uint64shr(x,1)
#else
 #if BIG_ENDIAN
  typedef struct int64{int32 hi; uint32 lo;} int64;
  typedef struct uint64{uint32 hi, lo;} uint64;

  #ifdef env68k
   /* returns high 32 bits */
   #pragma parameter __D0 _int64addhl(__A0,__D1,__D2)
    extern int32 _int64addhl(int64*,int32,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	ADD.L	D2,(A0)	*/	0xD590,
/*	ADDX.L	D1,D0	*/	0xD181,
/*	MOVE.L	D0,-(A0) */	0x2100
   };
   #pragma parameter __D0 _uint64addhl(__A0,__D1,__D2)
    extern uint32 _uint64addhl(uint64*,int32,uint32) =
	{0x2018,0xD590,0xD181,0x2100};
   /* returns high 32 bits, OR low 16 with low 8 = lo==0 ? 00:FF */
   #pragma parameter __D0 _int64addhls(__A0,__D1,__D2)
    extern int32 _int64addhls(int64*,int32,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	ADD.L	D2,(A0)	*/	0xD590,
/*	SNE	D2	*/	0x56C2,
/*	ADDX.L	D1,D0	*/	0xD181,
/*	MOVE.L	D0,-(A0) */	0x2100,
/*	OR	D2,D0	*/	0x8042
    };
   #pragma parameter __D0 _uint64addhls(__A0,__D1,__D2)
    extern uint32 _uint64addhls(uint64*,int32,uint32) =
	{0x2018,0xD590,0x56C2,0xD181,0x2100,0x8042};

   /* returns high 32 bits */
   #pragma parameter __D0 _int64subhl(__A0,__D1,__D2)
    extern int32 _int64subhl(int64*,int32,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	SUB.L	D2,(A0)	*/	0x9590,
/*	SUBX.L	D1,D0	*/	0x9181,
/*	MOVE.L	D0,-(A0) */	0x2100
    };
   #pragma parameter __D0 _uint64subhl(__A0,__D1,__D2)
    extern uint32 _uint64subhl(uint64*,int32,uint32) =
	{0x2018,0x9590,0x9181,0x2100};

   /* returns low 32b */
   #pragma parameter __D1 _int64divu32(__A0,__D2)
    extern int32 _int64divu32(int64*,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	BPL.S	*+6	;@1 */	0x6A04,
/*	NEG.L	(A0)	*/	0x4490,
/*	NEGX.L	D0	*/	0x4080,
/*@1	MOVE.L	(A0),D1	*/	0x2210,
/*	MOVE.L	D2,(A0)	*/	0x2082,
/*	TDIVU.L	D2,D2:D0 */	0x4C42, 2,
/*	DIVU.L	(A0),D2:D1 */	0x4C50, 0x1402,
/*	TST.L	-(A0)	*/	0x4AA0,
/*	BPL.S	*+6	;@2 */	0x6A04,
/*	NEG.L	D1	*/	0x4481,
/*	NEGX.L	D0	*/	0x4080,
/*@2	MOVE.L	D0,(A0)+ */	0x20C0,
/*	MOVE.L	D1,(A0)	*/	0x2081
    };
   #pragma parameter __A0 pint64divu32(__A0,__D2)
    extern int64 *pint64divu32(int64*,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	BPL.S	*+6	;@1 */	0x6A04,
/*	NEG.L	(A0)	*/	0x4490,
/*	NEGX.L	D0	*/	0x4080,
/*@1	MOVE.L	(A0),D1 */	0x2210,
/*	MOVE.L	D2,(A0)	*/	0x2082,
/*	TDIVU.L	D2,D2:D0 */	0x4C42, 2,
/*	DIVU.L	(A0),D2:D1 */	0x4C50, 0x1402,
/*	TST.L	-(A0)	*/	0x4AA0,
/*	BPL.S	*+6	;@2 */	0x6A04,
/*	NEG.L	D1	*/	0x4481,
/*	NEGX.L	D0	*/	0x4080,
/*@2	MOVE.L	D0,(A0)	*/	0x2080,
/*	MOVE.L	D1,4(A0) */	0x2141, 4
    };
   #pragma parameter __D0 _uint64divu32(__A0,__D2)
    extern uint32 _uint64divu32(uint64*,uint32) = {
/*	MOVE.L	(A0),D0 */	0x2010,
/*	TDIVU.L	D2,D1:D0 */	0x4C42, 1,
/*	MOVE.L	D0,(A0)+ */	0x20C0,
/*	MOVE.L	(A0),D0	*/	0x2010,
/*	DIVU.L	D2,D1:D0 */	0x4C42, 0x401,
/*	MOVE.L	D0,(A0)	*/	0x2080
    };
   #pragma parameter __A0 puint64divu32(__A0,__D2)
    extern uint64 *puint64divu32(uint64*,uint32) = {
/*	MOVE.L	(A0),D0 */	0x2010,
/*	TDIVU.L	D2,D1:D0 */	0x4C42, 1,
/*	MOVE.L	D0,(A0)+ */	0x20C0,
/*	MOVE.L	4(A0),D0 */	0x2028, 4,
/*	DIVU.L	D2,D1:D0 */	0x4C42, 0x401,
/*	MOVE.L	D0,4(A0) */	0x2140, 4
    };

   #pragma parameter __D1 _divi32(__A0,__D2)
    extern int32 _divi32(const int64*,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	MOVE.L	(A0),D1	*/	0x2210,
/*	DIVS.L	D2,D0:D1 */	0x4C42, 0x1C00,
/*	BVC.S	*+32 ;e	*/	0x681E,
/*	MOVE.L	D0,-(A7) */	0x2F00,
/*	BPL.S	*+6	;@1 */	0x6A04,
/*	NEG.L	D1	*/	0x4481,
/*	NEGX.L	D0	*/	0x4080,
/*@1	EOR.L	D2,(A7)	*/	0xB597,
/*	MOVE.L	D2,-(A7) */	0x2F02,
/*	BPL.S	*+4	;@2 */	0x6A02,
/*	NEG.L	(A7)	*/	0x4497,
/*@2	TDIVU.L	(A7),D2:D0 */	0x4C57, 2,
/*	DIVU.L	(A7)+,D2:D1 */	0x4C5F, 0x1402,
/*	TST.L	(A7)+	*/	0x4A9F,
/*	BPL.S	*+4 ;e	*/	0x6A02,
/*	NEG.L	D1	*/	0x4481
    };
   #pragma parameter __D0 _divu32(__A0,__D2)
    extern uint32 _divu32(const uint64*,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	MOVE.L	(A0),D1	*/	0x2210,
/*	DIVU.L	D2,D0:D1 */	0x4C42, 0x1400,
/*	BVS.S	*+6 ;@1	*/	0x6904,
/*	MOVE.L	D1,D0	*/	0x2001,
/*	BRA.S	*+12 ;e	*/	0x680A,
/*@1	TDIVU.L	D2,D1:D0 */	0x4C42, 1,
/*	MOVE.L	(A0),D0	*/	0x2010,
/*	DIVU.L	D2,D1:D0 */	0x4C42, 0x401
    };
   #pragma parameter __D2 _divi32r(__A0,__D2)
    extern int32 _divi32r(const int64*,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	MOVE.L	(A0),D1	*/	0x2210,
/*	DIVS.L	D2,D0:D1 */	0x4C42, 0x1C00,
/*	BVS.S	*+6 ;@0	*/	0x6904,
/*	MOVE.L	D0,D2	*/	0x2400,
/*	BRA.S	*+32 ;e	*/	0x601E,
/*@0	MOVE.L	D0,-(A7) */	0x2F00,
/*	BPL.S	*+6	;@1 */	0x6A04,
/*	NEG.L	D1	*/	0x4481,
/*	NEGX.L	D0	*/	0x4080,
/*@1	EOR.L	D2,(A7)	*/	0xB597,
/*	MOVE.L	D2,-(A7) */	0x2F02,
/*	BPL.S	*+4	;@2 */	0x6A02,
/*	NEG.L	(A7)	*/	0x4497,
/*@2	TDIVU.L	(A7),D2:D0 */	0x4C57, 2,
/*	DIVU.L	(A7)+,D2:D1 */	0x4C5F, 0x1402,
/*	TST.L	(A7)+	*/	0x4A9F,
/*	BPL.S	*+4 ;e	*/	0x6A02,
/*	NEG.L	D2	*/	0x4482
    };
   #pragma parameter __D1 _divu32r(__A0,__D2)
    extern uint32 _divu32r(const uint64*,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	MOVE.L	(A0),D1	*/	0x2210,
/*	DIVU.L	D2,D0:D1 */	0x4C42, 0x1400,
/*	BVS.S	*+6 ;@1	*/	0x6904,
/*	MOVE.L	D0,D1	*/	0x2200,
/*	BRA.S	*+12 ;e	*/	0x680A,
/*@1	TDIVU.L	D2,D1:D0 */	0x4C42, 1,
/*	MOVE.L	(A0),D0	*/	0x2010,
/*	DIVU.L	D2,D1:D0 */	0x4C42, 0x401
    };

   /* returns low 32b */
   #pragma parameter __D2 _muls64s32(__A0,__D1,__D2)
    extern int32 _muls64s32(int64*,int32,int32) = {
/*	MULS.L	D1,D1:D2 */	0x4C01, 0x2C01,
/*	MOVE.L	D1,(A0)+ */	0x20C1,
/*	MOVE.L	D2,(A0)	*/	0x2082
    };
   #pragma parameter __D2 _mulu64s32(__A0,__D1,__D2)
    extern uint32 _mulu64s32(uint64*,int32,int32) =
	{0x4C01, 0x2C01,0x20C1,0x2082};
   #pragma parameter __D2 _muls64u32(__A0,__D1,__D2)
    extern uint32 _muls64u32(int64*,uint32,uint32) = {
/*	MULU.L	D1,D1:D2 */	0x4C01, 0x2401,
/*	MOVE.L	D1,(A0)+ */	0x20C1,
/*	MOVE.L	D2,(A0)	*/	0x2082
    };
   #pragma parameter __D2 _mulu64u32(__A0,__D1,__D2)
    extern uint32 _mulu64u32(uint64*,uint32,uint32) =
	{0x4C01, 0x2401,0x20C1,0x2082};
   #pragma parameter __D2 _muls64su32(__A0,__D1,__D2)
    extern int32 _muls64su32(int64*,int32,uint32) = {
/*	MOVE.L	D1,D0 */	0x2001,
/*	ADD.L	D0,D0 */	0xD080,
/*	SUBX.L	D0,D0 */	0x9180,
/*	AND.L	D2,D0 */	0xC082,
/*	MULU.L	D1,D1:D2 */	0x4C01, 0x2401,
/*	SUB.L	D0,D1 */	0x9280,
/*	MOVE.L	D1,(A0)+ */	0x20C1,
/*	MOVE.L	D2,(A0)	*/	0x2082
    };

   /* returns low 32b */
   #pragma parameter __D2 _int64muls32(__A0,__D2)
    extern int32 _int64muls32(int64*,int32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	TST.L	D2	*/	0x4A82,
/*	BPL.S	*+8	;@1 */	0x6A06,
/*	NEG.L	D2	*/	0x4482,
/*	NEG.L	(A0)	*/	0x4490,
/*	NEGX.L	D0	*/	0x4080,
/*@1	MULU.L	D2,D0	*/	0x4C02, 0,
/*	MULU.L	(A0),D1:D2 */	0x4C10, 0x2401,
/*	ADD.L	D0,D1	*/	0xD280,
/*	MOVE.L	D2,(A0)	*/	0x2082,
/*	MOVE.L	D1,-(A0) */	0x2101
    };
   #pragma parameter __D2 _uint64muls32(__A0,__D2)
    extern uint32 _uint64muls32(uint64*,int32) =
	{0x2018,0x4A82,0x6A06,0x4482,0x4490,0x4080,0x4C02,0,0x4C10,0x2401,0xD280,0x2082,0x2101};
   #pragma parameter __D2 _int64mulu32(__A0,__D2)
    extern int32 _int64mulu32(int64*,uint32) = {
/*	MOVE.L	(A0)+,D0 */	0x2018,
/*	MULU.L	D2,D0	*/	0x4C02, 0,
/*	MULU.L	(A0),D1:D2 */	0x4C10, 0x2401,
/*	ADD.L	D0,D1	*/	0xD280,
/*	MOVE.L	D2,(A0)	*/	0x2082,
/*	MOVE.L	D1,-(A0) */	0x2101
    };
   #pragma parameter __D2 _uint64mulu32(__A0,__D2)
    extern uint32 _uint64mulu32(uint64*,uint32) =
	{0x2018,0x4C02,0,0x4C10, 0x2401,0xD280,0x2082,0x2101};

/* lo 32b result */
   #pragma parameter __D0 _int64neg(__A0)
    extern int32 _int64neg(int64*) = {
/*	MOVE.L	4(A0),D0 */	0x2028, 4,
/*	NEG.L	D0	*/	0x4480,
/*	NEGX.L	(A0)+	*/	0x4098,
/*	MOVE.L	D0,(A0)	*/	0x2080
    };
   #pragma parameter __D0 _uint64neg(__A0)
    extern uint32 _uint64neg(uint64*) = {0x2028,4,0x4480,0x4098,0x2080};
   #pragma parameter __D1 _int64half(__A0)
    extern int32 _int64half(int64*) = {
/*	MOVEQ	#0,D2	*/	0x7400,
/*	MOVE.L	(A0),D0	*/	0x2010,
/*	ADD.L	D0,(A0)+*/	0xD198,
/*	MOVE.L	(A0),D1	*/	0x2210,
/*	ADDX.L	D2,D1	*/	0xD382,
/*	ADDX.L	D2,D0	*/	0xD182,
/*	ASR.L	#1,D0	*/	0xE280,
/*	ROXR.L	#1,D1	*/	0xE291,
/*	MOVE.L	D1,(A0)	*/	0x2081,
/*	MOVE.L	D0,-(A0)*/	0x2100
   };
   #pragma parameter __D0 _uint64half(__A0)
    extern uint32 _uint64half(uint64*) = {
/*	MOVE.L	(A0)+,D0*/	0x2018,
/*	MOVE.L	(A0),D1	*/	0x2210,
/*	LSR.L	#1,D0	*/	0xE288,
/*	ROXR.L	#1,D1	*/	0xE291,
/*	MOVE.L	D1,(A0)	*/	0x2081,
/*	MOVE.L	D0,-(A0)*/	0x2100
   };

   #pragma parameter __D1 imuldiv(__D0,__D1,__D2)
    extern int32 imuldiv(int32,int32,int32) = {
/* 	MULS.L	D0,D0:D1 */	0x4C00, 0x1C00,
/*	MOVE.L	D0,-(A7) */	0x2F00,
/*	BPL.S	*+6	;@1*/	0x6A04,
/*	NEG.L	D1	*/	0x4481,
/*	NEGX.L	D0	*/	0x4080,
/*@1	EOR.L	D2,(A7)	*/	0xB597,
/*	MOVE.L	D2,-(A7)*/	0x2F02,
/*	BPL.S	*+4	;@2*/	0x6A02,
/*	NEG.L	(A7)	*/	0x4497,
/*@2	TDIVU.L	(A7),D2:D0*/	0x4C57, 2,
/*	DIVU.L	(A7)+,D2:D1*/	0x4C5F, 0x1402,
/*	TST.L	(A7)+	*/	0x4A9F,
/*	BPL.S	*+4 ;e	*/	0x6A02,
/*	NEG.L	D1	*/	0x4481
    };
   #pragma parameter __D1 umuldiv(__D0,__D1,__D2)
    extern uint32 umuldiv(uint32,uint32,uint32) = {
/*	MULU.L	D0,D0:D1*/	0x4C00, 0x1400,
/*	MOVE.L	D2,-(A7)*/	0x2F02,
/*	TDIVU.L	D2,D2:D0*/	0x4C42, 2,
/*	DIVU.L	(A7)+,D2:D1*/	0x4C5F, 0x1402
    };
   #undef reverse32
   #undef reverse16
   #pragma parameter __D0 reverse16(__D0)
    extern uint16 reverse16(uint16 x) = {
/*	ROL	#8,D0	*/	0xE158
    };
#   pragma parameter __D0 reverse32(__D0)
    extern uint32 reverse32(uint32 x) = {
/*	ROL	#8,D0	*/	0xE158,
/*	SWAP	D0	*/	0x4840,
/*	ROL	#8,D0	*/	0xE158
    };
  #endif /* env68k */
 #else /*little endian, no long long*/
  typedef struct int64{uint32 lo; int32 hi;} int64;
  typedef struct uint64{uint32 lo, hi;} uint64;
 #endif

 #define int64half(n)		(void)_int64half(&(n))
 #define uint64half(n)		(void)_uint64half(&(n))

 #define int64addhl(x,h,l)	_int64addhl(&(x),h,l)
 #define uint64addhl(x,h,l)	_uint64addhl(&(x),h,l)
 #define int64subhl(x,h,l)	_int64subhl(&(x),h,l)
 #define uint64subhl(x,h,l)	_uint64subhl(&(x),h,l)
 #define int64addhls(x,h,l)	_int64addhls(&(x),h,l)
 #define uint64addhls(x,h,l)	_uint64addhls(&(x),h,l)
 #define int64divu32(x,y)	_int64divu32(&(x),y)
 #define uint64divu32(x,y)	_uint64divu32(&(x),y)
 #define divi32(x,i)		_divi32(&(x),i)
 #define divu32(x,i)		_divu32(&(x),i)
 #define divi32r(x,i)		_divi32r(&(x),i)
 #define divu32r(x,i)		_divu32r(&(x),i)
 #define muls64s32(n,a,b)	_muls64s32(&(n),a,b)
 #define muls64u32(n,a,b)	_muls64u32(&(n),a,b)
 #define muls64su32(n,a,b)	_muls64su32(&(n),a,b)
 #define mulu64s32(n,a,b)	_mulu64s32(&(n),a,b)
 #define mulu64u32(n,a,b)	_mulu64u32(&(n),a,b)
 #define int64muls32(n,x)	_int64muls32(&(n),x)
 #define uint64muls32(n,x)	_uint64muls32(&(n),x)
 #define int64mulu32(n,x)	_int64mulu32(&(n),x)
 #define uint64mulu32(n,x)	_uint64mulu32(&(n),x)
 #define int64neg(n)		_int64neg(&(n))
 #define uint64neg(n)		_uint64neg(&(n))

 #define int64hi(x)		(0+(x).hi)
 #define int64lo(x)		((uint32)(x).lo)

 #if BIG_ENDIAN
  #define _int64val(h,l)	{h,l}
  #define _int64xval(f)		{(f)/4294967296.0, \
	(f)-4294967296.0*((uint32)((f)/4294967296.0))}
 #else
  #define _int64val(h,l)	{l,h}
  #define _int64xval(f)		{(f)-4294967296.0*((uint32)((f)/4294967296.0)), \
	(f)/4294967296.0}
 #endif

 #define _int64xset(x,f)	(void)((x).lo=(f)-4294967296.0*((uint32)((f)/ \
	4294967296.0)),(x).hi=(f)/4294967296.0)
 #define int64xset(x,f)		do{long double __f=f; \
	(x).lo=__f-4294967296.0*((x).hi=__f/4294967296.0);}while(0)
 #define int64qset(x,q)		(void)((x).hi=(q)>>16,(x).lo=(uint32)(q)<<16)
 #define int64sethl(x,h,l)	(void)((x).hi=h,(x).lo=l)
 #define int64setl(x,y)		do{long int _islv=y;(x).hi=_islv>>32,(x).lo=_islv;}while(0)
 #define int64set(x,y)		(void)((x).hi=(y).hi,(x).lo=(y).lo)

 #define int64z(n)		(!((n).hi|(n).lo))
 #define int64n(n)		(((n).hi&0x80000000UL)!=0)
/*once if <0, 3x otherwise*/
 #define int64p(n)		(!((n).hi&0x80000000UL)&&(n).hi|(n).lo)

 #define int64toi(n)		(int32)((n).hi==(signed)(n).lo>>31? \
	(n).lo:0x7FFFFFFFL+((unsigned)(n).hi>>31))
 #define int64tol(n)		((n).hi<<32|(n).lo)
 #define int64tox(n)		((long double)(n).hi*4294967296.0+(n).lo)

 #define int64eq(x,y)		((x).hi==(y).hi&&(x).lo==(y).lo)
 #define int64eqhl(x,h,l)	((x).hi==(h)&&(x).lo==(l))
 #define int64gt(x,y)		((x).hi>(y).hi||((x).hi==(y).hi&&(x).lo>(y).lo))
 #define int64gthl(x,h,l)	((x).hi>(h)||((x).hi==(h)&&(x).lo>(l)))
 #define int64ge(x,y)		((x).hi>(y).hi||((x).hi==(y).hi&&(x).lo>=(y).lo))
 #define int64gehl(x,h,l)	((x).hi>(h)||((x).hi==(h)&&(x).lo>=(l)))
 #define uint64gtu32(x,i)	((x).hi||(x).lo>(uint32)(i))

 #define int64add(x,y)		int64addhl(x,(y).hi,(y).lo)
 #define uint64add(x,y)		uint64addhl(x,(y).hi,(y).lo)
 #define int64addu32(x,i)	int64addhl(x,0,i)
 #define uint64addu32(x,i)	uint64addhl(x,0,i)

 #define int64sub(x,y)		int64subhl(x,(y).hi,(y).lo)
 #define uint64sub(x,y)		uint64subhl(x,(y).hi,(y).lo)
 #define int64subu32(x,i)	int64subhl(x,0,i)
 #define uint64subu32(x,i)	uint64subhl(x,0,i)

 #define int64divs32(x,i)	((i)&0x80000000UL?_int64neg(pint64divu32(&(x),-(i))):int64divu32(x,i))
 #define uint64divs32(x,i)	((i)&0x80000000UL?_uint64neg(puint64divu32(&(x),-(i))):uint64divu32(x,i))

 /* these only handle a literal count within [0,32] */
 #if BIG_ENDIAN
  #define _int64shr32(x,c)	((c)==16? \
	*(int32*)(2+(int8*)&(x).hi):((x).hi<<(32-(c))|((x).lo)>>c))
  #define _uint64shr32(x,c)	((c)==16? \
	*(uint32*)(2+(int8*)&(x).hi):((x).hi<<(32-(c))|((x).lo)>>c))
 #else
  #define _int64shr32(x,c)	(int32)(((x).hi<<(32-(c)))|((x).lo)>>c))
  #define _uint64shr32(x,c)	(uint32)(((x).hi<<(32-(c)))|((x).lo)>>c))
 #endif

 #define int64shl(n,i)		do{int __i=(i)&0x7F; uint32 __t=(n).lo; \
	if(__i<=32) (n).lo=__t<<__i,(n).hi=(n).hi<<__i|__t>>(32-__i); \
	else if((__i-=32)>32) (n).hi=0,(n).lo=0; else (n).hi=__t>>=__i,(n).lo=0; \
 }while(0)
 #define int64shr(n,i)		do{int __x=(i)&0x7F; uint32 __t=(n).hi; \
	if(__x<=31) (n).lo=__t<<(32-__x)|(n).lo>>__x,(n).hi=(signed)__t>>__x; \
	else if((__x-=32)<=31) (n).lo=(n).hi>>__x,(n).hi>>=31; else (n).hi=(n).lo=(n).hi>>31; \
 }while(0)
 #define uint64shr(n,i)		do{int __x=(i)&0x7F; uint32 __t=(n).hi; \
	if(__x<=31) (n).lo=__t<<(32-__x)|(n).lo>>__x,(n).hi=__t>>__x; \
	else if((__x-=32)<=31) (n).lo=(n).hi>>__x,(n).hi=0; else (n).hi=(n).lo=0; \
 }while(0)

 #ifndef int64half
  #define int64half(n)		do{int64 *__n=&(n); \
	if((__n->hi&0x80000000UL)&&!++__n->lo) ++__n->hi; \
	__n->lo=(__n->lo>>1)+(__n->hi<<31),__n->hi>>=1; \
  }while(0)
  #define uint64half(n)		do{uint64 *__n=&(n); \
   __n->lo=(__n->lo>>1)+(__n->hi<<31),__n->hi>>=1; \
  }while(0)
 #endif

 #define int64or(x,y)		((x).hi|=(y).hi,(x).lo|=(y).lo)
 #define int64eor(x,y)		((x).hi^=(y).hi,(x).lo^=(y).lo)
 #define int64and(x,y)		((x).hi&=(y).hi,(x).lo&=(y).lo)
 #define int64not(x)		((x).hi=~(x).hi,(x).lo=~(x).lo)

 #define int64orhl(x,h,l)	((x).hi|=h,(x).lo|=l)
 #define int64eorhl(x,h,l)	((x).hi^=h,(x).lo^=l)
 #define int64andhl(x,h,l)	((x).hi&=h,(x).lo&=l)

 #define int64adds32(x,l)	int64addhls(x,(l)>>31,l)
 #define uint64adds32(x,l)	uint64addhls(x,(l)>>31,l)
 #define int64subs32(x,l)	int64subhls(x,(l)>>31,l)
 #define uint64subs32(x,l)	uint64subhls(x,(l)>>31,l)
#endif /*!LONG_LONG*/

/* saturates; params used twice */
#define int64tou(n)		(-(int64hi(n)!=0)|int64lo(n))

/* int128 is available natively on 64b CPUs */

#ifdef __GLIBCXX_BITSIZE_INT_N_0
 #if __GLIBCXX_BITSIZE_INT_N_0==128
  #define int128 __int128
  #define uint128 __uint128
 #endif
#elif defined(__GNUC__)
 #if __GNUC__*10+__GNUC_MINOR__>40 && envx64
  #define int128 __int128
  typedef unsigned __int128 uint128;
 #endif
#endif
#ifdef int128
 #define _int128val(h,l) (((uint128)(h)<<64)|(uint128)(l))
#else
typedef struct int128
{
#if BIG_ENDIAN
 #define _int128val(h,l) {h,l}
	int64		hi;
	uint64		lo;
#else
 #define _int128val(h,l) {l,h}
	uint64		lo;
	int64		hi;
#endif
} int128;

typedef struct uint128
{
#if BIG_ENDIAN
	uint64		hi, lo;
#else
	uint64		lo, hi;
#endif
} uint128;
#endif

/* helpful to def this 16-byte union regardless of headers */
typedef union u_xmm128
{
	float		f32[4];
	double		f64[2];
	int8		i8[16];
	int16		i16[8];
	int32		i32[4];
	int64		i64[2];
	uint8		u8[16];
	uint16		u16[8];
	uint32		u32[4];
	uint64		u64[2];
	int128		i128;
	uint128		u128;
} u_xmm128;

#define __ENVIRO64_H
#endif
