|
|
1.1 ! root 1: /* match.s -- optional optimized asm version of longest match in deflate.c ! 2: * Copyright (C) 1992-1993 Jean-loup Gailly ! 3: * This is free software; you can redistribute it and/or modify it under the ! 4: * terms of the GNU General Public License, see the file COPYING. ! 5: */ ! 6: ! 7: /* $Id: match.S,v 0.9 1993/02/24 18:23:13 jloup Exp $ */ ! 8: ! 9: /* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix ! 10: * external symbols with an underline character '_'. ! 11: */ ! 12: #ifdef NO_UNDERLINE ! 13: # define _prev prev ! 14: # define _window window ! 15: # define _match_start match_start ! 16: # define _prev_length prev_length ! 17: # define _good_match good_match ! 18: # define _nice_match nice_match ! 19: # define _strstart strstart ! 20: # define _max_chain_length max_chain_length ! 21: ! 22: # define _match_init match_init ! 23: # define _longest_match longest_match ! 24: #endif ! 25: ! 26: #ifdef DYN_ALLOC ! 27: error: DYN_ALLOC not yet supported in match.s ! 28: #endif ! 29: ! 30: #if defined(i386) || defined(_I386) ! 31: ! 32: /* This version is for 386 Unix or OS/2 in 32 bit mode. ! 33: * Warning: it uses the AT&T syntax: mov source,dest ! 34: * This file is only optional. If you want to force the C version, ! 35: * add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string. ! 36: * If you have reduced WSIZE in gzip.h, then change its value below. ! 37: * This version assumes static allocation of the arrays (-DDYN_ALLOC not used). ! 38: */ ! 39: ! 40: .file "match.S" ! 41: ! 42: #define MAX_MATCH 258 ! 43: #define MAX_MATCH2 128 /* MAX_MATCH/2-1 */ ! 44: #define MIN_MATCH 3 ! 45: #define WSIZE 32768 ! 46: #define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1 ! 47: ! 48: .globl _match_init ! 49: .globl _longest_match ! 50: ! 51: .text ! 52: ! 53: _match_init: ! 54: ret ! 55: ! 56: /*----------------------------------------------------------------------- ! 57: * Set match_start to the longest match starting at the given string and ! 58: * return its length. Matches shorter or equal to prev_length are discarded, ! 59: * in which case the result is equal to prev_length and match_start is ! 60: * garbage. ! 61: * IN assertions: cur_match is the head of the hash chain for the current ! 62: * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 ! 63: */ ! 64: ! 65: _longest_match: /* int longest_match(cur_match) */ ! 66: ! 67: #define cur_match 20(%esp) ! 68: /* return address */ /* esp+16 */ ! 69: push %ebp /* esp+12 */ ! 70: push %edi /* esp+8 */ ! 71: push %esi /* esp+4 */ ! 72: push %ebx /* esp */ ! 73: ! 74: /* ! 75: * match equ esi ! 76: * scan equ edi ! 77: * chain_length equ ebp ! 78: * best_len equ ebx ! 79: * limit equ edx ! 80: */ ! 81: mov cur_match,%esi ! 82: mov _max_chain_length,%ebp /* chain_length = max_chain_length */ ! 83: mov _strstart,%edi ! 84: mov %edi,%edx ! 85: sub $ MAX_DIST,%edx /* limit = strstart-MAX_DIST */ ! 86: jae limit_ok ! 87: sub %edx,%edx /* limit = NIL */ ! 88: limit_ok: ! 89: add $ _window+2,%edi /* edi = offset(window+strstart+2) */ ! 90: mov _prev_length,%ebx /* best_len = prev_length */ ! 91: movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */ ! 92: movw -2(%edi),%cx /* cx = scan[0..1] */ ! 93: cmp _good_match,%ebx /* do we have a good match already? */ ! 94: jb do_scan ! 95: shr $2,%ebp /* chain_length >>= 2 */ ! 96: jmp do_scan ! 97: ! 98: .align 4 ! 99: long_loop: ! 100: /* at this point, edi == scan+2, esi == cur_match */ ! 101: movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */ ! 102: movw -2(%edi),%cx /* cx = scan[0..1] */ ! 103: short_loop: ! 104: /* ! 105: * at this point, di == scan+2, si == cur_match, ! 106: * ax = scan[best_len-1..best_len] and cx = scan[0..1] ! 107: */ ! 108: and $ WSIZE-1, %esi ! 109: movw _prev(%esi,%esi),%si /* cur_match = prev[cur_match] */ ! 110: /* top word of esi is still 0 */ ! 111: cmp %edx,%esi /* cur_match <= limit ? */ ! 112: jbe the_end ! 113: dec %ebp /* --chain_length */ ! 114: jz the_end ! 115: do_scan: ! 116: cmpw _window-1(%ebx,%esi),%ax/* check match at best_len-1 */ ! 117: jne short_loop ! 118: cmpw _window(%esi),%cx /* check min_match_length match */ ! 119: jne short_loop ! 120: ! 121: lea _window+2(%esi),%esi /* si = match */ ! 122: mov %edi,%eax /* ax = scan+2 */ ! 123: mov $ MAX_MATCH2,%ecx /* scan for at most MAX_MATCH bytes */ ! 124: rep; cmpsw /* loop until mismatch */ ! 125: je maxmatch /* match of length MAX_MATCH? */ ! 126: mismatch: ! 127: movb -2(%edi),%cl /* mismatch on first or second byte? */ ! 128: subb -2(%esi),%cl /* cl = 0 if first bytes equal */ ! 129: xchg %edi,%eax /* edi = scan+2, eax = end of scan */ ! 130: sub %edi,%eax /* eax = len */ ! 131: sub %eax,%esi /* esi = cur_match + 2 + offset(window) */ ! 132: sub $ _window+2,%esi /* esi = cur_match */ ! 133: subb $1,%cl /* set carry if cl == 0 (cannot use DEC) */ ! 134: adc $0,%eax /* eax = carry ? len+1 : len */ ! 135: cmp %ebx,%eax /* len > best_len ? */ ! 136: jle long_loop ! 137: mov %esi,_match_start /* match_start = cur_match */ ! 138: mov %eax,%ebx /* ebx = best_len = len */ ! 139: cmp _nice_match,%eax /* len >= nice_match ? */ ! 140: jl long_loop ! 141: the_end: ! 142: mov %ebx,%eax /* result = eax = best_len */ ! 143: pop %ebx ! 144: pop %esi ! 145: pop %edi ! 146: pop %ebp ! 147: ret ! 148: maxmatch: ! 149: cmpsb ! 150: jmp mismatch ! 151: ! 152: #else ! 153: #if defined(m68k) || defined(mc68020) ! 154: ! 155: /* 68020 version, written by Francesco Potorti` <[email protected]> */ ! 156: ! 157: #ifdef m68k /* Try 'delta' style */ ! 158: ! 159: # define GLOBAL(symbol) global symbol ! 160: # define TEXT text ! 161: # define FILE(filename) file filename ! 162: # define invert_maybe(src,dst) dst,src ! 163: # define imm(data) &data ! 164: # define reg(register) %register ! 165: ! 166: # define addl add.l ! 167: # define addql addq.l ! 168: # define blos blo.b ! 169: # define bhis bhi.b ! 170: # define bras bra.b ! 171: # define clrl clr.l ! 172: # define cmpmb cmpm.b ! 173: # define cmpw cmp.w ! 174: # define cmpl cmp.l ! 175: # define lslw lsl.w ! 176: # define lsrl lsr.l ! 177: # define movel move.l ! 178: # define movew move.w ! 179: # define moveml movem.l ! 180: # define subl sub.l ! 181: # define subw sub.w ! 182: # define subql subq.l ! 183: ! 184: # define IndBase(bd,An) (bd,An) ! 185: # define IndBaseNdxl(bd,An,Xn) (bd,An,Xn.l) ! 186: # define IndBaseNdxw(bd,An,Xn) (bd,An,Xn.w) ! 187: # define predec(An) -(An) ! 188: # define postinc(An) (An)+ ! 189: ! 190: #else /* Try Sun 3 or Amiga style */ ! 191: ! 192: # define GLOBAL(symbol) .globl symbol ! 193: # define TEXT .text ! 194: # define FILE(filename) .even ! 195: # define invert_maybe(src,dst) src,dst ! 196: # ifdef sun ! 197: # define imm(data) #data ! 198: # else ! 199: # define imm(data) \#data ! 200: # endif ! 201: # define reg(register) register ! 202: ! 203: # define blos bcss ! 204: # ifdef sun ! 205: # define movel movl ! 206: # define movew movw ! 207: # endif ! 208: # define IndBase(bd,An) An@(bd) ! 209: # define IndBaseNdxl(bd,An,Xn) An@(bd,Xn:l) ! 210: # define IndBaseNdxw(bd,An,Xn) An@(bd,Xn:w) ! 211: # define predec(An) An@- ! 212: # define postinc(An) An@+ ! 213: ! 214: #endif /* styles */ ! 215: ! 216: #define Best_Len reg(d0) /* unsigned */ ! 217: #define Cur_Match reg(d1) /* Ipos */ ! 218: #define Loop_Counter reg(d2) /* int */ ! 219: #define Scan_Start reg(d3) /* unsigned short */ ! 220: #define Scan_End reg(d4) /* unsigned short */ ! 221: #define Limit reg(d5) /* IPos */ ! 222: #define Chain_Length reg(d6) /* unsigned */ ! 223: #define Scan reg(a0) /* *uch */ ! 224: #define Match reg(a1) /* *uch */ ! 225: #define Prev_Address reg(a2) /* *Pos */ ! 226: #define Scan_Ini reg(a3) /* *uch */ ! 227: #define Match_Ini reg(a4) /* *uch */ ! 228: #define Stack_Pointer reg(sp) ! 229: ! 230: #define MAX_MATCH 258 ! 231: #define MIN_MATCH 3 ! 232: #define WSIZE 32768 ! 233: #define MAX_DIST (WSIZE - MAX_MATCH - MIN_MATCH - 1) ! 234: ! 235: GLOBAL (_match_init) ! 236: GLOBAL (_longest_match) ! 237: ! 238: TEXT ! 239: ! 240: FILE ("match.S") ! 241: ! 242: _match_init: ! 243: rts ! 244: ! 245: /*----------------------------------------------------------------------- ! 246: * Set match_start to the longest match starting at the given string and ! 247: * return its length. Matches shorter or equal to prev_length are discarded, ! 248: * in which case the result is equal to prev_length and match_start is ! 249: * garbage. ! 250: * IN assertions: cur_match is the head of the hash chain for the current ! 251: * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 ! 252: */ ! 253: ! 254: /* int longest_match (cur_match) */ ! 255: #define pushreg 15928 /* d2-d6/a2-a4 */ ! 256: #define popreg 7292 ! 257: ! 258: _longest_match: ! 259: movel IndBase(4,Stack_Pointer),Cur_Match ! 260: moveml imm(pushreg),predec(Stack_Pointer) ! 261: movel _max_chain_length,Chain_Length ! 262: movel _prev_length,Best_Len ! 263: movel imm(_prev),Prev_Address ! 264: movel imm(_window+MIN_MATCH),Match_Ini ! 265: movel _strstart,Limit ! 266: movel Match_Ini,Scan_Ini ! 267: addl Limit,Scan_Ini ! 268: subw imm(MAX_DIST),Limit ! 269: bhis L__limit_ok ! 270: clrl Limit ! 271: L__limit_ok: ! 272: cmpl invert_maybe(_good_match,Best_Len) ! 273: blos L__length_ok ! 274: lsrl imm(2),Chain_Length ! 275: L__length_ok: ! 276: subql imm(1),Chain_Length ! 277: movew IndBase(-MIN_MATCH,Scan_Ini),Scan_Start ! 278: movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End ! 279: bras L__do_scan ! 280: ! 281: L__long_loop: ! 282: movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End ! 283: ! 284: L__short_loop: ! 285: lslw imm(1),Cur_Match ! 286: movew IndBaseNdxl(0,Prev_Address,Cur_Match),Cur_Match ! 287: cmpw invert_maybe(Limit,Cur_Match) ! 288: dbls Chain_Length,L__do_scan ! 289: bras L__return ! 290: ! 291: L__do_scan: ! 292: movel Match_Ini,Match ! 293: addl Cur_Match,Match ! 294: cmpw invert_maybe(IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_End) ! 295: bne L__short_loop ! 296: cmpw invert_maybe(IndBase(-MIN_MATCH,Match),Scan_Start) ! 297: bne L__short_loop ! 298: ! 299: movew imm((MAX_MATCH-MIN_MATCH+1)-1),Loop_Counter ! 300: movel Scan_Ini,Scan ! 301: L__scan_loop: ! 302: cmpmb postinc(Match),postinc(Scan) ! 303: dbne Loop_Counter,L__scan_loop ! 304: ! 305: subl Scan_Ini,Scan ! 306: addql imm(MIN_MATCH-1),Scan ! 307: cmpl invert_maybe(Best_Len,Scan) ! 308: bls L__short_loop ! 309: movel Scan,Best_Len ! 310: movel Cur_Match,_match_start ! 311: cmpl invert_maybe(_nice_match,Best_Len) ! 312: blos L__long_loop ! 313: L__return: ! 314: moveml postinc(Stack_Pointer),imm(popreg) ! 315: rts ! 316: ! 317: #else ! 318: error: this asm version is for 386 or 68020 only ! 319: #endif /* m68k || mc68020 */ ! 320: #endif /* i386 || _I386 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.