1 /* Bcj2.h -- BCJ2 Converter for x86 code
2 2014-11-10 : Igor Pavlov : Public domain */
3 
4 #ifndef __BCJ2_H
5 #define __BCJ2_H
6 
7 #include "7zTypes.h"
8 
9 EXTERN_C_BEGIN
10 
11 #define BCJ2_NUM_STREAMS 4
12 
13 enum
14 {
15   BCJ2_STREAM_MAIN,
16   BCJ2_STREAM_CALL,
17   BCJ2_STREAM_JUMP,
18   BCJ2_STREAM_RC
19 };
20 
21 enum
22 {
23   BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
24   BCJ2_DEC_STATE_ORIG_1,
25   BCJ2_DEC_STATE_ORIG_2,
26   BCJ2_DEC_STATE_ORIG_3,
27 
28   BCJ2_DEC_STATE_ORIG,
29   BCJ2_DEC_STATE_OK
30 };
31 
32 enum
33 {
34   BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
35   BCJ2_ENC_STATE_OK
36 };
37 
38 
39 #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
40 
41 /*
42 CBcj2Dec / CBcj2Enc
43 bufs sizes:
44   BUF_SIZE(n) = lims[n] - bufs[n]
45 bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
46     (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
47     (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
48 */
49 
50 /*
51 CBcj2Dec:
52 dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
53   bufs[BCJ2_STREAM_MAIN] >= dest &&
54   bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
55         BUF_SIZE(BCJ2_STREAM_CALL) +
56         BUF_SIZE(BCJ2_STREAM_JUMP)
57      tempReserv = 0 : for first call of Bcj2Dec_Decode
58      tempReserv = 4 : for any other calls of Bcj2Dec_Decode
59   overlap with offset = 1 is not allowed
60 */
61 
62 typedef struct
63 {
64   const Byte *bufs[BCJ2_NUM_STREAMS];
65   const Byte *lims[BCJ2_NUM_STREAMS];
66   Byte *dest;
67   const Byte *destLim;
68 
69   unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
70 
71   UInt32 ip;
72   Byte temp[4];
73   UInt32 range;
74   UInt32 code;
75   UInt16 probs[2 + 256];
76 } CBcj2Dec;
77 
78 void Bcj2Dec_Init(CBcj2Dec *p);
79 
80 /* Returns: SZ_OK or SZ_ERROR_DATA */
81 SRes Bcj2Dec_Decode(CBcj2Dec *p);
82 
83 #define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)
84 
85 
86 
87 typedef enum
88 {
89   BCJ2_ENC_FINISH_MODE_CONTINUE,
90   BCJ2_ENC_FINISH_MODE_END_BLOCK,
91   BCJ2_ENC_FINISH_MODE_END_STREAM
92 } EBcj2Enc_FinishMode;
93 
94 typedef struct
95 {
96   Byte *bufs[BCJ2_NUM_STREAMS];
97   const Byte *lims[BCJ2_NUM_STREAMS];
98   const Byte *src;
99   const Byte *srcLim;
100 
101   unsigned state;
102   EBcj2Enc_FinishMode finishMode;
103 
104   Byte prevByte;
105 
106   Byte cache;
107   UInt32 range;
108   UInt64 low;
109   UInt64 cacheSize;
110 
111   UInt32 ip;
112 
113   /* 32-bit ralative offset in JUMP/CALL commands is
114        - (mod 4 GB)   in 32-bit mode
115        - signed Int32 in 64-bit mode
116      We use (mod 4 GB) check for fileSize.
117      Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */
118   UInt32 fileIp;
119   UInt32 fileSize;    /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */
120   UInt32 relatLimit;  /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */
121 
122   UInt32 tempTarget;
123   unsigned tempPos;
124   Byte temp[4 * 2];
125 
126   unsigned flushPos;
127 
128   UInt16 probs[2 + 256];
129 } CBcj2Enc;
130 
131 void Bcj2Enc_Init(CBcj2Enc *p);
132 void Bcj2Enc_Encode(CBcj2Enc *p);
133 
134 #define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)
135 #define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)
136 
137 
138 #define BCJ2_RELAT_LIMIT_NUM_BITS 26
139 #define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS)
140 
141 /* limit for CBcj2Enc::fileSize variable */
142 #define BCJ2_FileSize_MAX ((UInt32)1 << 31)
143 
144 EXTERN_C_END
145 
146 #endif
147