home *** CD-ROM | disk | FTP | other *** search
/ Freelog 11 / Freelog011.iso / Bas / Compression / ZLib / contrib / asm386 / gvmat32c.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  7KB  |  201 lines

  1. /* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
  2.  * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
  3.  * File written by Gilles Vollant, by modifiying the longest_match
  4.  *  from Jean-loup Gailly in deflate.c
  5.  *  it prepare all parameters and call the assembly longest_match_gvasm
  6.  *  longest_match execute standard C code is wmask != 0x7fff
  7.  *     (assembly code is faster with a fixed wmask)
  8.  *
  9.  */
  10.  
  11. #include "deflate.h"
  12.  
  13. #undef FAR
  14. #include <windows.h>
  15.  
  16. #ifdef ASMV
  17. #define NIL 0
  18.  
  19. #define UNALIGNED_OK
  20.  
  21.  
  22. /* if your C compiler don't add underline before function name,
  23.         define ADD_UNDERLINE_ASMFUNC */
  24. #ifdef ADD_UNDERLINE_ASMFUNC
  25. #define longest_match_7fff _longest_match_7fff
  26. #endif
  27.  
  28.  
  29.  
  30. void match_init()
  31. {
  32. }
  33.  
  34. unsigned long cpudetect32();
  35.  
  36. uInt longest_match_c(
  37.     deflate_state *s,
  38.     IPos cur_match);                             /* current match */
  39.  
  40.  
  41. uInt longest_match_7fff(
  42.     deflate_state *s,
  43.     IPos cur_match);                             /* current match */
  44.  
  45. uInt longest_match(
  46.     deflate_state *s,
  47.     IPos cur_match)                             /* current match */
  48. {
  49.     static uInt iIsPPro=2;
  50.  
  51.     if ((s->w_mask == 0x7fff) && (iIsPPro==0))
  52.         return longest_match_7fff(s,cur_match);
  53.  
  54.     if (iIsPPro==2)
  55.         iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
  56.  
  57.     return longest_match_c(s,cur_match);
  58. }
  59.  
  60.  
  61.  
  62. uInt longest_match_c(s, cur_match)
  63.     deflate_state *s;
  64.     IPos cur_match;                             /* current match */
  65. {
  66.     unsigned chain_length = s->max_chain_length;/* max hash chain length */
  67.     register Bytef *scan = s->window + s->strstart; /* current string */
  68.     register Bytef *match;                       /* matched string */
  69.     register int len;                           /* length of current match */
  70.     int best_len = s->prev_length;              /* best match length so far */
  71.     int nice_match = s->nice_match;             /* stop if match long enough */
  72.     IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
  73.         s->strstart - (IPos)MAX_DIST(s) : NIL;
  74.     /* Stop when cur_match becomes <= limit. To simplify the code,
  75.      * we prevent matches with the string of window index 0.
  76.      */
  77.     Posf *prev = s->prev;
  78.     uInt wmask = s->w_mask;
  79.  
  80. #ifdef UNALIGNED_OK
  81.     /* Compare two bytes at a time. Note: this is not always beneficial.
  82.      * Try with and without -DUNALIGNED_OK to check.
  83.      */
  84.     register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
  85.     register ush scan_start = *(ushf*)scan;
  86.     register ush scan_end   = *(ushf*)(scan+best_len-1);
  87. #else
  88.     register Bytef *strend = s->window + s->strstart + MAX_MATCH;
  89.     register Byte scan_end1  = scan[best_len-1];
  90.     register Byte scan_end   = scan[best_len];
  91. #endif
  92.  
  93.     /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
  94.      * It is easy to get rid of this optimization if necessary.
  95.      */
  96.     Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
  97.  
  98.     /* Do not waste too much time if we already have a good match: */
  99.     if (s->prev_length >= s->good_match) {
  100.         chain_length >>= 2;
  101.     }
  102.     /* Do not look for matches beyond the end of the input. This is necessary
  103.      * to make deflate deterministic.
  104.      */
  105.     if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
  106.  
  107.     Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
  108.  
  109.     do {
  110.         Assert(cur_match < s->strstart, "no future");
  111.         match = s->window + cur_match;
  112.  
  113.         /* Skip to next match if the match length cannot increase
  114.          * or if the match length is less than 2:
  115.          */
  116. #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
  117.         /* This code assumes sizeof(unsigned short) == 2. Do not use
  118.          * UNALIGNED_OK if your compiler uses a different size.
  119.          */
  120.         if (*(ushf*)(match+best_len-1) != scan_end ||
  121.             *(ushf*)match != scan_start) continue;
  122.  
  123.         /* It is not necessary to compare scan[2] and match[2] since they are
  124.          * always equal when the other bytes match, given that the hash keys
  125.          * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
  126.          * strstart+3, +5, ... up to strstart+257. We check for insufficient
  127.          * lookahead only every 4th comparison; the 128th check will be made
  128.          * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
  129.          * necessary to put more guard bytes at the end of the window, or
  130.          * to check more often for insufficient lookahead.
  131.          */
  132.         Assert(scan[2] == match[2], "scan[2]?");
  133.         scan++, match++;
  134.         do {
  135.         } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
  136.                  *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
  137.                  *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
  138.                  *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
  139.                  scan < strend);
  140.         /* The funny "do {}" generates better code on most compilers */
  141.  
  142.         /* Here, scan <= window+strstart+257 */
  143.         Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
  144.         if (*scan == *match) scan++;
  145.  
  146.         len = (MAX_MATCH - 1) - (int)(strend-scan);
  147.         scan = strend - (MAX_MATCH-1);
  148.  
  149. #else /* UNALIGNED_OK */
  150.  
  151.         if (match[best_len]   != scan_end  ||
  152.             match[best_len-1] != scan_end1 ||
  153.             *match            != *scan     ||
  154.             *++match          != scan[1])      continue;
  155.  
  156.         /* The check at best_len-1 can be removed because it will be made
  157.          * again later. (This heuristic is not always a win.)
  158.          * It is not necessary to compare scan[2] and match[2] since they
  159.          * are always equal when the other bytes match, given that
  160.          * the hash keys are equal and that HASH_BITS >= 8.
  161.          */
  162.         scan += 2, match++;
  163.         Assert(*scan == *match, "match[2]?");
  164.  
  165.         /* We check for insufficient lookahead only every 8th comparison;
  166.          * the 256th check will be made at strstart+258.
  167.          */
  168.         do {
  169.         } while (*++scan == *++match && *++scan == *++match &&
  170.                  *++scan == *++match && *++scan == *++match &&
  171.                  *++scan == *++match && *++scan == *++match &&
  172.                  *++scan == *++match && *++scan == *++match &&
  173.                  scan < strend);
  174.  
  175.         Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
  176.  
  177.         len = MAX_MATCH - (int)(strend - scan);
  178.         scan = strend - MAX_MATCH;
  179.  
  180. #endif /* UNALIGNED_OK */
  181.  
  182.         if (len > best_len) {
  183.             s->match_start = cur_match;
  184.             best_len = len;
  185.             if (len >= nice_match) break;
  186. #ifdef UNALIGNED_OK
  187.             scan_end = *(ushf*)(scan+best_len-1);
  188. #else
  189.             scan_end1  = scan[best_len-1];
  190.             scan_end   = scan[best_len];
  191. #endif
  192.         }
  193.     } while ((cur_match = prev[cur_match & wmask]) > limit
  194.              && --chain_length != 0);
  195.  
  196.     if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
  197.     return s->lookahead;
  198. }
  199.  
  200. #endif /* ASMV */
  201.