aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/zlib_inflate/inffast.c55
1 files changed, 44 insertions, 11 deletions
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c
index 8550b0c05d00..05e1559fa156 100644
--- a/lib/zlib_inflate/inffast.c
+++ b/lib/zlib_inflate/inffast.c
@@ -4,6 +4,8 @@
4 */ 4 */
5 5
6#include <linux/zutil.h> 6#include <linux/zutil.h>
7#include <asm/unaligned.h>
8#include <asm/byteorder.h>
7#include "inftrees.h" 9#include "inftrees.h"
8#include "inflate.h" 10#include "inflate.h"
9#include "inffast.h" 11#include "inffast.h"
@@ -24,9 +26,11 @@
24#ifdef POSTINC 26#ifdef POSTINC
25# define OFF 0 27# define OFF 0
26# define PUP(a) *(a)++ 28# define PUP(a) *(a)++
29# define UP_UNALIGNED(a) get_unaligned((a)++)
27#else 30#else
28# define OFF 1 31# define OFF 1
29# define PUP(a) *++(a) 32# define PUP(a) *++(a)
33# define UP_UNALIGNED(a) get_unaligned(++(a))
30#endif 34#endif
31 35
32/* 36/*
@@ -239,18 +243,47 @@ void inflate_fast(z_streamp strm, unsigned start)
239 } 243 }
240 } 244 }
241 else { 245 else {
246 unsigned short *sout;
247 unsigned long loops;
248
242 from = out - dist; /* copy direct from output */ 249 from = out - dist; /* copy direct from output */
243 do { /* minimum length is three */ 250 /* minimum length is three */
244 PUP(out) = PUP(from); 251 /* Align out addr */
245 PUP(out) = PUP(from); 252 if (!((long)(out - 1 + OFF) & 1)) {
246 PUP(out) = PUP(from); 253 PUP(out) = PUP(from);
247 len -= 3; 254 len--;
248 } while (len > 2); 255 }
249 if (len) { 256 sout = (unsigned short *)(out - OFF);
250 PUP(out) = PUP(from); 257 if (dist > 2) {
251 if (len > 1) 258 unsigned short *sfrom;
252 PUP(out) = PUP(from); 259
253 } 260 sfrom = (unsigned short *)(from - OFF);
261 loops = len >> 1;
262 do
263 PUP(sout) = UP_UNALIGNED(sfrom);
264 while (--loops);
265 out = (unsigned char *)sout + OFF;
266 from = (unsigned char *)sfrom + OFF;
267 } else { /* dist == 1 or dist == 2 */
268 unsigned short pat16;
269
270 pat16 = *(sout-2+2*OFF);
271 if (dist == 1)
272#if defined(__BIG_ENDIAN)
273 pat16 = (pat16 & 0xff) | ((pat16 & 0xff) << 8);
274#elif defined(__LITTLE_ENDIAN)
275 pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00) >> 8);
276#else
277#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
278#endif
279 loops = len >> 1;
280 do
281 PUP(sout) = pat16;
282 while (--loops);
283 out = (unsigned char *)sout + OFF;
284 }
285 if (len & 1)
286 PUP(out) = PUP(from);
254 } 287 }
255 } 288 }
256 else if ((op & 64) == 0) { /* 2nd level distance code */ 289 else if ((op & 64) == 0) { /* 2nd level distance code */