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