OLD | NEW |
(Empty) | |
| 1 /////////////////////////////////////////////////////////////////////////////// |
| 2 // |
| 3 /// \file ia64.c |
| 4 /// \brief Filter for IA64 (Itanium) binaries |
| 5 /// |
| 6 // Authors: Igor Pavlov |
| 7 // Lasse Collin |
| 8 // |
| 9 // This file has been put into the public domain. |
| 10 // You can do whatever you want with this file. |
| 11 // |
| 12 /////////////////////////////////////////////////////////////////////////////// |
| 13 |
| 14 #include "simple_private.h" |
| 15 |
| 16 |
| 17 static size_t |
| 18 ia64_code(lzma_simple *simple lzma_attribute((unused)), |
| 19 uint32_t now_pos, bool is_encoder, |
| 20 uint8_t *buffer, size_t size) |
| 21 { |
| 22 static const uint32_t BRANCH_TABLE[32] = { |
| 23 0, 0, 0, 0, 0, 0, 0, 0, |
| 24 0, 0, 0, 0, 0, 0, 0, 0, |
| 25 4, 4, 6, 6, 0, 0, 7, 7, |
| 26 4, 4, 0, 0, 4, 4, 0, 0 |
| 27 }; |
| 28 |
| 29 size_t i; |
| 30 for (i = 0; i + 16 <= size; i += 16) { |
| 31 const uint32_t instr_template = buffer[i] & 0x1F; |
| 32 const uint32_t mask = BRANCH_TABLE[instr_template]; |
| 33 uint32_t bit_pos = 5; |
| 34 |
| 35 for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) { |
| 36 if (((mask >> slot) & 1) == 0) |
| 37 continue; |
| 38 |
| 39 const size_t byte_pos = (bit_pos >> 3); |
| 40 const uint32_t bit_res = bit_pos & 0x7; |
| 41 uint64_t instruction = 0; |
| 42 |
| 43 for (size_t j = 0; j < 6; ++j) |
| 44 instruction += (uint64_t)( |
| 45 buffer[i + j + byte_pos]) |
| 46 << (8 * j); |
| 47 |
| 48 uint64_t inst_norm = instruction >> bit_res; |
| 49 |
| 50 if (((inst_norm >> 37) & 0xF) == 0x5 |
| 51 && ((inst_norm >> 9) & 0x7) == 0 |
| 52 /* && (inst_norm & 0x3F)== 0 */ |
| 53 ) { |
| 54 uint32_t src = (uint32_t)( |
| 55 (inst_norm >> 13) & 0xFFFFF); |
| 56 src |= ((inst_norm >> 36) & 1) << 20; |
| 57 |
| 58 src <<= 4; |
| 59 |
| 60 uint32_t dest; |
| 61 if (is_encoder) |
| 62 dest = now_pos + (uint32_t)(i) + src; |
| 63 else |
| 64 dest = src - (now_pos + (uint32_t)(i)); |
| 65 |
| 66 dest >>= 4; |
| 67 |
| 68 inst_norm &= ~((uint64_t)(0x8FFFFF) << 13); |
| 69 inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13; |
| 70 inst_norm |= (uint64_t)(dest & 0x100000) |
| 71 << (36 - 20); |
| 72 |
| 73 instruction &= (1 << bit_res) - 1; |
| 74 instruction |= (inst_norm << bit_res); |
| 75 |
| 76 for (size_t j = 0; j < 6; j++) |
| 77 buffer[i + j + byte_pos] = (uint8_t)( |
| 78 instruction |
| 79 >> (8 * j)); |
| 80 } |
| 81 } |
| 82 } |
| 83 |
| 84 return i; |
| 85 } |
| 86 |
| 87 |
| 88 static lzma_ret |
| 89 ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator, |
| 90 const lzma_filter_info *filters, bool is_encoder) |
| 91 { |
| 92 return lzma_simple_coder_init(next, allocator, filters, |
| 93 &ia64_code, 0, 16, 16, is_encoder); |
| 94 } |
| 95 |
| 96 |
| 97 extern lzma_ret |
| 98 lzma_simple_ia64_encoder_init(lzma_next_coder *next, |
| 99 lzma_allocator *allocator, const lzma_filter_info *filters) |
| 100 { |
| 101 return ia64_coder_init(next, allocator, filters, true); |
| 102 } |
| 103 |
| 104 |
| 105 extern lzma_ret |
| 106 lzma_simple_ia64_decoder_init(lzma_next_coder *next, |
| 107 lzma_allocator *allocator, const lzma_filter_info *filters) |
| 108 { |
| 109 return ia64_coder_init(next, allocator, filters, false); |
| 110 } |
OLD | NEW |