diff options
Diffstat (limited to 'lib/zlib_inflate/inffast.c')
-rw-r--r-- | lib/zlib_inflate/inffast.c | 73 |
1 files changed, 62 insertions, 11 deletions
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c index 8550b0c05d00..2c13ecc5bb2c 100644 --- a/lib/zlib_inflate/inffast.c +++ b/lib/zlib_inflate/inffast.c | |||
@@ -21,12 +21,31 @@ | |||
21 | - Pentium III (Anderson) | 21 | - Pentium III (Anderson) |
22 | - M68060 (Nikl) | 22 | - M68060 (Nikl) |
23 | */ | 23 | */ |
24 | union uu { | ||
25 | unsigned short us; | ||
26 | unsigned char b[2]; | ||
27 | }; | ||
28 | |||
29 | /* Endian independed version */ | ||
30 | static inline unsigned short | ||
31 | get_unaligned16(const unsigned short *p) | ||
32 | { | ||
33 | union uu mm; | ||
34 | unsigned char *b = (unsigned char *)p; | ||
35 | |||
36 | mm.b[0] = b[0]; | ||
37 | mm.b[1] = b[1]; | ||
38 | return mm.us; | ||
39 | } | ||
40 | |||
24 | #ifdef POSTINC | 41 | #ifdef POSTINC |
25 | # define OFF 0 | 42 | # define OFF 0 |
26 | # define PUP(a) *(a)++ | 43 | # define PUP(a) *(a)++ |
44 | # define UP_UNALIGNED(a) get_unaligned16((a)++) | ||
27 | #else | 45 | #else |
28 | # define OFF 1 | 46 | # define OFF 1 |
29 | # define PUP(a) *++(a) | 47 | # define PUP(a) *++(a) |
48 | # define UP_UNALIGNED(a) get_unaligned16(++(a)) | ||
30 | #endif | 49 | #endif |
31 | 50 | ||
32 | /* | 51 | /* |
@@ -239,18 +258,50 @@ void inflate_fast(z_streamp strm, unsigned start) | |||
239 | } | 258 | } |
240 | } | 259 | } |
241 | else { | 260 | else { |
261 | unsigned short *sout; | ||
262 | unsigned long loops; | ||
263 | |||
242 | from = out - dist; /* copy direct from output */ | 264 | from = out - dist; /* copy direct from output */ |
243 | do { /* minimum length is three */ | 265 | /* minimum length is three */ |
244 | PUP(out) = PUP(from); | 266 | /* Align out addr */ |
245 | PUP(out) = PUP(from); | 267 | if (!((long)(out - 1 + OFF) & 1)) { |
246 | PUP(out) = PUP(from); | 268 | PUP(out) = PUP(from); |
247 | len -= 3; | 269 | len--; |
248 | } while (len > 2); | 270 | } |
249 | if (len) { | 271 | sout = (unsigned short *)(out - OFF); |
250 | PUP(out) = PUP(from); | 272 | if (dist > 2) { |
251 | if (len > 1) | 273 | unsigned short *sfrom; |
252 | PUP(out) = PUP(from); | 274 | |
253 | } | 275 | sfrom = (unsigned short *)(from - OFF); |
276 | loops = len >> 1; | ||
277 | do | ||
278 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
279 | PUP(sout) = PUP(sfrom); | ||
280 | #else | ||
281 | PUP(sout) = UP_UNALIGNED(sfrom); | ||
282 | #endif | ||
283 | while (--loops); | ||
284 | out = (unsigned char *)sout + OFF; | ||
285 | from = (unsigned char *)sfrom + OFF; | ||
286 | } else { /* dist == 1 or dist == 2 */ | ||
287 | unsigned short pat16; | ||
288 | |||
289 | pat16 = *(sout-1+OFF); | ||
290 | if (dist == 1) { | ||
291 | union uu mm; | ||
292 | /* copy one char pattern to both bytes */ | ||
293 | mm.us = pat16; | ||
294 | mm.b[0] = mm.b[1]; | ||
295 | pat16 = mm.us; | ||
296 | } | ||
297 | loops = len >> 1; | ||
298 | do | ||
299 | PUP(sout) = pat16; | ||
300 | while (--loops); | ||
301 | out = (unsigned char *)sout + OFF; | ||
302 | } | ||
303 | if (len & 1) | ||
304 | PUP(out) = PUP(from); | ||
254 | } | 305 | } |
255 | } | 306 | } |
256 | else if ((op & 64) == 0) { /* 2nd level distance code */ | 307 | else if ((op & 64) == 0) { /* 2nd level distance code */ |