]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/simple/armthumb.c
Imported to git.
[icculus/xz.git] / src / liblzma / simple / armthumb.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       armthumb.c
4 /// \brief      Filter for ARM-Thumb 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 armthumb_code(lzma_simple *simple lzma_attribute((unused)),
26                 uint32_t now_pos, bool is_encoder,
27                 uint8_t *buffer, size_t size)
28 {
29         uint32_t i;
30         for (i = 0; i + 4 <= size; i += 2) {
31                 if ((buffer[i + 1] & 0xF8) == 0xF0
32                                 && (buffer[i + 3] & 0xF8) == 0xF8) {
33                         uint32_t src = ((buffer[i + 1] & 0x7) << 19)
34                                         | (buffer[i + 0] << 11)
35                                         | ((buffer[i + 3] & 0x7) << 8)
36                                         | (buffer[i + 2]);
37
38                         src <<= 1;
39
40                         uint32_t dest;
41                         if (is_encoder)
42                                 dest = now_pos + (uint32_t)(i) + 4 + src;
43                         else
44                                 dest = src - (now_pos + (uint32_t)(i) + 4);
45
46                         dest >>= 1;
47                         buffer[i + 1] = 0xF0 | ((dest >> 19) & 0x7);
48                         buffer[i + 0] = (dest >> 11);
49                         buffer[i + 3] = 0xF8 | ((dest >> 8) & 0x7);
50                         buffer[i + 2] = (dest);
51                         i += 2;
52                 }
53         }
54
55         return i;
56 }
57
58
59 static lzma_ret
60 armthumb_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
61                 const lzma_filter_info *filters, bool is_encoder)
62 {
63         return lzma_simple_coder_init(next, allocator, filters,
64                         &armthumb_code, 0, 4, is_encoder);
65 }
66
67
68 extern lzma_ret
69 lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
70                 lzma_allocator *allocator, const lzma_filter_info *filters)
71 {
72         return armthumb_coder_init(next, allocator, filters, true);
73 }
74
75
76 extern lzma_ret
77 lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
78                 lzma_allocator *allocator, const lzma_filter_info *filters)
79 {
80         return armthumb_coder_init(next, allocator, filters, false);
81 }