diff options
Diffstat (limited to 'lib/zlib_inflate/inffast.c')
-rw-r--r-- | lib/zlib_inflate/inffast.c | 75 |
1 files changed, 68 insertions, 7 deletions
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c index 8550b0c05d00..215447c55261 100644 --- a/lib/zlib_inflate/inffast.c +++ b/lib/zlib_inflate/inffast.c | |||
@@ -8,6 +8,21 @@ | |||
8 | #include "inflate.h" | 8 | #include "inflate.h" |
9 | #include "inffast.h" | 9 | #include "inffast.h" |
10 | 10 | ||
11 | /* Only do the unaligned "Faster" variant when | ||
12 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is set | ||
13 | * | ||
14 | * On powerpc, it won't be as we don't include autoconf.h | ||
15 | * automatically for the boot wrapper, which is intended as | ||
16 | * we run in an environment where we may not be able to deal | ||
17 | * with (even rare) alignment faults. In addition, we do not | ||
18 | * define __KERNEL__ for arch/powerpc/boot unlike x86 | ||
19 | */ | ||
20 | |||
21 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
22 | #include <asm/unaligned.h> | ||
23 | #include <asm/byteorder.h> | ||
24 | #endif | ||
25 | |||
11 | #ifndef ASMINF | 26 | #ifndef ASMINF |
12 | 27 | ||
13 | /* Allow machine dependent optimization for post-increment or pre-increment. | 28 | /* Allow machine dependent optimization for post-increment or pre-increment. |
@@ -24,9 +39,11 @@ | |||
24 | #ifdef POSTINC | 39 | #ifdef POSTINC |
25 | # define OFF 0 | 40 | # define OFF 0 |
26 | # define PUP(a) *(a)++ | 41 | # define PUP(a) *(a)++ |
42 | # define UP_UNALIGNED(a) get_unaligned((a)++) | ||
27 | #else | 43 | #else |
28 | # define OFF 1 | 44 | # define OFF 1 |
29 | # define PUP(a) *++(a) | 45 | # define PUP(a) *++(a) |
46 | # define UP_UNALIGNED(a) get_unaligned(++(a)) | ||
30 | #endif | 47 | #endif |
31 | 48 | ||
32 | /* | 49 | /* |
@@ -239,18 +256,62 @@ void inflate_fast(z_streamp strm, unsigned start) | |||
239 | } | 256 | } |
240 | } | 257 | } |
241 | else { | 258 | else { |
259 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | ||
260 | unsigned short *sout; | ||
261 | unsigned long loops; | ||
262 | |||
263 | from = out - dist; /* copy direct from output */ | ||
264 | /* minimum length is three */ | ||
265 | /* Align out addr */ | ||
266 | if (!((long)(out - 1 + OFF) & 1)) { | ||
267 | PUP(out) = PUP(from); | ||
268 | len--; | ||
269 | } | ||
270 | sout = (unsigned short *)(out - OFF); | ||
271 | if (dist > 2) { | ||
272 | unsigned short *sfrom; | ||
273 | |||
274 | sfrom = (unsigned short *)(from - OFF); | ||
275 | loops = len >> 1; | ||
276 | do | ||
277 | PUP(sout) = UP_UNALIGNED(sfrom); | ||
278 | while (--loops); | ||
279 | out = (unsigned char *)sout + OFF; | ||
280 | from = (unsigned char *)sfrom + OFF; | ||
281 | } else { /* dist == 1 or dist == 2 */ | ||
282 | unsigned short pat16; | ||
283 | |||
284 | pat16 = *(sout-2+2*OFF); | ||
285 | if (dist == 1) | ||
286 | #if defined(__BIG_ENDIAN) | ||
287 | pat16 = (pat16 & 0xff) | ((pat16 & 0xff) << 8); | ||
288 | #elif defined(__LITTLE_ENDIAN) | ||
289 | pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00) >> 8); | ||
290 | #else | ||
291 | #error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined | ||
292 | #endif | ||
293 | loops = len >> 1; | ||
294 | do | ||
295 | PUP(sout) = pat16; | ||
296 | while (--loops); | ||
297 | out = (unsigned char *)sout + OFF; | ||
298 | } | ||
299 | if (len & 1) | ||
300 | PUP(out) = PUP(from); | ||
301 | #else /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ | ||
242 | from = out - dist; /* copy direct from output */ | 302 | from = out - dist; /* copy direct from output */ |
243 | do { /* minimum length is three */ | 303 | do { /* minimum length is three */ |
244 | PUP(out) = PUP(from); | 304 | PUP(out) = PUP(from); |
245 | PUP(out) = PUP(from); | 305 | PUP(out) = PUP(from); |
246 | PUP(out) = PUP(from); | 306 | PUP(out) = PUP(from); |
247 | len -= 3; | 307 | len -= 3; |
248 | } while (len > 2); | 308 | } while (len > 2); |
249 | if (len) { | 309 | if (len) { |
250 | PUP(out) = PUP(from); | 310 | PUP(out) = PUP(from); |
251 | if (len > 1) | 311 | if (len > 1) |
252 | PUP(out) = PUP(from); | 312 | PUP(out) = PUP(from); |
253 | } | 313 | } |
314 | #endif /* !CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ | ||
254 | } | 315 | } |
255 | } | 316 | } |
256 | else if ((op & 64) == 0) { /* 2nd level distance code */ | 317 | else if ((op & 64) == 0) { /* 2nd level distance code */ |