/src/CMake/Utilities/cmliblzma/liblzma/simple/x86.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: 0BSD |
2 | | |
3 | | /////////////////////////////////////////////////////////////////////////////// |
4 | | // |
5 | | /// \file x86.c |
6 | | /// \brief Filter for x86 binaries (BCJ filter) |
7 | | /// |
8 | | // Authors: Igor Pavlov |
9 | | // Lasse Collin |
10 | | // |
11 | | /////////////////////////////////////////////////////////////////////////////// |
12 | | |
13 | | #include "simple_private.h" |
14 | | |
15 | | |
16 | 1.41k | #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) |
17 | | |
18 | | |
19 | | typedef struct { |
20 | | uint32_t prev_mask; |
21 | | uint32_t prev_pos; |
22 | | } lzma_simple_x86; |
23 | | |
24 | | |
25 | | static size_t |
26 | | x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder, |
27 | | uint8_t *buffer, size_t size) |
28 | 378 | { |
29 | 378 | static const uint32_t MASK_TO_BIT_NUMBER[5] = { 0, 1, 2, 2, 3 }; |
30 | | |
31 | 378 | lzma_simple_x86 *simple = simple_ptr; |
32 | 378 | uint32_t prev_mask = simple->prev_mask; |
33 | 378 | uint32_t prev_pos = simple->prev_pos; |
34 | | |
35 | 378 | if (size < 5) |
36 | 314 | return 0; |
37 | | |
38 | 64 | if (now_pos - prev_pos > 5) |
39 | 0 | prev_pos = now_pos - 5; |
40 | | |
41 | 64 | const size_t limit = size - 5; |
42 | 64 | size_t buffer_pos = 0; |
43 | | |
44 | 2.41k | while (buffer_pos <= limit) { |
45 | 2.35k | uint8_t b = buffer[buffer_pos]; |
46 | 2.35k | if (b != 0xE8 && b != 0xE9) { |
47 | 1.87k | ++buffer_pos; |
48 | 1.87k | continue; |
49 | 1.87k | } |
50 | | |
51 | 482 | const uint32_t offset = now_pos + (uint32_t)(buffer_pos) |
52 | 482 | - prev_pos; |
53 | 482 | prev_pos = now_pos + (uint32_t)(buffer_pos); |
54 | | |
55 | 482 | if (offset > 5) { |
56 | 86 | prev_mask = 0; |
57 | 396 | } else { |
58 | 1.01k | for (uint32_t i = 0; i < offset; ++i) { |
59 | 616 | prev_mask &= 0x77; |
60 | 616 | prev_mask <<= 1; |
61 | 616 | } |
62 | 396 | } |
63 | | |
64 | 482 | b = buffer[buffer_pos + 4]; |
65 | | |
66 | 482 | if (Test86MSByte(b) && (prev_mask >> 1) <= 4 |
67 | 62 | && (prev_mask >> 1) != 3) { |
68 | | |
69 | 44 | uint32_t src = ((uint32_t)(b) << 24) |
70 | 44 | | ((uint32_t)(buffer[buffer_pos + 3]) << 16) |
71 | 44 | | ((uint32_t)(buffer[buffer_pos + 2]) << 8) |
72 | 44 | | (buffer[buffer_pos + 1]); |
73 | | |
74 | 44 | uint32_t dest; |
75 | 44 | while (true) { |
76 | 44 | if (is_encoder) |
77 | 0 | dest = src + (now_pos + (uint32_t)( |
78 | 0 | buffer_pos) + 5); |
79 | 44 | else |
80 | 44 | dest = src - (now_pos + (uint32_t)( |
81 | 44 | buffer_pos) + 5); |
82 | | |
83 | 44 | if (prev_mask == 0) |
84 | 34 | break; |
85 | | |
86 | 10 | const uint32_t i = MASK_TO_BIT_NUMBER[ |
87 | 10 | prev_mask >> 1]; |
88 | | |
89 | 10 | b = (uint8_t)(dest >> (24 - i * 8)); |
90 | | |
91 | 10 | if (!Test86MSByte(b)) |
92 | 10 | break; |
93 | | |
94 | 0 | src = dest ^ ((1ull << (32 - i * 8)) - 1); |
95 | 0 | } |
96 | | |
97 | 44 | buffer[buffer_pos + 4] |
98 | 44 | = (uint8_t)(~(((dest >> 24) & 1) - 1)); |
99 | 44 | buffer[buffer_pos + 3] = (uint8_t)(dest >> 16); |
100 | 44 | buffer[buffer_pos + 2] = (uint8_t)(dest >> 8); |
101 | 44 | buffer[buffer_pos + 1] = (uint8_t)(dest); |
102 | 44 | buffer_pos += 5; |
103 | 44 | prev_mask = 0; |
104 | | |
105 | 438 | } else { |
106 | 438 | ++buffer_pos; |
107 | 438 | prev_mask |= 1; |
108 | 438 | if (Test86MSByte(b)) |
109 | 106 | prev_mask |= 0x10; |
110 | 438 | } |
111 | 482 | } |
112 | | |
113 | 64 | simple->prev_mask = prev_mask; |
114 | 64 | simple->prev_pos = prev_pos; |
115 | | |
116 | 64 | return buffer_pos; |
117 | 378 | } |
118 | | |
119 | | |
120 | | static lzma_ret |
121 | | x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, |
122 | | const lzma_filter_info *filters, bool is_encoder) |
123 | 74 | { |
124 | 74 | const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters, |
125 | 74 | &x86_code, sizeof(lzma_simple_x86), 5, 1, is_encoder); |
126 | | |
127 | 74 | if (ret == LZMA_OK) { |
128 | 74 | lzma_simple_coder *coder = next->coder; |
129 | 74 | lzma_simple_x86 *simple = coder->simple; |
130 | 74 | simple->prev_mask = 0; |
131 | 74 | simple->prev_pos = (uint32_t)(-5); |
132 | 74 | } |
133 | | |
134 | 74 | return ret; |
135 | 74 | } |
136 | | |
137 | | |
138 | | #ifdef HAVE_ENCODER_X86 |
139 | | extern lzma_ret |
140 | | lzma_simple_x86_encoder_init(lzma_next_coder *next, |
141 | | const lzma_allocator *allocator, |
142 | | const lzma_filter_info *filters) |
143 | 0 | { |
144 | 0 | return x86_coder_init(next, allocator, filters, true); |
145 | 0 | } |
146 | | #endif |
147 | | |
148 | | |
149 | | #ifdef HAVE_DECODER_X86 |
150 | | extern lzma_ret |
151 | | lzma_simple_x86_decoder_init(lzma_next_coder *next, |
152 | | const lzma_allocator *allocator, |
153 | | const lzma_filter_info *filters) |
154 | 74 | { |
155 | | return x86_coder_init(next, allocator, filters, false); |
156 | 74 | } |
157 | | #endif |