1207753Smm///////////////////////////////////////////////////////////////////////////////
2207753Smm//
3207753Smm/// \file       x86.c
4207753Smm/// \brief      Filter for x86 binaries (BCJ filter)
5207753Smm///
6207753Smm//  Authors:    Igor Pavlov
7207753Smm//              Lasse Collin
8207753Smm//
9207753Smm//  This file has been put into the public domain.
10207753Smm//  You can do whatever you want with this file.
11207753Smm//
12207753Smm///////////////////////////////////////////////////////////////////////////////
13207753Smm
14207753Smm#include "simple_private.h"
15207753Smm
16207753Smm
17207753Smm#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
18207753Smm
19207753Smm
20207753Smmstruct lzma_simple_s {
21207753Smm	uint32_t prev_mask;
22207753Smm	uint32_t prev_pos;
23207753Smm};
24207753Smm
25207753Smm
26207753Smmstatic size_t
27207753Smmx86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
28207753Smm		uint8_t *buffer, size_t size)
29207753Smm{
30207753Smm	static const bool MASK_TO_ALLOWED_STATUS[8]
31207753Smm		= { true, true, true, false, true, false, false, false };
32207753Smm
33207753Smm	static const uint32_t MASK_TO_BIT_NUMBER[8]
34207753Smm			= { 0, 1, 2, 2, 3, 3, 3, 3 };
35207753Smm
36207753Smm	uint32_t prev_mask = simple->prev_mask;
37207753Smm	uint32_t prev_pos = simple->prev_pos;
38207753Smm
39207753Smm	if (size < 5)
40207753Smm		return 0;
41207753Smm
42207753Smm	if (now_pos - prev_pos > 5)
43207753Smm		prev_pos = now_pos - 5;
44207753Smm
45207753Smm	const size_t limit = size - 5;
46207753Smm	size_t buffer_pos = 0;
47207753Smm
48207753Smm	while (buffer_pos <= limit) {
49207753Smm		uint8_t b = buffer[buffer_pos];
50207753Smm		if (b != 0xE8 && b != 0xE9) {
51207753Smm			++buffer_pos;
52207753Smm			continue;
53207753Smm		}
54207753Smm
55207753Smm		const uint32_t offset = now_pos + (uint32_t)(buffer_pos)
56207753Smm				- prev_pos;
57207753Smm		prev_pos = now_pos + (uint32_t)(buffer_pos);
58207753Smm
59207753Smm		if (offset > 5) {
60207753Smm			prev_mask = 0;
61207753Smm		} else {
62207753Smm			for (uint32_t i = 0; i < offset; ++i) {
63207753Smm				prev_mask &= 0x77;
64207753Smm				prev_mask <<= 1;
65207753Smm			}
66207753Smm		}
67207753Smm
68207753Smm		b = buffer[buffer_pos + 4];
69207753Smm
70207753Smm		if (Test86MSByte(b)
71207753Smm			&& MASK_TO_ALLOWED_STATUS[(prev_mask >> 1) & 0x7]
72207753Smm				&& (prev_mask >> 1) < 0x10) {
73207753Smm
74207753Smm			uint32_t src = ((uint32_t)(b) << 24)
75207753Smm				| ((uint32_t)(buffer[buffer_pos + 3]) << 16)
76207753Smm				| ((uint32_t)(buffer[buffer_pos + 2]) << 8)
77207753Smm				| (buffer[buffer_pos + 1]);
78207753Smm
79207753Smm			uint32_t dest;
80207753Smm			while (true) {
81207753Smm				if (is_encoder)
82207753Smm					dest = src + (now_pos + (uint32_t)(
83207753Smm							buffer_pos) + 5);
84207753Smm				else
85207753Smm					dest = src - (now_pos + (uint32_t)(
86207753Smm							buffer_pos) + 5);
87207753Smm
88207753Smm				if (prev_mask == 0)
89207753Smm					break;
90207753Smm
91207753Smm				const uint32_t i = MASK_TO_BIT_NUMBER[
92207753Smm						prev_mask >> 1];
93207753Smm
94207753Smm				b = (uint8_t)(dest >> (24 - i * 8));
95207753Smm
96207753Smm				if (!Test86MSByte(b))
97207753Smm					break;
98207753Smm
99207753Smm				src = dest ^ ((1 << (32 - i * 8)) - 1);
100207753Smm			}
101207753Smm
102207753Smm			buffer[buffer_pos + 4]
103207753Smm					= (uint8_t)(~(((dest >> 24) & 1) - 1));
104207753Smm			buffer[buffer_pos + 3] = (uint8_t)(dest >> 16);
105207753Smm			buffer[buffer_pos + 2] = (uint8_t)(dest >> 8);
106207753Smm			buffer[buffer_pos + 1] = (uint8_t)(dest);
107207753Smm			buffer_pos += 5;
108207753Smm			prev_mask = 0;
109207753Smm
110207753Smm		} else {
111207753Smm			++buffer_pos;
112207753Smm			prev_mask |= 1;
113207753Smm			if (Test86MSByte(b))
114207753Smm				prev_mask |= 0x10;
115207753Smm		}
116207753Smm	}
117207753Smm
118207753Smm	simple->prev_mask = prev_mask;
119207753Smm	simple->prev_pos = prev_pos;
120207753Smm
121207753Smm	return buffer_pos;
122207753Smm}
123207753Smm
124207753Smm
125207753Smmstatic lzma_ret
126207753Smmx86_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
127207753Smm		const lzma_filter_info *filters, bool is_encoder)
128207753Smm{
129207753Smm	const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters,
130207753Smm			&x86_code, sizeof(lzma_simple), 5, 1, is_encoder);
131207753Smm
132207753Smm	if (ret == LZMA_OK) {
133207753Smm		next->coder->simple->prev_mask = 0;
134207753Smm		next->coder->simple->prev_pos = (uint32_t)(-5);
135207753Smm	}
136207753Smm
137207753Smm	return ret;
138207753Smm}
139207753Smm
140207753Smm
141207753Smmextern lzma_ret
142207753Smmlzma_simple_x86_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
143207753Smm		const lzma_filter_info *filters)
144207753Smm{
145207753Smm	return x86_coder_init(next, allocator, filters, true);
146207753Smm}
147207753Smm
148207753Smm
149207753Smmextern lzma_ret
150207753Smmlzma_simple_x86_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
151207753Smm		const lzma_filter_info *filters)
152207753Smm{
153207753Smm	return x86_coder_init(next, allocator, filters, false);
154207753Smm}
155