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

1.1       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: DYN_ALLOC equ 1
                     34: SS_NEQ_DS equ 1
                     35: ; For Turbo C, define SS_NEQ_DS as 1, but for MSC you can leave it undefined.
                     36: ; The code is a little better when SS_NEQ_DS is not defined.
                     37: 
                     38: ifndef DYN_ALLOC
                     39:         extrn   _prev         : word
                     40:         extrn   _window       : byte
                     41:         prev    equ  _prev    ; offset part
                     42:         window  equ  _window
                     43: endif
                     44: 
                     45: _DATA    segment  word public 'DATA'
                     46:         extrn   _match_start  : word
                     47:         extrn   _prev_length  : word
                     48:         extrn   _good_match   : word
                     49:         extrn   _strstart     : word
                     50:         extrn   _max_chain_length : word
                     51: ifdef DYN_ALLOC
                     52:         extrn   _prev         : word
                     53:         extrn   _window       : word
                     54:         prev    equ 0         ; offset forced to zero
                     55:         window  equ 0
                     56:         window_seg equ _window[2]
                     57:        window_off equ 0
                     58: else
                     59:        wseg    dw seg _window
                     60:         window_seg equ wseg
                     61:        window_off equ offset _window
                     62: endif
                     63: _DATA    ends
                     64: 
                     65: DGROUP  group _DATA
                     66: 
                     67: if LCODE
                     68:        extrn   _exit : far
                     69: else
                     70:        extrn   _exit : near
                     71: endif
                     72: 
                     73: _TEXT   segment word public 'CODE'
                     74:         assume  cs: _TEXT, ds: DGROUP
                     75: 
                     76:        public _match_init
                     77:         public _longest_match
                     78: 
                     79:        MIN_MATCH     equ 3
                     80:         MAX_MATCH     equ 258
                     81:        WSIZE         equ 8192          ; keep in sync with zip.h !
                     82:        WMASK         equ (WSIZE-1)
                     83:        MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
                     84:        MAX_DIST      equ (WSIZE-MIN_LOOKAHEAD)
                     85: 
                     86: prev_ptr    dw  seg _prev              ; pointer to the prev array
                     87: ifdef SS_NEQ_DS
                     88:     match_start dw  0                  ; copy of _match_start if SS != DS
                     89: endif
                     90: 
                     91: ; initialize or check the variables used in match.asm.
                     92: 
                     93: if LCODE
                     94: _match_init proc far
                     95: else
                     96: _match_init proc near
                     97: endif
                     98: ifdef SS_NEQ_DS
                     99:         ma_start equ cs:match_start    ; does not work on OS/2
                    100: else
                    101:        assume ss: DGROUP
                    102:         ma_start equ ss:_match_start
                    103:         mov     ax,ds
                    104:         mov     bx,ss
                    105:         cmp     ax,bx                   ; SS == DS?
                    106:         jne     error
                    107: endif
                    108: ifdef DYN_ALLOC
                    109:        mov     ax,_window[0]           ; force zero offset
                    110:        add     ax,15
                    111:        mov     cx,4
                    112:        shr     ax,cl
                    113:        add     _window[2],ax
                    114:        mov     _window[0],0
                    115: 
                    116:        mov     ax,_prev[0]             ; force zero offset
                    117:        add     ax,15
                    118:        mov     cx,4
                    119:        shr     ax,cl
                    120:        add     _prev[2],ax
                    121:        mov     _prev[0],0
                    122:   ifdef SS_NEQ_DS
                    123:        mov     ax,_prev[2]             ; segment value
                    124:        mov     cs:prev_ptr,ax          ; ugly write to code, crash on OS/2
                    125:         prev_seg  equ cs:prev_ptr
                    126:   else
                    127:         prev_seg  equ ss:_prev[2]      ; works on OS/2 if SS == DS
                    128:   endif
                    129: else
                    130:         prev_seg  equ cs:prev_ptr
                    131: endif
                    132:        ret
                    133: error:  call    _exit
                    134: 
                    135: _match_init endp
                    136: 
                    137: ; -----------------------------------------------------------------------
                    138: ; Set match_start to the longest match starting at the given string and
                    139: ; return its length. Matches shorter or equal to prev_length are discarded,
                    140: ; in which case the result is equal to prev_length and match_start is
                    141: ; garbage.
                    142: ; IN assertions: cur_match is the head of the hash chain for the current
                    143: ;   string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
                    144: 
                    145: ; int longest_match(cur_match)
                    146: 
                    147: if LCODE
                    148: _longest_match  proc far
                    149: else
                    150: _longest_match  proc near
                    151: endif
                    152:         push    bp
                    153:         mov     bp,sp
                    154:         push    di
                    155:        push    si
                    156:        push    ds
                    157: 
                    158: if LCODE
                    159:         cur_match    equ word ptr [bp+6]
                    160: else
                    161:         cur_match    equ word ptr [bp+4]
                    162: endif
                    163: ;       window      equ es:window (es:0 for DYN_ALLOC)
                    164: ;       prev        equ ds:prev
                    165: ;       match        equ es:si
                    166: ;       scan         equ es:di
                    167: ;       chain_length equ bp
                    168: ;       best_len     equ bx
                    169: ;       limit        equ dx
                    170: 
                    171:        mov     si,cur_match            ; use bp before it is destroyed
                    172:         mov     bp,_max_chain_length    ; chain_length = max_chain_length
                    173:        mov     di,_strstart
                    174:        mov     dx,di
                    175:        sub     dx,MAX_DIST             ; limit = strstart-MAX_DIST
                    176:        jae     limit_ok
                    177:        sub     dx,dx                   ; limit = NIL
                    178: limit_ok:
                    179:         add     di,2+window_off         ; di = offset(window + strstart + 2)
                    180:         mov     bx,_prev_length         ; best_len = prev_length
                    181:        mov     es,window_seg
                    182:         mov     ax,es:[bx+di-3]         ; ax = scan[best_len-1..best_len]
                    183:         mov     cx,es:[di-2]            ; cx = scan[0..1]
                    184:        cmp     bx,_good_match          ; do we have a good match already?
                    185:         mov     ds,prev_seg                    ; (does not destroy the flags)
                    186:         assume  ds: nothing
                    187:         jb      do_scan                        ; good match?
                    188:        shr     bp,1                    ; chain_length >>= 2
                    189:        shr     bp,1
                    190:         jmp     short do_scan
                    191: 
                    192:         even                            ; align destination of branch
                    193: long_loop:
                    194: ; at this point, ds:di == scan+2, ds:si == cur_match
                    195:         mov     ax,[bx+di-3]            ; ax = scan[best_len-1..best_len]
                    196:         mov     cx,[di-2]               ; cx = scan[0..1]
                    197:         mov     ds,prev_seg                    ; reset ds to address the prev array
                    198: short_loop:
                    199:         dec     bp                      ; --chain_length
                    200:         jz      the_end
                    201: ; at this point, di == scan+2, si = cur_match,
                    202: ; ax = scan[best_len-1..best_len] and cx = scan[0..1]
                    203: if (WSIZE-32768)
                    204:         and     si,WMASK
                    205: endif
                    206:         shl     si,1                    ; cur_match as word index
                    207:         mov     si,prev[si]             ; cur_match = prev[cur_match]
                    208:         cmp     si,dx                  ; cur_match <= limit ?
                    209:         jbe     the_end
                    210: do_scan:
                    211:         cmp     ax,word ptr es:window[bx+si-1] ; check match at best_len-1
                    212:         jne     short_loop
                    213:         cmp     cx,word ptr es:window[si]      ; check min_match_length match
                    214:         jne     short_loop
                    215: 
                    216:         lea     si,window[si+2]         ; si = match
                    217:         mov     ax,di                   ; ax = scan+2
                    218:         mov     cx,es
                    219:         mov     ds,cx                  ; ds = es = window
                    220:         mov     cx,(MAX_MATCH-2)/2      ; scan for at most MAX_MATCH bytes
                    221:         repe    cmpsw                   ; loop until mismatch
                    222:         je      maxmatch                ; match of length MAX_MATCH?
                    223: mismatch:
                    224:         mov     cl,[di-2]               ; mismatch on first or second byte?
                    225:         sub     cl,[si-2]               ; cl = 0 if first bytes equal
                    226:         xchg    ax,di                   ; di = scan+2, ax = end of scan
                    227:         sub     ax,di                   ; ax = len
                    228:        sub     si,ax                   ; si = cur_match + 2 + offset(window)
                    229:        sub     si,2+window_off         ; si = cur_match
                    230:         sub     cl,1                    ; set carry if cl == 0 (can't use DEC)
                    231:         adc     ax,0                    ; ax = carry ? len+1 : len
                    232:         cmp     ax,bx                   ; len > best_len ?
                    233:         jle     long_loop
                    234:         mov     ma_start,si             ; match_start = cur_match
                    235:         mov     bx,ax                   ; bx = best_len = len
                    236:         cmp     ax,MAX_MATCH            ; len >= MAX_MATCH ?
                    237:         jl      long_loop
                    238: the_end:
                    239:        pop     ds
                    240:         assume  ds: DGROUP
                    241: ifdef SS_NEQ_DS
                    242:        mov     ax,ma_start             ; garbage if no match found
                    243:        mov     ds:_match_start,ax
                    244: endif
                    245:         pop     si
                    246:         pop     di
                    247:         pop     bp
                    248:         mov     ax,bx                   ; result = ax = best_len
                    249:         ret
                    250: maxmatch:                               ; come here if maximum match
                    251:         cmpsb                           ; increment si and di
                    252:         jmp     mismatch                ; force match_length = MAX_LENGTH
                    253:         
                    254: _longest_match  endp
                    255: 
                    256: _TEXT   ends
                    257: end

unix.superglobalmegacorp.com

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