|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly, ! 3: * Kai Uwe Rommel and Igor Mandrichenko. ! 4: * Permission is granted to any individual or institution to use, copy, or ! 5: * redistribute this software so long as all of the original files are included ! 6: * unmodified, that it is not sold for profit, and that this copyright notice ! 7: * is retained. ! 8: * ! 9: * match.s by Jean-loup Gailly. Translated to 32 bit code by Kai Uwe Rommel. ! 10: ! 11: * match.s, optimized version of longest_match() in deflate.c ! 12: * This version is for 386 Unix or OS/2 in 32 bit mode. ! 13: * Warning: it uses the AT&T syntax: mov source,dest ! 14: * This file is only optional. If you want to force the C version, ! 15: * add -DNO_ASM to CFLAGS in makefile and remove match.o from OBJI). ! 16: * If you have reduced WSIZE in zip.h, then change its value below. ! 17: * This version assumes static allocation of the arrays (-DDYN_ALLOC not used). ! 18: */ ! 19: ! 20: .file "zmatch.S" ! 21: ! 22: #ifdef SYSV ! 23: # define _prev prev ! 24: # define _window window ! 25: # define _match_start match_start ! 26: # define _prev_length prev_length ! 27: # define _good_match good_match ! 28: # define _strstart strstart ! 29: # define _max_chain_length max_chain_length ! 30: ! 31: # define _match_init match_init ! 32: # define _longest_match longest_match ! 33: #endif ! 34: ! 35: #define MAX_MATCH 258 ! 36: #define MAX_MATCH2 128 /* MAX_MATCH/2-1 */ ! 37: #define MIN_MATCH 3 ! 38: #define WSIZE 8192 ! 39: #define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1 ! 40: ! 41: .globl _match_init ! 42: .globl _longest_match ! 43: ! 44: .text ! 45: ! 46: _match_init: ! 47: ret ! 48: ! 49: /* ----------------------------------------------------------------------- ! 50: * Set match_start to the longest match starting at the given string and ! 51: * return its length. Matches shorter or equal to prev_length are discarded, ! 52: * in which case the result is equal to prev_length and match_start is ! 53: * garbage. ! 54: * IN assertions: cur_match is the head of the hash chain for the current ! 55: * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 ! 56: */ ! 57: ! 58: _longest_match: /* int longest_match(cur_match) */ ! 59: ! 60: #define cur_match 20(%esp) ! 61: /* return address / esp+16 */ ! 62: push %ebp /* esp+12 */ ! 63: push %edi /* esp+8 */ ! 64: push %esi /* esp+4 */ ! 65: push %ebx /* esp */ ! 66: ! 67: /* match equ esi ! 68: * scan equ edi ! 69: * chain_length equ ebp ! 70: * best_len equ ebx ! 71: * limit equ edx ! 72: */ ! 73: ! 74: mov cur_match,%esi ! 75: mov _max_chain_length,%ebp /* chain_length = max_chain_length */ ! 76: mov _strstart,%edi ! 77: mov %edi,%edx ! 78: sub $ MAX_DIST,%edx /* limit = strstart-MAX_DIST */ ! 79: jae limit_ok ! 80: sub %edx,%edx /* limit = NIL */ ! 81: limit_ok: ! 82: add $_window+2,%edi /* edi = offset(window + strstart + 2) */ ! 83: mov _prev_length,%ebx /* best_len = prev_length */ ! 84: movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */ ! 85: movw -2(%edi),%cx /* cx = scan[0..1] */ ! 86: cmp _good_match,%ebx /* do we have a good match already? */ ! 87: jb do_scan ! 88: shr $2,%ebp /* chain_length >>= 2 */ ! 89: jmp do_scan ! 90: ! 91: .align 4 ! 92: long_loop: ! 93: /* at this point, edi == scan+2, esi == cur_match */ ! 94: movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */ ! 95: movw -2(%edi),%cx /* cx = scan[0..1] */ ! 96: short_loop: ! 97: dec %ebp /* --chain_length */ ! 98: jz the_end ! 99: /* at this point, di == scan+2, si == cur_match, ! 100: * ax = scan[best_len-1..best_len] and cx = scan[0..1] ! 101: */ ! 102: and $ WSIZE-1, %esi ! 103: movw _prev(%esi,%esi),%si /* cur_match = prev[cur_match] */ ! 104: /* top word of esi is still 0 */ ! 105: cmp %edx,%esi /* cur_match <= limit ? */ ! 106: jbe the_end ! 107: do_scan: ! 108: cmpw _window-1(%ebx,%esi),%ax/*check match at best_len-1 */ ! 109: jne short_loop ! 110: cmpw _window(%esi),%cx /* check min_match_length match */ ! 111: jne short_loop ! 112: ! 113: lea _window+2(%esi),%esi /* si = match */ ! 114: mov %edi,%eax /* ax = scan+2 */ ! 115: mov $ MAX_MATCH2,%ecx /* scan for at most MAX_MATCH bytes */ ! 116: #ifdef SYSV ! 117: repz; cmpsw /* loop until mismatch */ ! 118: #else ! 119: repe; cmpsw ! 120: #endif ! 121: je maxmatch /* match of length MAX_MATCH? */ ! 122: mismatch: ! 123: movb -2(%edi),%cl /* mismatch on first or second byte? */ ! 124: subb -2(%esi),%cl /* cl = 0 if first bytes equal */ ! 125: xchg %edi,%eax /* edi = scan+2, eax = end of scan */ ! 126: sub %edi,%eax /* eax = len */ ! 127: sub %eax,%esi /* esi = cur_match + 2 + offset(window) */ ! 128: sub $_window+2,%esi /* esi = cur_match */ ! 129: subb $1,%cl /* set carry if cl == 0 (cannot use DEC) */ ! 130: adc $0,%eax /* eax = carry ? len+1 : len */ ! 131: cmp %ebx,%eax /* len > best_len ? */ ! 132: jle long_loop ! 133: mov %esi,_match_start /* match_start = cur_match */ ! 134: mov %eax,%ebx /* ebx = best_len = len */ ! 135: cmp $ MAX_MATCH,%eax /* len >= MAX_MATCH ? */ ! 136: jl long_loop ! 137: the_end: ! 138: mov %ebx,%eax /* result = eax = best_len */ ! 139: pop %ebx ! 140: pop %esi ! 141: pop %edi ! 142: pop %ebp ! 143: ret ! 144: maxmatch: ! 145: cmpsb ! 146: jmp mismatch
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.