13b35e7eeSXin LI // SPDX-License-Identifier: 0BSD
23b35e7eeSXin LI
381ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
481ad8388SMartin Matuska //
581ad8388SMartin Matuska /// \file ia64.c
681ad8388SMartin Matuska /// \brief Filter for IA64 (Itanium) binaries
781ad8388SMartin Matuska ///
881ad8388SMartin Matuska // Authors: Igor Pavlov
981ad8388SMartin Matuska // Lasse Collin
1081ad8388SMartin Matuska //
1181ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
1281ad8388SMartin Matuska
1381ad8388SMartin Matuska #include "simple_private.h"
1481ad8388SMartin Matuska
1581ad8388SMartin Matuska
1681ad8388SMartin Matuska static size_t
ia64_code(void * simple lzma_attribute ((__unused__)),uint32_t now_pos,bool is_encoder,uint8_t * buffer,size_t size)171456f0f9SXin LI ia64_code(void *simple lzma_attribute((__unused__)),
1881ad8388SMartin Matuska uint32_t now_pos, bool is_encoder,
1981ad8388SMartin Matuska uint8_t *buffer, size_t size)
2081ad8388SMartin Matuska {
2181ad8388SMartin Matuska static const uint32_t BRANCH_TABLE[32] = {
2281ad8388SMartin Matuska 0, 0, 0, 0, 0, 0, 0, 0,
2381ad8388SMartin Matuska 0, 0, 0, 0, 0, 0, 0, 0,
2481ad8388SMartin Matuska 4, 4, 6, 6, 0, 0, 7, 7,
2581ad8388SMartin Matuska 4, 4, 0, 0, 4, 4, 0, 0
2681ad8388SMartin Matuska };
2781ad8388SMartin Matuska
28*128836d3SXin LI size &= ~(size_t)15;
29*128836d3SXin LI
3081ad8388SMartin Matuska size_t i;
31*128836d3SXin LI for (i = 0; i < size; i += 16) {
3281ad8388SMartin Matuska const uint32_t instr_template = buffer[i] & 0x1F;
3381ad8388SMartin Matuska const uint32_t mask = BRANCH_TABLE[instr_template];
3481ad8388SMartin Matuska uint32_t bit_pos = 5;
3581ad8388SMartin Matuska
3681ad8388SMartin Matuska for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) {
3781ad8388SMartin Matuska if (((mask >> slot) & 1) == 0)
3881ad8388SMartin Matuska continue;
3981ad8388SMartin Matuska
4081ad8388SMartin Matuska const size_t byte_pos = (bit_pos >> 3);
4181ad8388SMartin Matuska const uint32_t bit_res = bit_pos & 0x7;
4281ad8388SMartin Matuska uint64_t instruction = 0;
4381ad8388SMartin Matuska
4481ad8388SMartin Matuska for (size_t j = 0; j < 6; ++j)
4581ad8388SMartin Matuska instruction += (uint64_t)(
4681ad8388SMartin Matuska buffer[i + j + byte_pos])
4781ad8388SMartin Matuska << (8 * j);
4881ad8388SMartin Matuska
4981ad8388SMartin Matuska uint64_t inst_norm = instruction >> bit_res;
5081ad8388SMartin Matuska
5181ad8388SMartin Matuska if (((inst_norm >> 37) & 0xF) == 0x5
5281ad8388SMartin Matuska && ((inst_norm >> 9) & 0x7) == 0
5381ad8388SMartin Matuska /* && (inst_norm & 0x3F)== 0 */
5481ad8388SMartin Matuska ) {
5581ad8388SMartin Matuska uint32_t src = (uint32_t)(
5681ad8388SMartin Matuska (inst_norm >> 13) & 0xFFFFF);
5781ad8388SMartin Matuska src |= ((inst_norm >> 36) & 1) << 20;
5881ad8388SMartin Matuska
5981ad8388SMartin Matuska src <<= 4;
6081ad8388SMartin Matuska
6181ad8388SMartin Matuska uint32_t dest;
6281ad8388SMartin Matuska if (is_encoder)
6381ad8388SMartin Matuska dest = now_pos + (uint32_t)(i) + src;
6481ad8388SMartin Matuska else
6581ad8388SMartin Matuska dest = src - (now_pos + (uint32_t)(i));
6681ad8388SMartin Matuska
6781ad8388SMartin Matuska dest >>= 4;
6881ad8388SMartin Matuska
6981ad8388SMartin Matuska inst_norm &= ~((uint64_t)(0x8FFFFF) << 13);
7081ad8388SMartin Matuska inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13;
7181ad8388SMartin Matuska inst_norm |= (uint64_t)(dest & 0x100000)
7281ad8388SMartin Matuska << (36 - 20);
7381ad8388SMartin Matuska
74a8675d92SXin LI instruction &= (1U << bit_res) - 1;
7581ad8388SMartin Matuska instruction |= (inst_norm << bit_res);
7681ad8388SMartin Matuska
7781ad8388SMartin Matuska for (size_t j = 0; j < 6; j++)
7881ad8388SMartin Matuska buffer[i + j + byte_pos] = (uint8_t)(
7981ad8388SMartin Matuska instruction
8081ad8388SMartin Matuska >> (8 * j));
8181ad8388SMartin Matuska }
8281ad8388SMartin Matuska }
8381ad8388SMartin Matuska }
8481ad8388SMartin Matuska
8581ad8388SMartin Matuska return i;
8681ad8388SMartin Matuska }
8781ad8388SMartin Matuska
8881ad8388SMartin Matuska
8981ad8388SMartin Matuska static lzma_ret
ia64_coder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters,bool is_encoder)9053200025SRui Paulo ia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
9181ad8388SMartin Matuska const lzma_filter_info *filters, bool is_encoder)
9281ad8388SMartin Matuska {
9381ad8388SMartin Matuska return lzma_simple_coder_init(next, allocator, filters,
9481ad8388SMartin Matuska &ia64_code, 0, 16, 16, is_encoder);
9581ad8388SMartin Matuska }
9681ad8388SMartin Matuska
9781ad8388SMartin Matuska
9873ed8e77SXin LI #ifdef HAVE_ENCODER_IA64
9981ad8388SMartin Matuska extern lzma_ret
lzma_simple_ia64_encoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)10081ad8388SMartin Matuska lzma_simple_ia64_encoder_init(lzma_next_coder *next,
10153200025SRui Paulo const lzma_allocator *allocator,
10253200025SRui Paulo const lzma_filter_info *filters)
10381ad8388SMartin Matuska {
10481ad8388SMartin Matuska return ia64_coder_init(next, allocator, filters, true);
10581ad8388SMartin Matuska }
10673ed8e77SXin LI #endif
10781ad8388SMartin Matuska
10881ad8388SMartin Matuska
10973ed8e77SXin LI #ifdef HAVE_DECODER_IA64
11081ad8388SMartin Matuska extern lzma_ret
lzma_simple_ia64_decoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)11181ad8388SMartin Matuska lzma_simple_ia64_decoder_init(lzma_next_coder *next,
11253200025SRui Paulo const lzma_allocator *allocator,
11353200025SRui Paulo const lzma_filter_info *filters)
11481ad8388SMartin Matuska {
11581ad8388SMartin Matuska return ia64_coder_init(next, allocator, filters, false);
11681ad8388SMartin Matuska }
11773ed8e77SXin LI #endif
118