]> git.sur5r.net Git - u-boot/blobdiff - lib_generic/zlib.c
TWL4030 Add usb PHY support
[u-boot] / lib_generic / zlib.c
index 1b6db3214e9c98cce1903198fba907808b8e42c1..26e5af1d8e84bfa74fee86b90adb5d4cbed4b40b 100644 (file)
 #define ZUTIL_H
 #define ZLIB_INTERNAL
 
+#include <common.h>
+#include <compiler.h>
+#include <asm/unaligned.h>
 #include "u-boot/zlib.h"
+#undef OFF                             /* avoid conflicts */
+
 /* To avoid a build time warning */
 #ifdef STDC
 #include <malloc.h>
@@ -83,10 +88,10 @@ typedef unsigned long ulg;
 
 /* Diagnostic functions */
 #ifdef DEBUG
-#include <stdio.h>
        extern int z_verbose;
        extern void z_error    OF((char *m));
 #define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#define fprintf(fp,...)        printf(__VA_ARGS__)
 #define Trace(x) {if (z_verbose>=0) fprintf x ;}
 #define Tracev(x) {if (z_verbose>0) fprintf x ;}
 #define Tracevv(x) {if (z_verbose>1) fprintf x ;}
@@ -399,6 +404,7 @@ void inflate_fast OF((z_streamp strm, unsigned start));
  */
 #define OFF 1
 #define PUP(a) *++(a)
+#define UP_UNALIGNED(a) get_unaligned(++(a))
 
 /*
    Decode literal, length, and distance codes and write out the resulting
@@ -615,18 +621,47 @@ unsigned start;         /* inflate()'s starting value for strm->avail_out */
                     }
                 }
                 else {
+                   unsigned short *sout;
+                   unsigned long loops;
+
                     from = out - dist;          /* copy direct from output */
-                    do {                        /* minimum length is three */
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        PUP(out) = PUP(from);
-                        len -= 3;
-                    } while (len > 2);
-                    if (len) {
-                        PUP(out) = PUP(from);
-                        if (len > 1)
-                            PUP(out) = PUP(from);
-                    }
+                    /* minimum length is three */
+                   /* Align out addr */
+                   if (!((long)(out - 1 + OFF) & 1)) {
+                       PUP(out) = PUP(from);
+                       len--;
+                   }
+                   sout = (unsigned short *)(out - OFF);
+                   if (dist > 2 ) {
+                       unsigned short *sfrom;
+
+                       sfrom = (unsigned short *)(from - OFF);
+                       loops = len >> 1;
+                       do
+                           PUP(sout) = UP_UNALIGNED(sfrom);
+                       while (--loops);
+                       out = (unsigned char *)sout + OFF;
+                       from = (unsigned char *)sfrom + OFF;
+                   } else { /* dist == 1 or dist == 2 */
+                       unsigned short pat16;
+
+                       pat16 = *(sout-2+2*OFF);
+                       if (dist == 1)
+#if defined(__BIG_ENDIAN)
+                           pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8);
+#elif defined(__LITTLE_ENDIAN)
+                           pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00 ) >> 8);
+#else
+#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined
+#endif
+                       loops = len >> 1;
+                       do
+                           PUP(sout) = pat16;
+                       while (--loops);
+                       out = (unsigned char *)sout + OFF;
+                   }
+                   if (len & 1)
+                       PUP(out) = PUP(from);
                 }
             }
             else if ((op & 64) == 0) {          /* 2nd level distance code */
@@ -2000,7 +2035,7 @@ void z_error (m)
     char *m;
 {
        fprintf(stderr, "%s\n", m);
-       exit(1);
+       hang ();
 }
 #endif