873 lines
38 KiB
C
873 lines
38 KiB
C
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
#ifndef __VARBITSH__
|
|
#define __VARBITSH__
|
|
|
|
#ifndef __RADRR_CORE2H__
|
|
#include "rrCore.h"
|
|
#endif
|
|
|
|
#ifdef WRAP_PUBLICS
|
|
#define rfmerge3(name,add) name##add
|
|
#define rfmerge2(name,add) rfmerge3(name,add)
|
|
#define rfmerge(name) rfmerge2(name,WRAP_PUBLICS)
|
|
#define VarBitsCopy rfmerge(VarBitsCopy)
|
|
#define VarBitsLens rfmerge(VarBitsLens)
|
|
#endif
|
|
|
|
|
|
// variable bit macros
|
|
//#if defined(__RADX86__)
|
|
RADDECLAREDATA const RAD_ALIGN(U32,VarBitsLens[33],32);
|
|
//#endif
|
|
|
|
/*************
|
|
|
|
VARBITS can either be in a struct , or in local variables set up by VARBITSLOCAL(name)
|
|
|
|
the "Local" macros make the names of the local variables using ##
|
|
|
|
***************/
|
|
|
|
//#define USE64BITVB
|
|
#ifdef USE64BITVB
|
|
|
|
#define BITSTYPE U64
|
|
#define BITSTYPELEN 64
|
|
#define BITSTYPEBYTES 8
|
|
#define BITSTOPMASK (1UL64<<(BITSTYPELEN-1))
|
|
|
|
//NOTE this is read-only on USE64BITVB!
|
|
#define VarBitsOpen(vb,pointer) { (vb).init=pointer; if (((U32)pointer)&4) { (vb).bits = *((U32* RADRESTRICT )pointer); (vb).cur = ((char*)pointer)+4; (vb).bitlen = 32; } else { (vb).cur=pointer; (vb).bits=(vb).bitlen=0; } }
|
|
#define VarBitsLocalOpen(vb,pointer) { if (((U32)pointer)&4) { vb##bits = *((U32 * RADRESTRICT)pointer); vb##cur = ((char*)pointer)+4; vb##bitlen = 32; } else { vb##cur=pointer; vb##bits=vb##bitlen=0; } }
|
|
|
|
#else
|
|
|
|
#define BITSTYPE U32
|
|
#define BITSTYPELEN 32
|
|
#define BITSTYPEBYTES 4
|
|
#define BITSTOPMASK (1UL<<(BITSTYPELEN-1))
|
|
|
|
#define VarBitsOpen(vb,pointer) { (vb).cur=(vb).init=pointer; (vb).bits=(vb).bitlen=0; }
|
|
#define VarBitsLocalOpen(vb,pointer) { vb##cur=pointer; vb##bits=vb##bitlen=0; }
|
|
|
|
#endif
|
|
|
|
#define VARBITSTEMP BITSTYPE
|
|
|
|
typedef struct _VARBITS
|
|
{
|
|
BITSTYPE bits;
|
|
void* RADRESTRICT cur;
|
|
U32 bitlen;
|
|
void* RADRESTRICT init;
|
|
} VARBITS;
|
|
|
|
// FG: same as VARBITS (and can be used with the same macros), but has space for an "end" pointer
|
|
// not used by the macros, but useful if you need to propagate the "end" pointer downstream in
|
|
// a decoder.
|
|
typedef struct _VARBITSEND
|
|
{
|
|
BITSTYPE bits;
|
|
void* RADRESTRICT cur;
|
|
U32 bitlen;
|
|
void* RADRESTRICT init;
|
|
void* RADRESTRICT end;
|
|
} VARBITSEND;
|
|
|
|
// CB : WARNING : these functions are generally NOT safe to call with # bits = 0
|
|
|
|
#define VarBitsPut(vb,val,size) { U32 __s=size; U32 __v=(val)&VarBitsLens[__s]; (vb).bits|=__v<<((vb).bitlen); (vb).bitlen+=__s; if ((vb).bitlen>=32) { *((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); (vb).bitlen-=32; (vb).bits=0; if ((vb).bitlen) { (vb).bits=__v>>(__s-(vb).bitlen); } } }
|
|
#define VarBitsPut1(vb,boolean) { if (boolean) (vb).bits|=(1<<(vb).bitlen); if ((++(vb).bitlen)==32) { *((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); (vb).bits=(vb).bitlen=0; } }
|
|
#define VarBitsPuta1(vb) { (vb).bits|=(1<<(vb).bitlen); if ((++(vb).bitlen)==32) { *((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); (vb).bits=(vb).bitlen=0; } }
|
|
#define VarBitsPuta0(vb) { if ((++(vb).bitlen)==32) { *((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); (vb).bits=(vb).bitlen=0; } }
|
|
#define VarBitsPutAlign(vb) { U32 __s2=(32-(vb).bitlen)&31; if (__s2) { VarBitsPut((vb),0,__s2); } }
|
|
#define VarBitsFlushtoMemOnly(vb) { if (((vb).bitlen)) { *((U32*)(vb).cur)=(vb).bits; } }
|
|
#define VarBitsConvertPutToGet(gvb,pvb) { if (((pvb).bitlen)) { (gvb).bits=(*((U32*)(pvb).cur))>>(pvb).bitlen; (gvb).bitlen=BITSTYPELEN-(pvb).bitlen; (gvb).cur=((char*)((pvb).cur)+4); } else { (gvb).bits=0; (gvb).bitlen=0; (gvb).cur=(pvb).cur; } (gvb).init=(pvb).init; }
|
|
#define VarBitsFlush(vb) VarBitsPutAlign(vb)
|
|
#define VarBitsSize(vb) ((U32)( (((char*)(vb).cur)-((char*)(vb).init))*8 +(vb).bitlen )) // in bits !!
|
|
|
|
// VarBitsCopy size is in bits of course; don't use this for big copies
|
|
RADDEFFUNC void VarBitsCopy(VARBITS* dest,VARBITS* src,U32 size);
|
|
|
|
// getbitlevel :
|
|
// getbitlevel(n) is the number of bits that n uses for its on bits
|
|
// eg. n < (1<<getbitlevel(n)) , n >= (1<<(getbitlevel(n)-1))
|
|
// getbitlevel(n)-1 is the bit position of the leftmost 1 bit in 'n'
|
|
// NOTE : getbitlevel(0) = 0
|
|
// getbitlevel(n) = ilog2ceil except on powers of two
|
|
//---------------------------------------
|
|
|
|
|
|
// WARNING : this getbitlevel only works on *constant* U16 values ! (up to 65535)
|
|
// it will fail to compile with strange errors if you use a variable
|
|
#define getbitlevelconst(level) \
|
|
( \
|
|
(((level)< 1)?0: \
|
|
(((level)< 2)?1: \
|
|
(((level)< 4)?2: \
|
|
(((level)< 8)?3: \
|
|
(((level)< 16)?4: \
|
|
(((level)< 32)?5: \
|
|
(((level)< 64)?6: \
|
|
(((level)< 128)?7: \
|
|
(((level)< 256)?8: \
|
|
(((level)< 512)?9: \
|
|
(((level)< 1024)?10: \
|
|
(((level)< 2048)?11: \
|
|
(((level)< 4096)?12: \
|
|
(((level)< 8192)?13: \
|
|
(((level)<16384)?14: \
|
|
(((level)<32768)?15: \
|
|
(((level)<65536)?16:sizeof(char[65535-level]) \
|
|
))))))))))))))))) \
|
|
)
|
|
|
|
|
|
#if defined(__RADPPC__)
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
#if defined(__SNC__)
|
|
#define count_leading_zeros(count, x) count = __cntlzw(x)
|
|
#elif defined(__ghs__)
|
|
RADDEFFUNC unsigned int __CLZ32(unsigned int a);
|
|
#define count_leading_zeros(count, x) count = __CLZ32(x)
|
|
#else
|
|
#define count_leading_zeros(count, x) \
|
|
__asm__ ("{cntlz|cntlzw} %0,%1" \
|
|
: "=r" (count) \
|
|
: "r" (x))
|
|
#endif
|
|
|
|
|
|
static RADINLINE U32 getbitlevelvar( register U32 n )
|
|
{
|
|
count_leading_zeros( n, n );
|
|
return( 32 - n );
|
|
}
|
|
|
|
#else
|
|
|
|
#ifdef _MSC_VER
|
|
#include <ppcintrinsics.h>
|
|
#define __cntlzw _CountLeadingZeros
|
|
#endif
|
|
|
|
#define getbitlevelvar(n) (U32) (32 - __cntlzw(n))
|
|
|
|
#endif
|
|
|
|
#elif defined(__RADSPU__)
|
|
|
|
static RADINLINE U32 getbitlevelvar( register U32 n )
|
|
{
|
|
vector unsigned int v;
|
|
v[0]=n;
|
|
v = __builtin_spu_cntlz( v );
|
|
return( 32 - v[0] );
|
|
}
|
|
|
|
#elif defined(__RADARM__)
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#ifdef _M_ARM64
|
|
|
|
#define getbitlevelvar(n) (U32) (32 - _CountLeadingZeros(n))
|
|
|
|
#else
|
|
|
|
#define getbitlevelvar(n) (U32) (32 - _arm_clz(n))
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
#define getbitlevelvar(n) (U32) (32 - __builtin_clz(n))
|
|
|
|
#endif
|
|
|
|
#elif (_MSC_FULL_VER >= 13012035 )
|
|
|
|
RADDEFSTART
|
|
unsigned char _BitScanReverse(unsigned long* Index, unsigned long Mask);
|
|
#pragma intrinsic(_BitScanReverse)
|
|
RADDEFEND
|
|
|
|
static RADINLINE U32 getbitlevelvar( register U32 val )
|
|
{
|
|
if ( val )
|
|
{
|
|
U32 b = 0;
|
|
_BitScanReverse( (unsigned long*)&b, val );
|
|
return b + 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
|
|
static RADINLINE U32 getbitlevelvar( register U32 val )
|
|
{
|
|
static char vs[16]={0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4};
|
|
int bits=0;
|
|
|
|
if ( val & 0xffff0000 )
|
|
{
|
|
bits = 16;
|
|
val >>= 16;
|
|
}
|
|
|
|
if ( val & 0xff00 )
|
|
{
|
|
bits += 8;
|
|
val >>= 8;
|
|
}
|
|
|
|
if ( val & 0xf0 )
|
|
{
|
|
bits += 4;
|
|
val >>= 4;
|
|
}
|
|
|
|
bits += vs[ val ];
|
|
|
|
return bits;
|
|
}
|
|
|
|
#endif
|
|
|
|
#define VarBitsGetAlign(vb) { (vb).bitlen=0; }
|
|
#define VarBitsPos(vb) ((U32)( (((U8*)(vb).cur)-((U8*)(vb).init))*8-(vb).bitlen ))
|
|
|
|
// CB : GetBitsLen(bits) = (1<<bits)-1
|
|
// except that values for bits=32 , GetBitsLen fails for bits=0
|
|
// don't pass zero to this function
|
|
#define GetBitsLen(val) (((U32)0xffffffff)>>(U32)(32-(val)))
|
|
// for debugging: causes crash on zero: #define GetBitsLen(val) (((val)==0)?(((U8*)val)[0]=0):(0xffffffffL>>(U32)(32-(val))))
|
|
|
|
// get 1 bit
|
|
// best to use like : if ( VarBitsGet1(vb,i) )
|
|
//
|
|
// This *doesn't* set i to the result - that's just a temp - the expression is the result!!!
|
|
// i will be the unmasked bits, but that's not guaranteed!
|
|
#define VarBitsGet1(vb,i) \
|
|
( \
|
|
((vb).bitlen==0)? \
|
|
( \
|
|
i=*((BITSTYPE* RADRESTRICT)((vb).cur)), \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES, \
|
|
((vb).bits)=((BITSTYPE)i)>>1, \
|
|
((vb).bitlen)=(BITSTYPELEN-1) \
|
|
):( \
|
|
i=((vb).bits), \
|
|
((vb).bits)>>=1, \
|
|
--((vb).bitlen) \
|
|
),(i&1) \
|
|
)
|
|
|
|
//not USE64BITVB safe!
|
|
#define VarBitsGet1LE(vb,i) \
|
|
( \
|
|
((vb).bitlen==0)? \
|
|
( \
|
|
i=radloadu32ptr((vb).cur), \
|
|
((vb).cur)=((char*)((vb).cur))+4, \
|
|
((vb).bits)=((U32)i)>>1, \
|
|
((vb).bitlen)=31 \
|
|
):( \
|
|
i=((vb).bits), \
|
|
((vb).bits)>>=1, \
|
|
--((vb).bitlen) \
|
|
),(i&1) \
|
|
)
|
|
|
|
|
|
#define VarBitsGet(v,typ,vb,len) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)((vb).cur)); \
|
|
v=(typ)((((vb).bits)|(nb<<((vb).bitlen)))&GetBitsLen(len)); \
|
|
((vb).bits)=nb>>((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
v=(typ)(((vb).bits)&GetBitsLen(len)); \
|
|
((vb).bits)>>=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsGetWithCheck(v,typ,vb,len,endp,dowhat) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb; \
|
|
if ( ( (U8*)((vb).cur) ) >= ( (U8*) (endp) ) ) dowhat \
|
|
nb=*((BITSTYPE* RADRESTRICT)((vb).cur)); \
|
|
v=(typ)((((vb).bits)|(nb<<((vb).bitlen)))&GetBitsLen(len)); \
|
|
((vb).bits)=nb>>((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
v=(typ)(((vb).bits)&GetBitsLen(len)); \
|
|
((vb).bits)>>=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsGetWithCheckBE(v,typ,vb,len,endp,dowhat) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb; \
|
|
if ( ( (U8*)((vb).cur) ) >= ( (U8*) (endp) ) ) dowhat \
|
|
nb=radloadu32ptrBE((vb).cur); \
|
|
v=(typ)((((vb).bits)|(nb<<((vb).bitlen)))&GetBitsLen(len)); \
|
|
((vb).bits)=nb>>((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
v=(typ)(((vb).bits)&GetBitsLen(len)); \
|
|
((vb).bits)>>=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsGetWithCheckLE(v,typ,vb,len,endp,dowhat) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb; \
|
|
if ( ( (U8*)((vb).cur) ) >= ( (U8*) (endp) ) ) dowhat \
|
|
nb=radloadu32ptr((vb).cur); \
|
|
v=(typ)((((vb).bits)|(nb<<((vb).bitlen)))&GetBitsLen(len)); \
|
|
((vb).bits)=nb>>((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
v=(typ)(((vb).bits)&GetBitsLen(len)); \
|
|
((vb).bits)>>=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
// Peek : put len bits in v but don't shift the read pointer
|
|
#define VarBitsPeek(v,typ,vb,len) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)((vb).cur)); \
|
|
v=(typ)((((vb).bits)|(nb<<((vb).bitlen)))&GetBitsLen(len)); \
|
|
} else { \
|
|
v=(typ)(((vb).bits)&GetBitsLen(len)); \
|
|
} \
|
|
}
|
|
|
|
//not USE64BITVB safe!
|
|
#define VarBitsGetLE(v,typ,vb,len) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register U32 nb=radloadu32ptr((vb).cur); \
|
|
v=(typ)((((vb).bits)|(nb<<((vb).bitlen)))&GetBitsLen(len)); \
|
|
((vb).bits)=nb>>((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+32-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+4; \
|
|
} else { \
|
|
v=(typ)(((vb).bits)&GetBitsLen(len)); \
|
|
((vb).bits)>>=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
// VarBitsUse : just skip 'len' bits ; useful after a Peek
|
|
#define VarBitsUse(vb,len) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)((vb).cur)); \
|
|
((vb).bits)=nb>>((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
((vb).bits)>>=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------
|
|
// VarBitsLocal stuff for even more speed
|
|
|
|
// VARBITSLOCAL defines the local vars to hold the varbits goodies
|
|
// VarBitsCopyToLocal() at the start
|
|
// VarBitsCopyFromLocal() at the end
|
|
|
|
#define VARBITSLOCAL(name) void * name##cur; BITSTYPE name##bits; U32 name##bitlen
|
|
|
|
|
|
#ifdef __RAD64REGS__
|
|
|
|
#ifdef INC_BINK2
|
|
|
|
#if defined(__RADX86__)
|
|
#include <xmmintrin.h>
|
|
#define VBPREFETCH( ptr ) _mm_prefetch(((char*)(ptr))+1024, _MM_HINT_T0 )
|
|
#elif defined(__RADARM64__)
|
|
// should we do this??
|
|
#define VBPREFETCH( ptr ) __builtin_prefetch(((char*)(ptr))+1024)
|
|
#else
|
|
#define VBPREFETCH( ptr )
|
|
#endif
|
|
#else
|
|
#define VBPREFETCH( ptr )
|
|
#endif
|
|
|
|
#define VarBitsLocalGet(v,typ,vb,len) \
|
|
{ \
|
|
register U64 _bits = (vb##bits); \
|
|
if ((vb##bitlen)<len) { \
|
|
_bits |= (((U64)(*((U32* RADRESTRICT)(vb##cur))))<<(vb##bitlen)); \
|
|
(vb##bitlen)=(vb##bitlen)+32; \
|
|
VBPREFETCH((vb##cur)); \
|
|
(vb##cur)=((char*)(vb##cur))+4; \
|
|
} \
|
|
(vb##bits)=(U32)(_bits>>(len)); \
|
|
(vb##bitlen)-=(len); \
|
|
v=(typ)(((U32)_bits)&GetBitsLen(len)); \
|
|
}
|
|
|
|
// mask == GetBitsLen(len) - for when you know this in advance.
|
|
// load == what to do to load
|
|
#define VarBitsLocalGetWithCheckBase(v,typ,vb,len,mask,endp,dowhat,load) \
|
|
{ \
|
|
register U64 _bits = (vb##bits); \
|
|
if ((vb##bitlen)<len) { \
|
|
if ( ( (U8*)(vb##cur) ) >= ( (U8*) (endp) ) ) dowhat \
|
|
_bits|=((U64) (load(vb##cur))) << (vb##bitlen); \
|
|
(vb##bitlen)+=32; \
|
|
(vb##cur)=((char*)(vb##cur))+4; \
|
|
} \
|
|
v=(typ)(_bits & (mask)); \
|
|
(vb##bits)=(U32)(_bits>>(len)); \
|
|
(vb##bitlen)-=(len); \
|
|
}
|
|
|
|
#else
|
|
|
|
#define VarBitsLocalGet(v,typ,vb,len) \
|
|
{ \
|
|
if ((vb##bitlen)<len) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)(vb##cur)); \
|
|
v=(typ)(((vb##bits)|(nb<<(vb##bitlen)))&GetBitsLen(len)); \
|
|
(vb##bits)=nb>>((len)-(vb##bitlen)); \
|
|
(vb##bitlen)=(vb##bitlen)+BITSTYPELEN-(len); \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
v=(typ)((vb##bits)&GetBitsLen(len)); \
|
|
(vb##bits)>>=(len); \
|
|
(vb##bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
// mask == GetBitsLen(len) - for when you know this in advance.
|
|
// load == what to do to load
|
|
#define VarBitsLocalGetWithCheckBase(v,typ,vb,len,mask,endp,dowhat,load) \
|
|
{ \
|
|
if ((vb##bitlen)<len) { \
|
|
register BITSTYPE nb; \
|
|
if ( ( (U8*)(vb##cur) ) >= ( (U8*) (endp) ) ) dowhat \
|
|
nb=load(vb##cur); \
|
|
v=(typ)(((vb##bits)|(nb<<(vb##bitlen)))&(mask)); \
|
|
(vb##bits)=nb>>((len)-(vb##bitlen)); \
|
|
(vb##bitlen)=(vb##bitlen)+BITSTYPELEN-(len); \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
v=(typ)((vb##bits)&(mask)); \
|
|
(vb##bits)>>=(len); \
|
|
(vb##bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
#endif
|
|
|
|
#define radloadbitsnative(ptr) (*((BITSTYPE* RADRESTRICT)(ptr)))
|
|
|
|
#define VarBitsLocalGetWithCheck(v,typ,vb,len,endp,dowhat) VarBitsLocalGetWithCheckBase(v,typ,vb,len,GetBitsLen(len),endp,dowhat,radloadbitsnative)
|
|
#define VarBitsLocalGetWithCheckBE(v,typ,vb,len,endp,dowhat) VarBitsLocalGetWithCheckBase(v,typ,vb,len,GetBitsLen(len),endp,dowhat,radloadu32ptrBE)
|
|
#define VarBitsLocalGetWithCheckLE(v,typ,vb,len,endp,dowhat) VarBitsLocalGetWithCheckBase(v,typ,vb,len,GetBitsLen(len),endp,dowhat,radloadu32ptr)
|
|
|
|
// same as LocalGetWithCheck, but passing in the bit mask yourself
|
|
#define VarBitsLocalGetWithCheckM(v,typ,vb,len,mask,endp,dowhat) VarBitsLocalGetWithCheckBase(v,typ,vb,len,mask,endp,dowhat,radloadbitsnative)
|
|
#define VarBitsLocalGetWithCheckMBE(v,typ,vb,len,mask,endp,dowhat) VarBitsLocalGetWithCheckBase(v,typ,vb,len,mask,endp,dowhat,radloadu32ptrBE)
|
|
#define VarBitsLocalGetWithCheckMLE(v,typ,vb,len,mask,endp,dowhat) VarBitsLocalGetWithCheckBase(v,typ,vb,len,mask,endp,dowhat,radloadu32ptr)
|
|
|
|
// just the refill for a VarBitsLocalGet1WithCheck, and with an extra conditional
|
|
// this turns out to be really useful to have in Bink Audio.
|
|
#define VarBitsLocalFill1WithCheckBase(vb,endp,cond,dowhat,load)\
|
|
{ \
|
|
if ((vb##bitlen)==0 && (cond)) { \
|
|
if ( ( (U8*)(vb##cur) ) >= ( (U8*) (endp) ) ) dowhat \
|
|
(vb##bits)=load(vb##cur); \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES; \
|
|
(vb##bitlen)=(BITSTYPELEN); \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsLocalGet1WithCheckBase(v,vb,endp,dowhat,load) \
|
|
{ \
|
|
VarBitsLocalFill1WithCheckBase(vb,endp,1,dowhat,load) \
|
|
--(vb##bitlen); \
|
|
v=(vb##bits); \
|
|
(vb##bits)>>=1; \
|
|
v&=1; \
|
|
}
|
|
|
|
#define VarBitsLocalFill1WithCheck(vb,endp,cond,dowhat) VarBitsLocalFill1WithCheckBase(vb,endp,cond,dowhat,radloadbitsnative)
|
|
#define VarBitsLocalFill1WithCheckBE(vb,endp,cond,dowhat) VarBitsLocalFill1WithCheckBase(vb,endp,cond,dowhat,radloadu32ptrBE)
|
|
#define VarBitsLocalFill1WithCheckLE(vb,endp,cond,dowhat) VarBitsLocalFill1WithCheckBase(vb,endp,cond,dowhat,radloadu32ptr)
|
|
|
|
#define VarBitsLocalGet1WithCheck(v,vb,endp,dowhat) VarBitsLocalGet1WithCheckBase(v,vb,endp,dowhat,radloadbitsnative)
|
|
#define VarBitsLocalGet1WithCheckBE(v,vb,endp,dowhat) VarBitsLocalGet1WithCheckBase(v,vb,endp,dowhat,radloadu32ptrBE)
|
|
#define VarBitsLocalGet1WithCheckLE(v,vb,endp,dowhat) VarBitsLocalGet1WithCheckBase(v,vb,endp,dowhat,radloadu32ptr)
|
|
|
|
|
|
// get the value, if the next bit is X (mask bits with mask)
|
|
// usually, you will use the two wrapper macros below
|
|
|
|
#define VarBitsLocalGetIfxSM(v,typ,vb,len,i,x,mask) \
|
|
(vb##bitlen==0)? \
|
|
( \
|
|
i=*((BITSTYPE* RADRESTRICT)(vb##cur)), \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES, \
|
|
( ( i & 1 ) == x ) ? \
|
|
( \
|
|
v = (typ)( ( i >> 1 ) mask ), \
|
|
(vb##bits)=((BITSTYPE)i)>>(len+1), \
|
|
(vb##bitlen)=(BITSTYPELEN - 1 - len), \
|
|
x \
|
|
):( \
|
|
(vb##bits)=(((BITSTYPE)i)>>1), \
|
|
(vb##bitlen)=(BITSTYPELEN-1), \
|
|
!x \
|
|
) \
|
|
):( \
|
|
--(vb##bitlen), \
|
|
( ( (vb##bits) & 1 ) == x ) ? \
|
|
( \
|
|
( ( vb##bitlen ) < len )? \
|
|
( \
|
|
i=*((BITSTYPE* RADRESTRICT)(vb##cur)), \
|
|
(vb##cur)=(((char*)(vb##cur))+BITSTYPEBYTES ), \
|
|
v=(typ)(((vb##bits>>1)|(i<<vb##bitlen)) mask ), \
|
|
(vb##bits)=(i>>((len)-vb##bitlen)), \
|
|
(vb##bitlen)=((vb##bitlen)+BITSTYPELEN-(len)), \
|
|
x \
|
|
):( \
|
|
v = (typ) ( ( (vb##bits) >> 1 ) mask ), \
|
|
(vb##bits)>>=(len+1), \
|
|
(vb##bitlen)-=len, \
|
|
x \
|
|
) \
|
|
):( \
|
|
(vb##bits)>>=1, \
|
|
!x \
|
|
) \
|
|
) \
|
|
|
|
|
|
// get the value, if the next bit is x (0 or 1)
|
|
|
|
#define VarBitsLocalGetIfx(v,typ,vb,len,i,x) \
|
|
VarBitsLocalGetIfxSM(v,typ,vb,len,i,x,&GetBitLen(len))
|
|
|
|
// get the value, if the next bit is x (0 or 1), but don't
|
|
// mask off the high bits of the value
|
|
|
|
#define VarBitsLocalGetIfxNM(v,typ,vb,len,i,x) \
|
|
VarBitsLocalGetIfxSM(v,typ,vb,len,i,x, )
|
|
|
|
|
|
#define VarBitsLocalPeek(v,typ,vb,len) \
|
|
{ \
|
|
if ((vb##bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)(vb##cur)); \
|
|
v=(typ)(((vb##bits)|(nb<<(vb##bitlen)))&GetBitsLen(len)); \
|
|
} else { \
|
|
v=(typ)((vb##bits)&GetBitsLen(len)); \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsLocalGet1BE(vb,i) \
|
|
( \
|
|
(vb##bitlen==0)? \
|
|
( \
|
|
i=radloadu32ptrBE(vb##cur), \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES, \
|
|
(vb##bits)=((BITSTYPE)i)>>1, \
|
|
(vb##bitlen)=(BITSTYPELEN-1) \
|
|
):( \
|
|
i=(vb##bits), \
|
|
(vb##bits)>>=1, \
|
|
--(vb##bitlen) \
|
|
),(i&1) \
|
|
)
|
|
|
|
#define VarBitsLocalGet1LE(vb,i) \
|
|
( \
|
|
(vb##bitlen==0)? \
|
|
( \
|
|
i=radloadu32ptr(vb##cur), \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES, \
|
|
(vb##bits)=((BITSTYPE)i)>>1, \
|
|
(vb##bitlen)=(BITSTYPELEN-1) \
|
|
):( \
|
|
i=(vb##bits), \
|
|
(vb##bits)>>=1, \
|
|
--(vb##bitlen) \
|
|
),(i&1) \
|
|
)
|
|
|
|
// if imask is -1, then read a bit and then &-it with input mask
|
|
// so now you have a mask that you can (v^m)-m to neg a value
|
|
#define VarBitsLocalMaskFromMaskAndUse1(omask,vb,imask) \
|
|
if (vb##bitlen==0) \
|
|
{ \
|
|
(vb##bits)=*((BITSTYPE* RADRESTRICT)(vb##cur)); \
|
|
(vb##bitlen)=BITSTYPELEN; \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES; \
|
|
} \
|
|
(vb##bitlen)+=imask; \
|
|
omask=(((S32)(vb##bits)<<31)>>31)&imask; \
|
|
(vb##bits)=((vb##bits>>1)&imask)|(vb##bits&~imask); \
|
|
|
|
#ifdef __RAD64REGS__
|
|
|
|
#define VarBitsLocalGet1(vb,i) \
|
|
( \
|
|
((vb##bitlen==0)? \
|
|
( \
|
|
(vb##bits)=*((BITSTYPE* RADRESTRICT)(vb##cur)), \
|
|
(vb##cur)=((char*)(vb##cur))+4, \
|
|
(vb##bitlen)=32 \
|
|
):0), \
|
|
( \
|
|
i=(vb##bits)&1, \
|
|
(vb##bits)>>=1, \
|
|
--(vb##bitlen) \
|
|
),(i) \
|
|
)
|
|
|
|
#else
|
|
|
|
#define VarBitsLocalGet1(vb,i) \
|
|
( \
|
|
(vb##bitlen==0)? \
|
|
( \
|
|
i=*((BITSTYPE* RADRESTRICT)(vb##cur)), \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES, \
|
|
(vb##bits)=((BITSTYPE)i)>>1, \
|
|
(vb##bitlen)=(BITSTYPELEN-1) \
|
|
):( \
|
|
i=(vb##bits), \
|
|
(vb##bits)>>=1, \
|
|
--(vb##bitlen) \
|
|
),(i&1) \
|
|
)
|
|
|
|
#endif
|
|
|
|
#define VarBitsLocalUse(vb,len) \
|
|
{ \
|
|
if ((vb##bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)(vb##cur)); \
|
|
(vb##bits)=nb>>((len)-(vb##bitlen)); \
|
|
(vb##bitlen)=(vb##bitlen)+BITSTYPELEN-(len); \
|
|
(vb##cur)=((char*)(vb##cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
(vb##bits)>>=(len); \
|
|
(vb##bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsLocalPos(vb,origvb) ((U32)( (((char*)vb##cur)-((char*)(origvb)->init))*8 +(32-vb##bitlen) )) // in bits !!
|
|
|
|
|
|
|
|
#define VarBitsCopyToLocal( local, vb ) local##cur = (vb).cur; local##bits = (vb).bits; local##bitlen = (vb).bitlen;
|
|
|
|
#define VarBitsCopyFromLocal( vb, local ) (vb).cur = local##cur; (vb).bits = local##bits; (vb).bitlen = local##bitlen;
|
|
|
|
|
|
|
|
|
|
// classifies a signed value into: 0 = zero, 1 = neg, 2 = pos
|
|
#define CLASSIFY_SIGN( val ) ( (((U32)((S32)(val))) >> 31 ) + ((((U32)(-(S32)(val))) >> 30 ) & 2 ) )
|
|
|
|
//=========================================================================================================
|
|
|
|
// VARBITSB = backward !
|
|
//
|
|
// CB : these *do* work with len == 0 , VarBits does not
|
|
|
|
typedef struct _VARBITSB
|
|
{
|
|
BITSTYPE bits;
|
|
void* RADRESTRICT cur;
|
|
U32 bitlen;
|
|
void* RADRESTRICT init;
|
|
int isPut; // CB maybe temp ; help me find bugs
|
|
} VARBITSB;
|
|
|
|
#define VarBitsBPutOpen(vb,ptr) { (vb).cur=(vb).init=(void *)(ptr); (vb).bits=(vb).bitlen=0; (vb).isPut = 1; }
|
|
#define VarBitsBGetOpen(vb,ptr) { (vb).cur=(vb).init=(void *)(ptr); (vb).bits=(vb).bitlen=0; (vb).isPut = 0; }
|
|
|
|
// __v=(val)&VarBitsLens[__s]
|
|
#define VarBitsBPut(vb,val,size) do { U32 __s=size; U32 __v=(val); \
|
|
radassert( __v < (1UL<<__s) ); \
|
|
if ((vb).bitlen+__s >=BITSTYPELEN) { U32 __r = __s + (vb).bitlen - BITSTYPELEN; \
|
|
(vb).bits <<= (BITSTYPELEN-(vb).bitlen); (vb).bits |= __v >> __r; \
|
|
*((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); \
|
|
(vb).bitlen = __r; (vb).bits = __v&VarBitsLens[__r]; } \
|
|
else { (vb).bits = ((vb).bits<<__s) | __v; (vb).bitlen+=__s; } } while(0)
|
|
|
|
#define VarBitsBPuta1(vb) { (vb).bits = (vb).bits + (vb).bits + 1; if ((++(vb).bitlen)==BITSTYPELEN) { *((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); (vb).bits=(vb).bitlen=0; } }
|
|
#define VarBitsBPuta0(vb) { (vb).bits <<= 1; if ((++(vb).bitlen)==BITSTYPELEN) { *((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); (vb).bits=(vb).bitlen=0; } }
|
|
#define VarBitsBPut1(vb,bit) { (vb).bits = (vb).bits + (vb).bits + ((bit)?1:0); if ((++(vb).bitlen)==BITSTYPELEN) { *((U32*)(vb).cur)=(vb).bits; (vb).cur=((char*)((vb).cur)+4); (vb).bits=(vb).bitlen=0; } }
|
|
|
|
#define VarBitsBPutAlign(vb) { U32 __s2=(32-(vb).bitlen)&31; if (__s2) { VarBitsBPut((vb),0,__s2); } }
|
|
#define VarBitsBPutFlush(vb) VarBitsBPutAlign(vb)
|
|
#define VarBitsBGetAlign(vb) { (vb).bitlen=0; }
|
|
#define VarBitsBPutSize(vb) ((U32)( (((char*)(vb).cur)-((char*)(vb).init))*8 +(vb).bitlen )) // in bits !!
|
|
#define VarBitsBGetSize(vb) ((U32)( (((char*)(vb).cur)-((char*)(vb).init))*8 -(vb).bitlen )) // in bits !!
|
|
|
|
// CB : stupid & with VarBitsLens just for len = 0 !
|
|
// this is because >>32 = NOP !! (on x86 anyway)
|
|
#define VarBitsBGet(v,typ,vb,len) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)((vb).cur)); \
|
|
v=(typ)((((vb).bits)|(nb>>((vb).bitlen)))>>(BITSTYPELEN-len));\
|
|
((vb).bits)=nb<<((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
v=(typ)(((vb).bits)>>(BITSTYPELEN-len)); \
|
|
((vb).bits)<<=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
v &= (len)?0xffffffff:0; \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsBPeek(v,typ,vb,len) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)((vb).cur)); \
|
|
v=(typ)((((vb).bits)|(nb>>((vb).bitlen)))>>(BITSTYPELEN-len));\
|
|
} else { \
|
|
v=(typ)(((vb).bits)>>(BITSTYPELEN-len)); \
|
|
} \
|
|
}
|
|
|
|
#define VarBitsBUse(vb,len) \
|
|
{ \
|
|
if (((vb).bitlen)<(len)) { \
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)((vb).cur)); \
|
|
((vb).bits)=nb<<((len)-((vb).bitlen)); \
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len); \
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES; \
|
|
} else { \
|
|
((vb).bits)<<=(len); \
|
|
((vb).bitlen)-=(len); \
|
|
} \
|
|
}
|
|
|
|
// get 1 bit
|
|
// best to use like : if ( VarBitsGet1(vb,i) )
|
|
// or bit = VarBitsGet1(vb,temp);
|
|
// WARNING : CB: i is NOT masked by &1 in this function, you must do it yourself !
|
|
// 'temp_u32' MUST be a U32 !!
|
|
#define VarBitsBGet1(vb,temp_u32) \
|
|
( \
|
|
((vb).bitlen==0)? \
|
|
( \
|
|
temp_u32=*((BITSTYPE* RADRESTRICT)((vb).cur)),\
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES, \
|
|
((vb).bits)=((BITSTYPE)temp_u32)<<1, \
|
|
((vb).bitlen)=(BITSTYPELEN-1) \
|
|
):( \
|
|
temp_u32=((vb).bits), \
|
|
((vb).bits)<<=1, \
|
|
--((vb).bitlen) \
|
|
), \
|
|
(temp_u32>>(BITSTYPELEN-1)) \
|
|
)
|
|
|
|
|
|
|
|
//*
|
|
#ifdef __RADX86__
|
|
#ifdef _DEBUG
|
|
#ifdef __cplusplus
|
|
|
|
inline void _VarBitsBGet(U32 & v,VARBITSB & vb,int len)
|
|
{
|
|
radassert( ! vb.isPut );
|
|
|
|
if ( (int)((vb).bitlen) < (len))
|
|
{
|
|
register BITSTYPE nb=*((BITSTYPE* RADRESTRICT)((vb).cur));
|
|
v=((((vb).bits)|(nb>>((vb).bitlen)))>>(BITSTYPELEN-len));
|
|
((vb).bits)=nb<<((len)-((vb).bitlen));
|
|
((vb).bitlen)=((vb).bitlen)+BITSTYPELEN-(len);
|
|
((vb).cur)=((char*)((vb).cur))+BITSTYPEBYTES;
|
|
v &= VarBitsLens[len];
|
|
}
|
|
else
|
|
{
|
|
int shift = BITSTYPELEN - len;
|
|
v=(((vb).bits)>>shift);
|
|
((vb).bits)<<=(len);
|
|
((vb).bitlen)-=(len);
|
|
v &= VarBitsLens[len];
|
|
}
|
|
}
|
|
|
|
#undef VarBitsBGet
|
|
#define VarBitsBGet(v,typ,vb,len) _VarBitsBGet((U32 &)v,vb,len)
|
|
|
|
|
|
// __v=(val)&VarBitsLens[__s]
|
|
inline void _VarBitsBPut(VARBITSB & vb,U32 val,int size)
|
|
{
|
|
radassert( vb.isPut );
|
|
|
|
S32 __s=size;
|
|
U32 __v=(val);
|
|
radassert( __v < (1UL<<__s) );
|
|
|
|
if ((vb).bitlen+__s >=BITSTYPELEN)
|
|
{
|
|
S32 __r = __s + (vb).bitlen - BITSTYPELEN;
|
|
radassert( __r >= 0 && __r < 32 );
|
|
radassert( (vb).bitlen != 0 );
|
|
(vb).bits <<= (BITSTYPELEN-(vb).bitlen);
|
|
(vb).bits |= __v >> __r;
|
|
*((U32*)(vb).cur)=(vb).bits;
|
|
(vb).cur=((char*)((vb).cur)+4);
|
|
(vb).bitlen = __r;
|
|
(vb).bits = __v&VarBitsLens[__r];
|
|
}
|
|
else
|
|
{
|
|
radassert( __s < 32 );
|
|
(vb).bits = ((vb).bits<<__s) | __v;
|
|
(vb).bitlen+=__s;
|
|
}
|
|
}
|
|
|
|
#undef VarBitsBPut
|
|
#define VarBitsBPut(vb,val,size) _VarBitsBPut(vb,val,size)
|
|
|
|
#endif // cplusplus
|
|
#endif // _DEBUG
|
|
#endif // __RADX86__
|
|
/**/
|
|
|
|
|
|
#endif
|