1 // SPDX-License-Identifier: 0BSD
3 ///////////////////////////////////////////////////////////////////////////////
6 /// \brief Filter for x86 binaries (BCJ filter)
8 // Authors: Igor Pavlov
11 ///////////////////////////////////////////////////////////////////////////////
13 #include "simple_private.h"
16 #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
26 x86_code(void *simple_ptr
, uint32_t now_pos
, bool is_encoder
,
27 uint8_t *buffer
, size_t size
)
29 static const uint32_t MASK_TO_BIT_NUMBER
[5] = { 0, 1, 2, 2, 3 };
31 lzma_simple_x86
*simple
= simple_ptr
;
32 uint32_t prev_mask
= simple
->prev_mask
;
33 uint32_t prev_pos
= simple
->prev_pos
;
38 if (now_pos
- prev_pos
> 5)
39 prev_pos
= now_pos
- 5;
41 const size_t limit
= size
- 5;
42 size_t buffer_pos
= 0;
44 while (buffer_pos
<= limit
) {
45 uint8_t b
= buffer
[buffer_pos
];
46 if (b
!= 0xE8 && b
!= 0xE9) {
51 const uint32_t offset
= now_pos
+ (uint32_t)(buffer_pos
)
53 prev_pos
= now_pos
+ (uint32_t)(buffer_pos
);
58 for (uint32_t i
= 0; i
< offset
; ++i
) {
64 b
= buffer
[buffer_pos
+ 4];
66 if (Test86MSByte(b
) && (prev_mask
>> 1) <= 4
67 && (prev_mask
>> 1) != 3) {
69 uint32_t src
= ((uint32_t)(b
) << 24)
70 | ((uint32_t)(buffer
[buffer_pos
+ 3]) << 16)
71 | ((uint32_t)(buffer
[buffer_pos
+ 2]) << 8)
72 | (buffer
[buffer_pos
+ 1]);
77 dest
= src
+ (now_pos
+ (uint32_t)(
80 dest
= src
- (now_pos
+ (uint32_t)(
86 const uint32_t i
= MASK_TO_BIT_NUMBER
[
89 b
= (uint8_t)(dest
>> (24 - i
* 8));
94 src
= dest
^ ((1U << (32 - i
* 8)) - 1);
97 buffer
[buffer_pos
+ 4]
98 = (uint8_t)(~(((dest
>> 24) & 1) - 1));
99 buffer
[buffer_pos
+ 3] = (uint8_t)(dest
>> 16);
100 buffer
[buffer_pos
+ 2] = (uint8_t)(dest
>> 8);
101 buffer
[buffer_pos
+ 1] = (uint8_t)(dest
);
113 simple
->prev_mask
= prev_mask
;
114 simple
->prev_pos
= prev_pos
;
121 x86_coder_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
122 const lzma_filter_info
*filters
, bool is_encoder
)
124 const lzma_ret ret
= lzma_simple_coder_init(next
, allocator
, filters
,
125 &x86_code
, sizeof(lzma_simple_x86
), 5, 1, is_encoder
);
127 if (ret
== LZMA_OK
) {
128 lzma_simple_coder
*coder
= next
->coder
;
129 lzma_simple_x86
*simple
= coder
->simple
;
130 simple
->prev_mask
= 0;
131 simple
->prev_pos
= (uint32_t)(-5);
138 #ifdef HAVE_ENCODER_X86
140 lzma_simple_x86_encoder_init(lzma_next_coder
*next
,
141 const lzma_allocator
*allocator
,
142 const lzma_filter_info
*filters
)
144 return x86_coder_init(next
, allocator
, filters
, true);
149 #ifdef HAVE_DECODER_X86
151 lzma_simple_x86_decoder_init(lzma_next_coder
*next
,
152 const lzma_allocator
*allocator
,
153 const lzma_filter_info
*filters
)
155 return x86_coder_init(next
, allocator
, filters
, false);