2 * LZO1X Compressor from LZO
4 * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
6 * The full LZO package can be found at:
7 * http://www.oberhumer.com/opensource/lzo/
9 * Changed for Linux kernel use by:
10 * Nitin Gupta <nitingupta910@gmail.com>
11 * Richard Purdie <rpurdie@openedhand.com>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <asm/unaligned.h>
17 #include <linux/lzo.h>
20 static noinline
size_t
21 lzo1x_1_do_compress(const unsigned char *in
, size_t in_len
,
22 unsigned char *out
, size_t *out_len
,
23 size_t ti
, void *wrkmem
)
25 const unsigned char *ip
;
27 const unsigned char * const in_end
= in
+ in_len
;
28 const unsigned char * const ip_end
= in
+ in_len
- 20;
29 const unsigned char *ii
;
30 lzo_dict_t
* const dict
= (lzo_dict_t
*) wrkmem
;
35 ip
+= ti
< 4 ? 4 - ti
: 0;
38 const unsigned char *m_pos
;
39 size_t t
, m_len
, m_off
;
42 ip
+= 1 + ((ip
- ii
) >> 5);
44 if (unlikely(ip
>= ip_end
))
46 dv
= get_unaligned_le32(ip
);
47 t
= ((dv
* 0x1824429d) >> (32 - D_BITS
)) & D_MASK
;
49 dict
[t
] = (lzo_dict_t
) (ip
- in
);
50 if (unlikely(dv
!= get_unaligned_le32(m_pos
)))
64 COPY8(op
+ 8, ii
+ 8);
72 while (unlikely(tt
> 255)) {
80 COPY8(op
+ 8, ii
+ 8);
93 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
95 v
= get_unaligned((const u64
*) (ip
+ m_len
)) ^
96 get_unaligned((const u64
*) (m_pos
+ m_len
));
97 if (unlikely(v
== 0)) {
100 v
= get_unaligned((const u64
*) (ip
+ m_len
)) ^
101 get_unaligned((const u64
*) (m_pos
+ m_len
));
102 if (unlikely(ip
+ m_len
>= ip_end
))
106 # if defined(__LITTLE_ENDIAN)
107 m_len
+= (unsigned) __builtin_ctzll(v
) / 8;
108 # elif defined(__BIG_ENDIAN)
109 m_len
+= (unsigned) __builtin_clzll(v
) / 8;
111 # error "missing endian definition"
113 #elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
115 v
= get_unaligned((const u32
*) (ip
+ m_len
)) ^
116 get_unaligned((const u32
*) (m_pos
+ m_len
));
117 if (unlikely(v
== 0)) {
120 v
= get_unaligned((const u32
*) (ip
+ m_len
)) ^
121 get_unaligned((const u32
*) (m_pos
+ m_len
));
125 v
= get_unaligned((const u32
*) (ip
+ m_len
)) ^
126 get_unaligned((const u32
*) (m_pos
+ m_len
));
127 if (unlikely(ip
+ m_len
>= ip_end
))
131 # if defined(__LITTLE_ENDIAN)
132 m_len
+= (unsigned) __builtin_ctz(v
) / 8;
133 # elif defined(__BIG_ENDIAN)
134 m_len
+= (unsigned) __builtin_clz(v
) / 8;
136 # error "missing endian definition"
139 if (unlikely(ip
[m_len
] == m_pos
[m_len
])) {
142 if (ip
[m_len
] != m_pos
[m_len
])
145 if (ip
[m_len
] != m_pos
[m_len
])
148 if (ip
[m_len
] != m_pos
[m_len
])
151 if (ip
[m_len
] != m_pos
[m_len
])
154 if (ip
[m_len
] != m_pos
[m_len
])
157 if (ip
[m_len
] != m_pos
[m_len
])
160 if (ip
[m_len
] != m_pos
[m_len
])
163 if (unlikely(ip
+ m_len
>= ip_end
))
165 } while (ip
[m_len
] == m_pos
[m_len
]);
174 if (m_len
<= M2_MAX_LEN
&& m_off
<= M2_MAX_OFFSET
) {
176 *op
++ = (((m_len
- 1) << 5) | ((m_off
& 7) << 2));
177 *op
++ = (m_off
>> 3);
178 } else if (m_off
<= M3_MAX_OFFSET
) {
180 if (m_len
<= M3_MAX_LEN
)
181 *op
++ = (M3_MARKER
| (m_len
- 2));
184 *op
++ = M3_MARKER
| 0;
185 while (unlikely(m_len
> 255)) {
191 *op
++ = (m_off
<< 2);
192 *op
++ = (m_off
>> 6);
195 if (m_len
<= M4_MAX_LEN
)
196 *op
++ = (M4_MARKER
| ((m_off
>> 11) & 8)
200 *op
++ = (M4_MARKER
| ((m_off
>> 11) & 8));
201 while (unlikely(m_len
> 255)) {
207 *op
++ = (m_off
<< 2);
208 *op
++ = (m_off
>> 6);
213 return in_end
- (ii
- ti
);
216 int lzo1x_1_compress(const unsigned char *in
, size_t in_len
,
217 unsigned char *out
, size_t *out_len
,
220 const unsigned char *ip
= in
;
221 unsigned char *op
= out
;
226 size_t ll
= l
<= (M4_MAX_OFFSET
+ 1) ? l
: (M4_MAX_OFFSET
+ 1);
227 uintptr_t ll_end
= (uintptr_t) ip
+ ll
;
228 if ((ll_end
+ ((t
+ ll
) >> 5)) <= ll_end
)
230 BUILD_BUG_ON(D_SIZE
* sizeof(lzo_dict_t
) > LZO1X_1_MEM_COMPRESS
);
231 memset(wrkmem
, 0, D_SIZE
* sizeof(lzo_dict_t
));
232 t
= lzo1x_1_do_compress(ip
, ll
, op
, out_len
, t
, wrkmem
);
240 const unsigned char *ii
= in
+ in_len
- t
;
242 if (op
== out
&& t
<= 238) {
246 } else if (t
<= 18) {
259 COPY8(op
+ 8, ii
+ 8);
269 *op
++ = M4_MARKER
| 1;
276 EXPORT_SYMBOL_GPL(lzo1x_1_compress
);
278 MODULE_LICENSE("GPL");
279 MODULE_DESCRIPTION("LZO1X-1 Compressor");