1207753Smm/////////////////////////////////////////////////////////////////////////////// 2207753Smm// 3207753Smm/// \file ia64.c 4207753Smm/// \brief Filter for IA64 (Itanium) binaries 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 17207753Smmstatic size_t 18312518Sdelphijia64_code(void *simple lzma_attribute((__unused__)), 19207753Smm uint32_t now_pos, bool is_encoder, 20207753Smm uint8_t *buffer, size_t size) 21207753Smm{ 22207753Smm static const uint32_t BRANCH_TABLE[32] = { 23207753Smm 0, 0, 0, 0, 0, 0, 0, 0, 24207753Smm 0, 0, 0, 0, 0, 0, 0, 0, 25207753Smm 4, 4, 6, 6, 0, 0, 7, 7, 26207753Smm 4, 4, 0, 0, 4, 4, 0, 0 27207753Smm }; 28207753Smm 29207753Smm size_t i; 30207753Smm for (i = 0; i + 16 <= size; i += 16) { 31207753Smm const uint32_t instr_template = buffer[i] & 0x1F; 32207753Smm const uint32_t mask = BRANCH_TABLE[instr_template]; 33207753Smm uint32_t bit_pos = 5; 34207753Smm 35207753Smm for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) { 36207753Smm if (((mask >> slot) & 1) == 0) 37207753Smm continue; 38207753Smm 39207753Smm const size_t byte_pos = (bit_pos >> 3); 40207753Smm const uint32_t bit_res = bit_pos & 0x7; 41207753Smm uint64_t instruction = 0; 42207753Smm 43207753Smm for (size_t j = 0; j < 6; ++j) 44207753Smm instruction += (uint64_t)( 45207753Smm buffer[i + j + byte_pos]) 46207753Smm << (8 * j); 47207753Smm 48207753Smm uint64_t inst_norm = instruction >> bit_res; 49207753Smm 50207753Smm if (((inst_norm >> 37) & 0xF) == 0x5 51207753Smm && ((inst_norm >> 9) & 0x7) == 0 52207753Smm /* && (inst_norm & 0x3F)== 0 */ 53207753Smm ) { 54207753Smm uint32_t src = (uint32_t)( 55207753Smm (inst_norm >> 13) & 0xFFFFF); 56207753Smm src |= ((inst_norm >> 36) & 1) << 20; 57207753Smm 58207753Smm src <<= 4; 59207753Smm 60207753Smm uint32_t dest; 61207753Smm if (is_encoder) 62207753Smm dest = now_pos + (uint32_t)(i) + src; 63207753Smm else 64207753Smm dest = src - (now_pos + (uint32_t)(i)); 65207753Smm 66207753Smm dest >>= 4; 67207753Smm 68207753Smm inst_norm &= ~((uint64_t)(0x8FFFFF) << 13); 69207753Smm inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13; 70207753Smm inst_norm |= (uint64_t)(dest & 0x100000) 71207753Smm << (36 - 20); 72207753Smm 73207753Smm instruction &= (1 << bit_res) - 1; 74207753Smm instruction |= (inst_norm << bit_res); 75207753Smm 76207753Smm for (size_t j = 0; j < 6; j++) 77207753Smm buffer[i + j + byte_pos] = (uint8_t)( 78207753Smm instruction 79207753Smm >> (8 * j)); 80207753Smm } 81207753Smm } 82207753Smm } 83207753Smm 84207753Smm return i; 85207753Smm} 86207753Smm 87207753Smm 88207753Smmstatic lzma_ret 89292588Sdelphijia64_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, 90207753Smm const lzma_filter_info *filters, bool is_encoder) 91207753Smm{ 92207753Smm return lzma_simple_coder_init(next, allocator, filters, 93207753Smm &ia64_code, 0, 16, 16, is_encoder); 94207753Smm} 95207753Smm 96207753Smm 97207753Smmextern lzma_ret 98207753Smmlzma_simple_ia64_encoder_init(lzma_next_coder *next, 99292588Sdelphij const lzma_allocator *allocator, 100292588Sdelphij const lzma_filter_info *filters) 101207753Smm{ 102207753Smm return ia64_coder_init(next, allocator, filters, true); 103207753Smm} 104207753Smm 105207753Smm 106207753Smmextern lzma_ret 107207753Smmlzma_simple_ia64_decoder_init(lzma_next_coder *next, 108292588Sdelphij const lzma_allocator *allocator, 109292588Sdelphij const lzma_filter_info *filters) 110207753Smm{ 111207753Smm return ia64_coder_init(next, allocator, filters, false); 112207753Smm} 113