Path: blob/master/Utilities/cmliblzma/liblzma/simple/x86.c
3156 views
// SPDX-License-Identifier: 0BSD12///////////////////////////////////////////////////////////////////////////////3//4/// \file x86.c5/// \brief Filter for x86 binaries (BCJ filter)6///7// Authors: Igor Pavlov8// Lasse Collin9//10///////////////////////////////////////////////////////////////////////////////1112#include "simple_private.h"131415#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)161718typedef struct {19uint32_t prev_mask;20uint32_t prev_pos;21} lzma_simple_x86;222324static size_t25x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder,26uint8_t *buffer, size_t size)27{28static const uint32_t MASK_TO_BIT_NUMBER[5] = { 0, 1, 2, 2, 3 };2930lzma_simple_x86 *simple = simple_ptr;31uint32_t prev_mask = simple->prev_mask;32uint32_t prev_pos = simple->prev_pos;3334if (size < 5)35return 0;3637if (now_pos - prev_pos > 5)38prev_pos = now_pos - 5;3940const size_t limit = size - 5;41size_t buffer_pos = 0;4243while (buffer_pos <= limit) {44uint8_t b = buffer[buffer_pos];45if (b != 0xE8 && b != 0xE9) {46++buffer_pos;47continue;48}4950const uint32_t offset = now_pos + (uint32_t)(buffer_pos)51- prev_pos;52prev_pos = now_pos + (uint32_t)(buffer_pos);5354if (offset > 5) {55prev_mask = 0;56} else {57for (uint32_t i = 0; i < offset; ++i) {58prev_mask &= 0x77;59prev_mask <<= 1;60}61}6263b = buffer[buffer_pos + 4];6465if (Test86MSByte(b) && (prev_mask >> 1) <= 466&& (prev_mask >> 1) != 3) {6768uint32_t src = ((uint32_t)(b) << 24)69| ((uint32_t)(buffer[buffer_pos + 3]) << 16)70| ((uint32_t)(buffer[buffer_pos + 2]) << 8)71| (buffer[buffer_pos + 1]);7273uint32_t dest;74while (true) {75if (is_encoder)76dest = src + (now_pos + (uint32_t)(77buffer_pos) + 5);78else79dest = src - (now_pos + (uint32_t)(80buffer_pos) + 5);8182if (prev_mask == 0)83break;8485const uint32_t i = MASK_TO_BIT_NUMBER[86prev_mask >> 1];8788b = (uint8_t)(dest >> (24 - i * 8));8990if (!Test86MSByte(b))91break;9293src = dest ^ ((1ull << (32 - i * 8)) - 1);94}9596buffer[buffer_pos + 4]97= (uint8_t)(~(((dest >> 24) & 1) - 1));98buffer[buffer_pos + 3] = (uint8_t)(dest >> 16);99buffer[buffer_pos + 2] = (uint8_t)(dest >> 8);100buffer[buffer_pos + 1] = (uint8_t)(dest);101buffer_pos += 5;102prev_mask = 0;103104} else {105++buffer_pos;106prev_mask |= 1;107if (Test86MSByte(b))108prev_mask |= 0x10;109}110}111112simple->prev_mask = prev_mask;113simple->prev_pos = prev_pos;114115return buffer_pos;116}117118119static lzma_ret120x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,121const lzma_filter_info *filters, bool is_encoder)122{123const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters,124&x86_code, sizeof(lzma_simple_x86), 5, 1, is_encoder);125126if (ret == LZMA_OK) {127lzma_simple_coder *coder = next->coder;128lzma_simple_x86 *simple = coder->simple;129simple->prev_mask = 0;130simple->prev_pos = (uint32_t)(-5);131}132133return ret;134}135136137#ifdef HAVE_ENCODER_X86138extern lzma_ret139lzma_simple_x86_encoder_init(lzma_next_coder *next,140const lzma_allocator *allocator,141const lzma_filter_info *filters)142{143return x86_coder_init(next, allocator, filters, true);144}145#endif146147148#ifdef HAVE_DECODER_X86149extern lzma_ret150lzma_simple_x86_decoder_init(lzma_next_coder *next,151const lzma_allocator *allocator,152const lzma_filter_info *filters)153{154return x86_coder_init(next, allocator, filters, false);155}156#endif157158159