Annotation of pgp/src/zmatch.asm, revision 1.1.1.3

1.1.1.3 ! root        1: ;
        !             2: ; Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
        !             3: ; Permission is granted to any individual or institution to use, copy, or
        !             4: ; redistribute this software so long as all of the original files are included
        !             5: ; unmodified, that it is not sold for profit, and that this copyright notice
        !             6: ; is retained.
        !             7: ;
        !             8: ; match.asm by Jean-loup Gailly.
        !             9: 
        !            10: ; match.asm, optimized version of longest_match() in deflate.c
        !            11: ; Must be assembled with masm -ml. To be used only with C large model.
        !            12: ; (For compact model, follow the instructions given below.)
        !            13: ; This file is only optional. If you don't have masm or tasm, use the
        !            14: ; C version (add -DNO_ASM to CFLAGS in makefile.msc and remove match.obj
        !            15: ; from OBJI). If you have reduced WSIZE in zip.h, then change its value
        !            16: ; below.
        !            17: ;
        !            18: ; Turbo C 2.0 does not support static allocation of more than 64K bytes per
        !            19: ; file, and does not have SS == DS. So TC and BC++ users must use:
        !            20: ;   tasm -ml -DDYN_ALLOC -DSS_NEQ_DS match;
        !            21: ;
        !            22: ; To simplify the code, the option -DDYN_ALLOC is supported for OS/2
        !            23: ; only if the arrays are guaranteed to have zero offset (allocated by
        !            24: ; halloc). We also require SS==DS. This is satisfied for MSC but not Turbo C.
        !            25: 
        !            26:         name    match
        !            27: 
        !            28: ; define LCODE as follows:
        !            29: ; model:        compact large (small and medium not supported here)
        !            30: ; LCODE           0       1
        !            31: 
        !            32: LCODE equ 1
        !            33: ; Better define them on the command line
        !            34: ;DYN_ALLOC equ 1
        !            35: ;SS_NEQ_DS equ 1
        !            36: ; For Turbo C, define SS_NEQ_DS as 1, but for MSC you can leave it undefined.
        !            37: ; The code is a little better when SS_NEQ_DS is not defined.
        !            38: 
        !            39: ifndef DYN_ALLOC
        !            40:         extrn   _prev         : word
        !            41:         extrn   _window       : byte
        !            42:         prev    equ  _prev    ; offset part
        !            43:         window  equ  _window
        !            44: endif
        !            45: 
        !            46: _DATA    segment  word public 'DATA'
        !            47:         extrn   _match_start  : word
        !            48:         extrn   _prev_length  : word
        !            49:         extrn   _good_match   : word
        !            50:         extrn   _strstart     : word
        !            51:         extrn   _max_chain_length : word
        !            52: ifdef DYN_ALLOC
        !            53:         extrn   _prev         : word
        !            54:         extrn   _window       : word
        !            55:         prev    equ 0         ; offset forced to zero
        !            56:         window  equ 0
        !            57:         window_seg equ _window[2]
        !            58:        window_off equ 0
        !            59: else
        !            60:        wseg    dw seg _window
        !            61:         window_seg equ wseg
        !            62:        window_off equ offset _window
        !            63: endif
        !            64: _DATA    ends
        !            65: 
        !            66: DGROUP  group _DATA
        !            67: 
        !            68: if LCODE
        !            69:        extrn   _exit : far
        !            70: else
        !            71:        extrn   _exit : near
        !            72: endif
        !            73: 
        !            74: _TEXT   segment word public 'CODE'
        !            75:         assume  cs: _TEXT, ds: DGROUP
        !            76: 
        !            77:        public _match_init
        !            78:         public _longest_match
        !            79: 
        !            80:        MIN_MATCH     equ 3
        !            81:         MAX_MATCH     equ 258
        !            82:        WSIZE         equ 8192          ; keep in sync with zip.h !
        !            83:        WMASK         equ (WSIZE-1)
        !            84:        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
        !            85:        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)
        !            86: 
        !            87: prev_ptr    dw  seg _prev              ; pointer to the prev array
        !            88: ifdef SS_NEQ_DS
        !            89:     match_start dw  0                  ; copy of _match_start if SS != DS
        !            90: endif
        !            91: 
        !            92: ; initialize or check the variables used in match.asm.
        !            93: 
        !            94: if LCODE
        !            95: _match_init proc far
        !            96: else
        !            97: _match_init proc near
        !            98: endif
        !            99: ifdef SS_NEQ_DS
        !           100:         ma_start equ cs:match_start    ; does not work on OS/2
        !           101: else
        !           102:        assume ss: DGROUP
        !           103:         ma_start equ ss:_match_start
        !           104:         mov     ax,ds
        !           105:         mov     bx,ss
        !           106:         cmp     ax,bx                   ; SS == DS?
        !           107:         jne     error
        !           108: endif
        !           109: ifdef DYN_ALLOC
        !           110:        mov     ax,_window[0]           ; force zero offset
        !           111:        add     ax,15
        !           112:        mov     cx,4
        !           113:        shr     ax,cl
        !           114:        add     _window[2],ax
        !           115:        mov     _window[0],0
        !           116: 
        !           117:        mov     ax,_prev[0]             ; force zero offset
        !           118:        add     ax,15
        !           119:        mov     cx,4
        !           120:        shr     ax,cl
        !           121:        add     _prev[2],ax
        !           122:        mov     _prev[0],0
        !           123:   ifdef SS_NEQ_DS
        !           124:        mov     ax,_prev[2]             ; segment value
        !           125:        mov     cs:prev_ptr,ax          ; ugly write to code, crash on OS/2
        !           126:         prev_seg  equ cs:prev_ptr
        !           127:   else
        !           128:         prev_seg  equ ss:_prev[2]      ; works on OS/2 if SS == DS
        !           129:   endif
        !           130: else
        !           131:         prev_seg  equ cs:prev_ptr
        !           132: endif
        !           133:        ret
        !           134: error:  call    _exit
        !           135: 
        !           136: _match_init endp
        !           137: 
        !           138: ; -----------------------------------------------------------------------
        !           139: ; Set match_start to the longest match starting at the given string and
        !           140: ; return its length. Matches shorter or equal to prev_length are discarded,
        !           141: ; in which case the result is equal to prev_length and match_start is
        !           142: ; garbage.
        !           143: ; IN assertions: cur_match is the head of the hash chain for the current
        !           144: ;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
        !           145: 
        !           146: ; int longest_match(cur_match)
        !           147: 
        !           148: if LCODE
        !           149: _longest_match  proc far
        !           150: else
        !           151: _longest_match  proc near
        !           152: endif
        !           153:         push    bp
        !           154:         mov     bp,sp
        !           155:         push    di
        !           156:        push    si
        !           157:        push    ds
        !           158: 
        !           159: if LCODE
        !           160:         cur_match    equ word ptr [bp+6]
        !           161: else
        !           162:         cur_match    equ word ptr [bp+4]
        !           163: endif
        !           164: ;       window      equ es:window (es:0 for DYN_ALLOC)
        !           165: ;       prev        equ ds:prev
        !           166: ;       match        equ es:si
        !           167: ;       scan         equ es:di
        !           168: ;       chain_length equ bp
        !           169: ;       best_len     equ bx
        !           170: ;       limit        equ dx
        !           171: 
        !           172:        mov     si,cur_match            ; use bp before it is destroyed
        !           173:         mov     bp,_max_chain_length    ; chain_length = max_chain_length
        !           174:        mov     di,_strstart
        !           175:        mov     dx,di
        !           176:        sub     dx,MAX_DIST             ; limit = strstart-MAX_DIST
        !           177:        jae     limit_ok
        !           178:        sub     dx,dx                   ; limit = NIL
        !           179: limit_ok:
        !           180:         add     di,2+window_off         ; di = offset(window + strstart + 2)
        !           181:         mov     bx,_prev_length         ; best_len = prev_length
        !           182:        mov     es,window_seg
        !           183:         mov     ax,es:[bx+di-3]         ; ax = scan[best_len-1..best_len]
        !           184:         mov     cx,es:[di-2]            ; cx = scan[0..1]
        !           185:        cmp     bx,_good_match          ; do we have a good match already?
        !           186:         mov     ds,prev_seg                    ; (does not destroy the flags)
        !           187:         assume  ds: nothing
        !           188:         jb      do_scan                        ; good match?
        !           189:        shr     bp,1                    ; chain_length >>= 2
        !           190:        shr     bp,1
        !           191:         jmp     short do_scan
        !           192: 
        !           193:         even                            ; align destination of branch
        !           194: long_loop:
        !           195: ; at this point, ds:di == scan+2, ds:si == cur_match
        !           196:         mov     ax,[bx+di-3]            ; ax = scan[best_len-1..best_len]
        !           197:         mov     cx,[di-2]               ; cx = scan[0..1]
        !           198:         mov     ds,prev_seg                    ; reset ds to address the prev array
        !           199: short_loop:
        !           200:         dec     bp                      ; --chain_length
        !           201:         jz      the_end
        !           202: ; at this point, di == scan+2, si = cur_match,
        !           203: ; ax = scan[best_len-1..best_len] and cx = scan[0..1]
        !           204: if (WSIZE-32768)
        !           205:         and     si,WMASK
        !           206: endif
        !           207:         shl     si,1                    ; cur_match as word index
        !           208:         mov     si,prev[si]             ; cur_match = prev[cur_match]
        !           209:         cmp     si,dx                  ; cur_match <= limit ?
        !           210:         jbe     the_end
        !           211: do_scan:
        !           212:         cmp     ax,word ptr es:window[bx+si-1] ; check match at best_len-1
        !           213:         jne     short_loop
        !           214:         cmp     cx,word ptr es:window[si]      ; check min_match_length match
        !           215:         jne     short_loop
        !           216: 
        !           217:         lea     si,window[si+2]         ; si = match
        !           218:         mov     ax,di                   ; ax = scan+2
        !           219:         mov     cx,es
        !           220:         mov     ds,cx                  ; ds = es = window
        !           221:         mov     cx,(MAX_MATCH-2)/2      ; scan for at most MAX_MATCH bytes
        !           222:         repe    cmpsw                   ; loop until mismatch
        !           223:         je      maxmatch                ; match of length MAX_MATCH?
        !           224: mismatch:
        !           225:         mov     cl,[di-2]               ; mismatch on first or second byte?
        !           226:         sub     cl,[si-2]               ; cl = 0 if first bytes equal
        !           227:         xchg    ax,di                   ; di = scan+2, ax = end of scan
        !           228:         sub     ax,di                   ; ax = len
        !           229:        sub     si,ax                   ; si = cur_match + 2 + offset(window)
        !           230:        sub     si,2+window_off         ; si = cur_match
        !           231:         sub     cl,1                    ; set carry if cl == 0 (can't use DEC)
        !           232:         adc     ax,0                    ; ax = carry ? len+1 : len
        !           233:         cmp     ax,bx                   ; len > best_len ?
        !           234:         jle     long_loop
        !           235:         mov     ma_start,si             ; match_start = cur_match
        !           236:         mov     bx,ax                   ; bx = best_len = len
        !           237:         cmp     ax,MAX_MATCH            ; len >= MAX_MATCH ?
        !           238:         jl      long_loop
        !           239: the_end:
        !           240:        pop     ds
        !           241:         assume  ds: DGROUP
        !           242: ifdef SS_NEQ_DS
        !           243:        mov     ax,ma_start             ; garbage if no match found
        !           244:        mov     ds:_match_start,ax
        !           245: endif
        !           246:         pop     si
        !           247:         pop     di
        !           248:         pop     bp
        !           249:         mov     ax,bx                   ; result = ax = best_len
        !           250:         ret
        !           251: maxmatch:                               ; come here if maximum match
        !           252:         cmpsb                           ; increment si and di
        !           253:         jmp     mismatch                ; force match_length = MAX_LENGTH
        !           254:         
        !           255: _longest_match  endp
        !           256: 
        !           257: _TEXT   ends
        !           258: end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.