]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/simple/ia64.c
Imported to git.
[icculus/xz.git] / src / liblzma / simple / ia64.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       ia64.c
4 /// \brief      Filter for IA64 (Itanium) binaries
5 //
6 //  Copyright (C) 1999-2006 Igor Pavlov
7 //  Copyright (C) 2007 Lasse Collin
8 //
9 //  This library is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU Lesser General Public
11 //  License as published by the Free Software Foundation; either
12 //  version 2.1 of the License, or (at your option) any later version.
13 //
14 //  This library is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //  Lesser General Public License for more details.
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20
21 #include "simple_private.h"
22
23
24 static size_t
25 ia64_code(lzma_simple *simple lzma_attribute((unused)),
26                 uint32_t now_pos, bool is_encoder,
27                 uint8_t *buffer, size_t size)
28 {
29         static const uint32_t BRANCH_TABLE[32] = {
30                 0, 0, 0, 0, 0, 0, 0, 0,
31                 0, 0, 0, 0, 0, 0, 0, 0,
32                 4, 4, 6, 6, 0, 0, 7, 7,
33                 4, 4, 0, 0, 4, 4, 0, 0
34         };
35
36         size_t i;
37         for (i = 0; i + 16 <= size; i += 16) {
38                 const uint32_t instr_template = buffer[i] & 0x1F;
39                 const uint32_t mask = BRANCH_TABLE[instr_template];
40                 uint32_t bit_pos = 5;
41
42                 for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) {
43                         if (((mask >> slot) & 1) == 0)
44                                 continue;
45
46                         const size_t byte_pos = (bit_pos >> 3);
47                         const uint32_t bit_res = bit_pos & 0x7;
48                         uint64_t instruction = 0;
49
50                         for (size_t j = 0; j < 6; ++j)
51                                 instruction += (uint64_t)(
52                                                 buffer[i + j + byte_pos])
53                                                 << (8 * j);
54
55                         uint64_t inst_norm = instruction >> bit_res;
56
57                         if (((inst_norm >> 37) & 0xF) == 0x5
58                                         && ((inst_norm >> 9) & 0x7) == 0
59                                         /* &&  (inst_norm & 0x3F)== 0 */
60                                         ) {
61                                 uint32_t src = (uint32_t)(
62                                                 (inst_norm >> 13) & 0xFFFFF);
63                                 src |= ((inst_norm >> 36) & 1) << 20;
64
65                                 src <<= 4;
66
67                                 uint32_t dest;
68                                 if (is_encoder)
69                                         dest = now_pos + (uint32_t)(i) + src;
70                                 else
71                                         dest = src - (now_pos + (uint32_t)(i));
72
73                                 dest >>= 4;
74
75                                 inst_norm &= ~((uint64_t)(0x8FFFFF) << 13);
76                                 inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13;
77                                 inst_norm |= (uint64_t)(dest & 0x100000)
78                                                 << (36 - 20);
79
80                                 instruction &= (1 << bit_res) - 1;
81                                 instruction |= (inst_norm << bit_res);
82
83                                 for (size_t j = 0; j < 6; j++)
84                                         buffer[i + j + byte_pos] = (uint8_t)(
85                                                         instruction
86                                                         >> (8 * j));
87                         }
88                 }
89         }
90
91         return i;
92 }
93
94
95 static lzma_ret
96 ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
97                 const lzma_filter_info *filters, bool is_encoder)
98 {
99         return lzma_simple_coder_init(next, allocator, filters,
100                         &ia64_code, 0, 4, is_encoder);
101 }
102
103
104 extern lzma_ret
105 lzma_simple_ia64_encoder_init(lzma_next_coder *next,
106                 lzma_allocator *allocator, const lzma_filter_info *filters)
107 {
108         return ia64_coder_init(next, allocator, filters, true);
109 }
110
111
112 extern lzma_ret
113 lzma_simple_ia64_decoder_init(lzma_next_coder *next,
114                 lzma_allocator *allocator, const lzma_filter_info *filters)
115 {
116         return ia64_coder_init(next, allocator, filters, false);
117 }