/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
2018-04-28 : Igor Pavlov : Public domain */
#include "Precomp.h"
#include "Bcj2.h"
#include "CpuArch.h"
#define CProb UInt16
#define kTopValue ((UInt32)1 << 24 )
#define kNumModelBits 11
#define kBitModelTotal (1 << kNumModelBits)
#define kNumMoveBits 5
#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
void Bcj2Dec_Init(CBcj2Dec *p)
{
unsigned i;
p->state = BCJ2_DEC_STATE_OK;
p->ip = 0 ;
p->temp[3 ] = 0 ;
p->range = 0 ;
p->code = 0 ;
for (i = 0 ; i < sizeof (p->probs) / sizeof (p->probs[0 ]); i++)
p->probs[i] = kBitModelTotal >> 1 ;
}
SRes Bcj2Dec_Decode(CBcj2Dec *p)
{
if (p->range <= 5 )
{
p->state = BCJ2_DEC_STATE_OK;
for (; p->range != 5 ; p->range++)
{
if (p->range == 1 && p->code != 0 )
return SZ_ERROR_DATA;
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
{
p->state = BCJ2_STREAM_RC;
return SZ_OK;
}
p->code = (p->code << 8 ) | *(p->bufs[BCJ2_STREAM_RC])++;
}
if (p->code == 0 xFFFFFFFF)
return SZ_ERROR_DATA;
p->range = 0 xFFFFFFFF;
}
else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
{
while (p->state <= BCJ2_DEC_STATE_ORIG_3)
{
Byte *dest = p->dest;
if (dest == p->destLim)
return SZ_OK;
*dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
p->state++;
p->dest = dest + 1 ;
}
}
/*
if ( BCJ2_IS_32BIT_STREAM ( p - > state ) )
{
const Byte * cur = p - > bufs [ p - > state ] ;
if ( cur = = p - > lims [ p - > state ] )
return SZ_OK ;
p - > bufs [ p - > state ] = cur + 4 ;
{
UInt32 val ;
Byte * dest ;
SizeT rem ;
p - > ip + = 4 ;
val = GetBe32 ( cur ) - p - > ip ;
dest = p - > dest ;
rem = p - > destLim - dest ;
if ( rem < 4 )
{
SizeT i ;
SetUi32 ( p - > temp , val ) ;
for ( i = 0 ; i < rem ; i + + )
dest [ i ] = p - > temp [ i ] ;
p - > dest = dest + rem ;
p - > state = BCJ2_DEC_STATE_ORIG_0 + ( unsigned ) rem ;
return SZ_OK ;
}
SetUi32 ( dest , val ) ;
p - > temp [ 3 ] = ( Byte ) ( val > > 24 ) ;
p - > dest = dest + 4 ;
p - > state = BCJ2_DEC_STATE_OK ;
}
}
*/
for (;;)
{
if (BCJ2_IS_32BIT_STREAM(p->state))
p->state = BCJ2_DEC_STATE_OK;
else
{
if (p->range < kTopValue)
{
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
{
p->state = BCJ2_STREAM_RC;
return SZ_OK;
}
p->range <<= 8 ;
p->code = (p->code << 8 ) | *(p->bufs[BCJ2_STREAM_RC])++;
}
{
const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
const Byte *srcLim;
Byte *dest;
SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
if (num == 0 )
{
p->state = BCJ2_STREAM_MAIN;
return SZ_OK;
}
dest = p->dest;
if (num > (SizeT)(p->destLim - dest))
{
num = p->destLim - dest;
if (num == 0 )
{
p->state = BCJ2_DEC_STATE_ORIG;
return SZ_OK;
}
}
srcLim = src + num;
if (p->temp[3 ] == 0 x0F && (src[0 ] & 0 xF0) == 0 x80)
*dest = src[0 ];
else for (;;)
{
Byte b = *src;
*dest = b;
if (b != 0 x0F)
{
if ((b & 0 xFE) == 0 xE8)
break ;
dest++;
if (++src != srcLim)
continue ;
break ;
}
dest++;
if (++src == srcLim)
break ;
if ((*src & 0 xF0) != 0 x80)
continue ;
*dest = *src;
break ;
}
num = src - p->bufs[BCJ2_STREAM_MAIN];
if (src == srcLim)
{
p->temp[3 ] = src[-1 ];
p->bufs[BCJ2_STREAM_MAIN] = src;
p->ip += (UInt32)num;
p->dest += num;
p->state =
p->bufs[BCJ2_STREAM_MAIN] ==
p->lims[BCJ2_STREAM_MAIN] ?
(unsigned )BCJ2_STREAM_MAIN :
(unsigned )BCJ2_DEC_STATE_ORIG;
return SZ_OK;
}
{
UInt32 bound, ttt;
CProb *prob;
Byte b = src[0 ];
Byte prev = (Byte)(num == 0 ? p->temp[3 ] : src[-1 ]);
p->temp[3 ] = b;
p->bufs[BCJ2_STREAM_MAIN] = src + 1 ;
num++;
p->ip += (UInt32)num;
p->dest += num;
prob = p->probs + (unsigned )(b == 0 xE8 ? 2 + (unsigned )prev : (b == 0 xE9 ? 1 : 0 ));
_IF_BIT_0
{
_UPDATE_0
continue ;
}
_UPDATE_1
}
}
}
{
UInt32 val;
unsigned cj = (p->temp[3 ] == 0 xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
const Byte *cur = p->bufs[cj];
Byte *dest;
SizeT rem;
if (cur == p->lims[cj])
{
p->state = cj;
break ;
}
val = GetBe32(cur);
p->bufs[cj] = cur + 4 ;
p->ip += 4 ;
val -= p->ip;
dest = p->dest;
rem = p->destLim - dest;
if (rem < 4 )
{
p->temp[0 ] = (Byte)val; if (rem > 0 ) dest[0 ] = (Byte)val; val >>= 8 ;
p->temp[1 ] = (Byte)val; if (rem > 1 ) dest[1 ] = (Byte)val; val >>= 8 ;
p->temp[2 ] = (Byte)val; if (rem > 2 ) dest[2 ] = (Byte)val; val >>= 8 ;
p->temp[3 ] = (Byte)val;
p->dest = dest + rem;
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned )rem;
break ;
}
SetUi32(dest, val);
p->temp[3 ] = (Byte)(val >> 24 );
p->dest = dest + 4 ;
}
}
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
{
p->range <<= 8 ;
p->code = (p->code << 8 ) | *(p->bufs[BCJ2_STREAM_RC])++;
}
return SZ_OK;
}
Messung V0.5 in Prozent C=94 H=88 G=90
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland