/* Bcj2.h -- BCJ2 Converter for x86 code | |
2014-11-10 : Igor Pavlov : Public domain */ | |
#ifndef __BCJ2_H | |
#define __BCJ2_H | |
#include "7zTypes.h" | |
EXTERN_C_BEGIN | |
#define BCJ2_NUM_STREAMS 4 | |
enum | |
{ | |
BCJ2_STREAM_MAIN, | |
BCJ2_STREAM_CALL, | |
BCJ2_STREAM_JUMP, | |
BCJ2_STREAM_RC | |
}; | |
enum | |
{ | |
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS, | |
BCJ2_DEC_STATE_ORIG_1, | |
BCJ2_DEC_STATE_ORIG_2, | |
BCJ2_DEC_STATE_ORIG_3, | |
BCJ2_DEC_STATE_ORIG, | |
BCJ2_DEC_STATE_OK | |
}; | |
enum | |
{ | |
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, | |
BCJ2_ENC_STATE_OK | |
}; | |
#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) | |
/* | |
CBcj2Dec / CBcj2Enc | |
bufs sizes: | |
BUF_SIZE(n) = lims[n] - bufs[n] | |
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4: | |
(BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 | |
(BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 | |
*/ | |
/* | |
CBcj2Dec: | |
dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: | |
bufs[BCJ2_STREAM_MAIN] >= dest && | |
bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv + | |
BUF_SIZE(BCJ2_STREAM_CALL) + | |
BUF_SIZE(BCJ2_STREAM_JUMP) | |
tempReserv = 0 : for first call of Bcj2Dec_Decode | |
tempReserv = 4 : for any other calls of Bcj2Dec_Decode | |
overlap with offset = 1 is not allowed | |
*/ | |
typedef struct | |
{ | |
const Byte *bufs[BCJ2_NUM_STREAMS]; | |
const Byte *lims[BCJ2_NUM_STREAMS]; | |
Byte *dest; | |
const Byte *destLim; | |
unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ | |
UInt32 ip; | |
Byte temp[4]; | |
UInt32 range; | |
UInt32 code; | |
UInt16 probs[2 + 256]; | |
} CBcj2Dec; | |
void Bcj2Dec_Init(CBcj2Dec *p); | |
/* Returns: SZ_OK or SZ_ERROR_DATA */ | |
SRes Bcj2Dec_Decode(CBcj2Dec *p); | |
#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0) | |
typedef enum | |
{ | |
BCJ2_ENC_FINISH_MODE_CONTINUE, | |
BCJ2_ENC_FINISH_MODE_END_BLOCK, | |
BCJ2_ENC_FINISH_MODE_END_STREAM | |
} EBcj2Enc_FinishMode; | |
typedef struct | |
{ | |
Byte *bufs[BCJ2_NUM_STREAMS]; | |
const Byte *lims[BCJ2_NUM_STREAMS]; | |
const Byte *src; | |
const Byte *srcLim; | |
unsigned state; | |
EBcj2Enc_FinishMode finishMode; | |
Byte prevByte; | |
Byte cache; | |
UInt32 range; | |
UInt64 low; | |
UInt64 cacheSize; | |
UInt32 ip; | |
/* 32-bit ralative offset in JUMP/CALL commands is | |
- (mod 4 GB) in 32-bit mode | |
- signed Int32 in 64-bit mode | |
We use (mod 4 GB) check for fileSize. | |
Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */ | |
UInt32 fileIp; | |
UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */ | |
UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */ | |
UInt32 tempTarget; | |
unsigned tempPos; | |
Byte temp[4 * 2]; | |
unsigned flushPos; | |
UInt16 probs[2 + 256]; | |
} CBcj2Enc; | |
void Bcj2Enc_Init(CBcj2Enc *p); | |
void Bcj2Enc_Encode(CBcj2Enc *p); | |
#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos) | |
#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5) | |
#define BCJ2_RELAT_LIMIT_NUM_BITS 26 | |
#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS) | |
/* limit for CBcj2Enc::fileSize variable */ | |
#define BCJ2_FileSize_MAX ((UInt32)1 << 31) | |
EXTERN_C_END | |
#endif |