1 /* Bcj2Enc.c -- BCJ2 Encoder (Converter for x86 code)
2 2019-02-02 : Igor Pavlov : Public domain */
6 /* #define SHOW_STAT */
22 #define kTopValue ((UInt32)1 << 24)
23 #define kNumModelBits 11
24 #define kBitModelTotal (1 << kNumModelBits)
25 #define kNumMoveBits 5
27 void Bcj2Enc_Init(CBcj2Enc
*p
)
31 p
->state
= BCJ2_ENC_STATE_OK
;
32 p
->finishMode
= BCJ2_ENC_FINISH_MODE_CONTINUE
;
37 p
->range
= 0xFFFFFFFF;
45 p
->relatLimit
= BCJ2_RELAT_LIMIT
;
51 for (i
= 0; i
< sizeof(p
->probs
) / sizeof(p
->probs
[0]); i
++)
52 p
->probs
[i
] = kBitModelTotal
>> 1;
55 static BoolInt MY_FAST_CALL
RangeEnc_ShiftLow(CBcj2Enc
*p
)
57 if ((UInt32
)p
->low
< (UInt32
)0xFF000000 || (UInt32
)(p
->low
>> 32) != 0)
59 Byte
*buf
= p
->bufs
[BCJ2_STREAM_RC
];
62 if (buf
== p
->lims
[BCJ2_STREAM_RC
])
64 p
->state
= BCJ2_STREAM_RC
;
65 p
->bufs
[BCJ2_STREAM_RC
] = buf
;
68 *buf
++ = (Byte
)(p
->cache
+ (Byte
)(p
->low
>> 32));
71 while (--p
->cacheSize
);
72 p
->bufs
[BCJ2_STREAM_RC
] = buf
;
73 p
->cache
= (Byte
)((UInt32
)p
->low
>> 24);
76 p
->low
= (UInt32
)p
->low
<< 8;
80 static void Bcj2Enc_Encode_2(CBcj2Enc
*p
)
82 if (BCJ2_IS_32BIT_STREAM(p
->state
))
84 Byte
*cur
= p
->bufs
[p
->state
];
85 if (cur
== p
->lims
[p
->state
])
87 SetBe32(cur
, p
->tempTarget
);
88 p
->bufs
[p
->state
] = cur
+ 4;
91 p
->state
= BCJ2_ENC_STATE_ORIG
;
95 if (p
->range
< kTopValue
)
97 if (RangeEnc_ShiftLow(p
))
104 const Byte
*src
= p
->src
;
107 SizeT num
= p
->srcLim
- src
;
109 if (p
->finishMode
== BCJ2_ENC_FINISH_MODE_CONTINUE
)
118 dest
= p
->bufs
[BCJ2_STREAM_MAIN
];
119 if (num
> (SizeT
)(p
->lims
[BCJ2_STREAM_MAIN
] - dest
))
121 num
= p
->lims
[BCJ2_STREAM_MAIN
] - dest
;
124 p
->state
= BCJ2_STREAM_MAIN
;
131 if (p
->prevByte
== 0x0F && (src
[0] & 0xF0) == 0x80)
139 if ((b
& 0xFE) == 0xE8)
149 if ((*src
& 0xF0) != 0x80)
159 p
->prevByte
= src
[-1];
160 p
->bufs
[BCJ2_STREAM_MAIN
] = dest
;
162 p
->ip
+= (UInt32
)num
;
167 Byte context
= (Byte
)(num
== 0 ? p
->prevByte
: src
[-1]);
170 p
->bufs
[BCJ2_STREAM_MAIN
] = dest
+ 1;
171 p
->ip
+= (UInt32
)num
+ 1;
176 if ((SizeT
)(p
->srcLim
- src
) >= 4)
178 UInt32 relatVal
= GetUi32(src
);
179 if ((p
->fileSize
== 0 || (UInt32
)(p
->ip
+ 4 + relatVal
- p
->fileIp
) < p
->fileSize
)
180 && ((relatVal
+ p
->relatLimit
) >> 1) < p
->relatLimit
)
188 CProb
*prob
= p
->probs
+ (unsigned)(b
== 0xE8 ? 2 + (unsigned)context
: (b
== 0xE9 ? 1 : 0));
191 bound
= (p
->range
>> kNumModelBits
) * ttt
;
196 *prob
= (CProb
)(ttt
+ ((kBitModelTotal
- ttt
) >> kNumMoveBits
));
204 *prob
= (CProb
)(ttt
- (ttt
>> kNumMoveBits
));
207 UInt32 relatVal
= GetUi32(src
);
210 absVal
= p
->ip
+ relatVal
;
211 p
->prevByte
= src
[3];
215 unsigned cj
= (b
== 0xE8) ? BCJ2_STREAM_CALL
: BCJ2_STREAM_JUMP
;
216 Byte
*cur
= p
->bufs
[cj
];
217 if (cur
== p
->lims
[cj
])
220 p
->tempTarget
= absVal
;
223 SetBe32(cur
, absVal
);
224 p
->bufs
[cj
] = cur
+ 4;
233 if (p
->finishMode
!= BCJ2_ENC_FINISH_MODE_END_STREAM
)
236 for (; p
->flushPos
< 5; p
->flushPos
++)
237 if (RangeEnc_ShiftLow(p
))
239 p
->state
= BCJ2_ENC_STATE_OK
;
243 void Bcj2Enc_Encode(CBcj2Enc
*p
)
246 PRF(printf("---- ip = %8d tempPos = %8d src = %8d\n", p
->ip
, p
->tempPos
, p
->srcLim
- p
->src
));
254 const Byte
*src
= p
->src
;
255 const Byte
*srcLim
= p
->srcLim
;
256 EBcj2Enc_FinishMode finishMode
= p
->finishMode
;
259 p
->srcLim
= p
->temp
+ p
->tempPos
;
261 p
->finishMode
= BCJ2_ENC_FINISH_MODE_CONTINUE
;
263 PRF(printf(" ip = %8d tempPos = %8d src = %8d\n", p
->ip
, p
->tempPos
, p
->srcLim
- p
->src
));
268 unsigned num
= (unsigned)(p
->src
- p
->temp
);
269 unsigned tempPos
= p
->tempPos
- num
;
271 p
->tempPos
= tempPos
;
272 for (i
= 0; i
< tempPos
; i
++)
273 p
->temp
[i
] = p
->temp
[(size_t)i
+ num
];
277 p
->finishMode
= finishMode
;
279 if (p
->state
!= BCJ2_ENC_STATE_ORIG
|| src
== srcLim
)
282 if (extra
>= tempPos
)
284 p
->src
= src
- tempPos
;
289 p
->temp
[tempPos
] = src
[0];
290 p
->tempPos
= tempPos
+ 1;
297 PRF(printf("++++ ip = %8d tempPos = %8d src = %8d\n", p
->ip
, p
->tempPos
, p
->srcLim
- p
->src
));
301 if (p
->state
== BCJ2_ENC_STATE_ORIG
)
303 const Byte
*src
= p
->src
;
304 unsigned rem
= (unsigned)(p
->srcLim
- src
);
306 for (i
= 0; i
< rem
; i
++)