12940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
22940b44dSPeter Avalos //
32940b44dSPeter Avalos /// \file ia64.c
42940b44dSPeter Avalos /// \brief Filter for IA64 (Itanium) binaries
52940b44dSPeter Avalos ///
62940b44dSPeter Avalos // Authors: Igor Pavlov
72940b44dSPeter Avalos // Lasse Collin
82940b44dSPeter Avalos //
92940b44dSPeter Avalos // This file has been put into the public domain.
102940b44dSPeter Avalos // You can do whatever you want with this file.
112940b44dSPeter Avalos //
122940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
132940b44dSPeter Avalos
142940b44dSPeter Avalos #include "simple_private.h"
152940b44dSPeter Avalos
162940b44dSPeter Avalos
172940b44dSPeter Avalos static size_t
ia64_code(void * simple lzma_attribute ((__unused__)),uint32_t now_pos,bool is_encoder,uint8_t * buffer,size_t size)1846a2189dSzrj ia64_code(void *simple lzma_attribute((__unused__)),
192940b44dSPeter Avalos uint32_t now_pos, bool is_encoder,
202940b44dSPeter Avalos uint8_t *buffer, size_t size)
212940b44dSPeter Avalos {
222940b44dSPeter Avalos static const uint32_t BRANCH_TABLE[32] = {
232940b44dSPeter Avalos 0, 0, 0, 0, 0, 0, 0, 0,
242940b44dSPeter Avalos 0, 0, 0, 0, 0, 0, 0, 0,
252940b44dSPeter Avalos 4, 4, 6, 6, 0, 0, 7, 7,
262940b44dSPeter Avalos 4, 4, 0, 0, 4, 4, 0, 0
272940b44dSPeter Avalos };
282940b44dSPeter Avalos
292940b44dSPeter Avalos size_t i;
302940b44dSPeter Avalos for (i = 0; i + 16 <= size; i += 16) {
312940b44dSPeter Avalos const uint32_t instr_template = buffer[i] & 0x1F;
322940b44dSPeter Avalos const uint32_t mask = BRANCH_TABLE[instr_template];
332940b44dSPeter Avalos uint32_t bit_pos = 5;
342940b44dSPeter Avalos
352940b44dSPeter Avalos for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) {
362940b44dSPeter Avalos if (((mask >> slot) & 1) == 0)
372940b44dSPeter Avalos continue;
382940b44dSPeter Avalos
392940b44dSPeter Avalos const size_t byte_pos = (bit_pos >> 3);
402940b44dSPeter Avalos const uint32_t bit_res = bit_pos & 0x7;
412940b44dSPeter Avalos uint64_t instruction = 0;
422940b44dSPeter Avalos
432940b44dSPeter Avalos for (size_t j = 0; j < 6; ++j)
442940b44dSPeter Avalos instruction += (uint64_t)(
452940b44dSPeter Avalos buffer[i + j + byte_pos])
462940b44dSPeter Avalos << (8 * j);
472940b44dSPeter Avalos
482940b44dSPeter Avalos uint64_t inst_norm = instruction >> bit_res;
492940b44dSPeter Avalos
502940b44dSPeter Avalos if (((inst_norm >> 37) & 0xF) == 0x5
512940b44dSPeter Avalos && ((inst_norm >> 9) & 0x7) == 0
522940b44dSPeter Avalos /* && (inst_norm & 0x3F)== 0 */
532940b44dSPeter Avalos ) {
542940b44dSPeter Avalos uint32_t src = (uint32_t)(
552940b44dSPeter Avalos (inst_norm >> 13) & 0xFFFFF);
562940b44dSPeter Avalos src |= ((inst_norm >> 36) & 1) << 20;
572940b44dSPeter Avalos
582940b44dSPeter Avalos src <<= 4;
592940b44dSPeter Avalos
602940b44dSPeter Avalos uint32_t dest;
612940b44dSPeter Avalos if (is_encoder)
622940b44dSPeter Avalos dest = now_pos + (uint32_t)(i) + src;
632940b44dSPeter Avalos else
642940b44dSPeter Avalos dest = src - (now_pos + (uint32_t)(i));
652940b44dSPeter Avalos
662940b44dSPeter Avalos dest >>= 4;
672940b44dSPeter Avalos
682940b44dSPeter Avalos inst_norm &= ~((uint64_t)(0x8FFFFF) << 13);
692940b44dSPeter Avalos inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13;
702940b44dSPeter Avalos inst_norm |= (uint64_t)(dest & 0x100000)
712940b44dSPeter Avalos << (36 - 20);
722940b44dSPeter Avalos
73*e151908bSDaniel Fojt instruction &= (1U << bit_res) - 1;
742940b44dSPeter Avalos instruction |= (inst_norm << bit_res);
752940b44dSPeter Avalos
762940b44dSPeter Avalos for (size_t j = 0; j < 6; j++)
772940b44dSPeter Avalos buffer[i + j + byte_pos] = (uint8_t)(
782940b44dSPeter Avalos instruction
792940b44dSPeter Avalos >> (8 * j));
802940b44dSPeter Avalos }
812940b44dSPeter Avalos }
822940b44dSPeter Avalos }
832940b44dSPeter Avalos
842940b44dSPeter Avalos return i;
852940b44dSPeter Avalos }
862940b44dSPeter Avalos
872940b44dSPeter Avalos
882940b44dSPeter Avalos static lzma_ret
ia64_coder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters,bool is_encoder)8915ab8c86SJohn Marino ia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
902940b44dSPeter Avalos const lzma_filter_info *filters, bool is_encoder)
912940b44dSPeter Avalos {
922940b44dSPeter Avalos return lzma_simple_coder_init(next, allocator, filters,
932940b44dSPeter Avalos &ia64_code, 0, 16, 16, is_encoder);
942940b44dSPeter Avalos }
952940b44dSPeter Avalos
962940b44dSPeter Avalos
972940b44dSPeter Avalos extern lzma_ret
lzma_simple_ia64_encoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)982940b44dSPeter Avalos lzma_simple_ia64_encoder_init(lzma_next_coder *next,
9915ab8c86SJohn Marino const lzma_allocator *allocator,
10015ab8c86SJohn Marino const lzma_filter_info *filters)
1012940b44dSPeter Avalos {
1022940b44dSPeter Avalos return ia64_coder_init(next, allocator, filters, true);
1032940b44dSPeter Avalos }
1042940b44dSPeter Avalos
1052940b44dSPeter Avalos
1062940b44dSPeter Avalos extern lzma_ret
lzma_simple_ia64_decoder_init(lzma_next_coder * next,const lzma_allocator * allocator,const lzma_filter_info * filters)1072940b44dSPeter Avalos lzma_simple_ia64_decoder_init(lzma_next_coder *next,
10815ab8c86SJohn Marino const lzma_allocator *allocator,
10915ab8c86SJohn Marino const lzma_filter_info *filters)
1102940b44dSPeter Avalos {
1112940b44dSPeter Avalos return ia64_coder_init(next, allocator, filters, false);
1122940b44dSPeter Avalos }
113