⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deflate.a

📁 infozip2.2源码
💻 A
📖 第 1 页 / 共 3 页
字号:
; This is a 680x0 assembly language translation of the Info-ZIP source file; deflate.c, by Paul Kienitz.  No rights reserved.  The function longest_match; is based in part on match.a by Carsten Steger, which in turn is partly based; on match.s for 386 by Jean-loup Gailly and Kai Uwe Rommel.  Mostly, however,; this material is based on deflate.c, by Gailly, Rommel, and Igor Mandrichenko.; This code is not commented very much; see deflate.c for comments that explain; what the functions are doing.;; The symbols that can be used to select different versions are as follows:;;   CPU020     if defined, use 68020 instructions always.;;   CPUTEST    if defined, check at runtime for CPU type.  Another symbol;               specifying the platform-specific test must be used with this.;               If neither of these is defined, use 68000 instructions only.;               Runtime test is nonportable; it is different for each OS.;;   AMIGA      use Amiga-specific test for 68020, if CPUTEST defined.  Also;               tells it that registers d0/a0/d1/a1 are not preserved by;               function calls.  At present, if AMIGA is not defined, it;               causes functions to preserve all registers.  ALL OF THIS CODE;               CURRENTLY ASSUMES THAT REGISTERS D2-D7/A2-A6 WILL BE PRESERVED;               BY ANY FUNCTIONS THAT IT CALLS.;;   DYN_ALLOC  should be defined here if it is defined for C source; tells us;               that big arrays are allocated instead of static.;;   WSIZE      must be defined as the same number used for WSIZE in the C;               source, and must be a power of two <= 32768.  As elsewhere,;               the default value is 32768.;;   INT16      define this if ints are 16 bits; otherwise 32 bit ints assumed.;;   SMALL_MEM  define this if it is defined in the C source; otherwise it uses;               the MEDIUM_MEM model.  BIG_MEM and MMAP are *not* supported.;               The FULL_SEARCH option in deflate.c is also not supported.;;   DEBUG      activates some tracing output, as in the C source.;;   QUADLONG   this selects a different version of the innermost longest_match;               loop code for 68020 operations, comparing bytes four at a time;               instead of two at a time.  It seems to be a tiny bit faster on;               average, but it's slower often enough that one can't generalize.;; This code currently assumes that function results are returned in D0 for; all platforms.  It assumes that args to functions are pushed onto the stack,; last arg first.  It also currently assumes that all C symbols have an; underscore prepended when referenced from assembly.    IFND    CPU020     IFND   CPUTESTCPU000  equ     1     ENDC    ENDC; Use these macros for accessing variables of type int:    IFD     INT16MOVINT  MACRO        move.w  \1,\2        ENDMCLRINT  MACRO        clr.w   \1        ENDMINTSIZE equ     2    ELSE    ; !INT16MOVINT  MACRO        move.l  \1,\2        ENDMCLRINT  MACRO        clr.l   \1        ENDMINTSIZE equ     4    ENDC    IFD     DYN_ALLOCBASEPTR MACRO        move.l  \1,\2        ENDM    ELSEBASEPTR MACRO        lea     \1,\2        ENDM    ENDC; constants we use, many of them adjustable:MAX_MATCH       equ     258MIN_MATCH       equ     3TOO_FAR         equ     4096    IFND    WSIZEWSIZE           equ     32768    ENDCWMASK           equ     WSIZE-1MAX_DIST        equ     WSIZE-MAX_MATCH-MIN_MATCH-1MIN_LOOKAHEAD   equ     MAX_MATCH+MIN_MATCH+1;    IFD     BIG_MEM      ; NOT supported -- type Pos needs to be 32 bits;HASH_BITS      equ     15;    ELSE    IFD    SMALL_MEMHASH_BITS       equ     13    ELSEHASH_BITS       equ     14      ; default -- MEDIUM_MEM    ENDC;    ENDC    ; BIG_MEMHASH_SIZE       equ     1<<HASH_BITSHASH_MASK       equ     HASH_SIZE-1H_SHIFT         equ     (HASH_BITS+MIN_MATCH-1)/MIN_MATCHB_SLOW          equ     1B_FAST          equ     2ZE_MEM          equ     4EOF             equ     -1; struct config is defined by these offsets:Good_length     equ     0Max_lazy        equ     2Nice_length     equ     4Max_chain       equ     6Sizeof_config   equ     8; external functions we call:        xref    _ct_tally       ; int ct_tally(int, int)        xref    _flush_block    ; unsigned long F(char *, unsigned long, int)        xref    _ziperr         ; void ziperr(int, char *)        xref    _error          ; void error(char *)        xref    _calloc         ; stdlib function: void *calloc(size_t, size_t)        xref    _free           ; stdlib function: void free(void *)    IFD     DEBUG        xref    _fputc          ; stdio function: int fputc(int, FILE *)        xref    _stderr         ; pointer to FILE, which we pass to fputc    ENDC; our entry points:        xdef    _lm_init        ; void lm_init(int level, unsigned short *flags)        xdef    _lm_free        ; void lm_free(void)        xdef    _deflate        ; void deflate(void)  ...the big one        xdef    _fill_window    ; this line is just for debugging; ============================================================================; Here is where we have our global variables.        section deflatevars,data; external global variables we reference:        xref    _verbose        ; signed int        xref    _level          ; signed int        xref    _read_buf       ; int (*read_buf)(char *, unsigned int); global variables we make available:        xdef    _window        xdef    _prev        xdef    _head        xdef    _window_size        xdef    _block_start        xdef    _strstart    IFD     DYN_ALLOC_prev:          ds.l    1       ; pointer to calloc()'d unsigned short array_head:          ds.l    1       ; pointer to calloc()'d unsigned short array_window:        ds.l    1       ; pointer to calloc()'d unsigned char array    ELSE    ; !DYN_ALLOC_prev:          ds.w    WSIZE           ; array of unsigned short_head:          ds.w    HASH_SIZE       ; array of unsigned short_window:        ds.b    2*WSIZE         ; array of unsigned char    ENDC    ; ?DYN_ALLOC_window_size:   ds.l    1               ; unsigned long_block_start:   ds.l    1               ; unsigned long_strstart:      ds.w    INTSIZE/2       ; unsigned int; Now here are our private variables:    IFD     CPUTESTis020:          ds.w    1       ; bool: CPU type is '020 or higher    ENDCins_h:          ds.w    1       ; unsigned shortsliding:        ds.w    1       ; bool: the file is read a piece at a timeeofile:         ds.w    1       ; bool: we have read in the end of the filemax_lazy_match: ds.w    1       ; unsigned shortlookahead:      ds.w    1       ; unsigned short; These are NOT DECLARED AS STATIC in deflate.c, but currently could be:max_chain_len:  ds.w    1       ; unsigned short (unsigned int in deflate.c)prev_length:    ds.w    1       ; unsigned short (unsigned int in deflate.c)good_match:     ds.w    1       ; unsigned short (unsigned int in deflate.c)nice_match:     ds.w    1       ; unsigned short (signed int in deflate.c)match_start:    ds.w    1       ; unsigned short (unsigned int in deflate.c); This array of struct config is a constant and could be in the code section:config_table:   dc.w    0,0,0,0         ; level 0: store uncompressed                dc.w    4,4,8,4         ; level 1: fastest, loosest compression                dc.w    4,5,16,8        ; level 2                dc.w    4,6,32,32       ; level 3: highest to use deflate_fast                dc.w    4,4,16,16       ; level 4: lowest to use lazy matches                dc.w    8,16,32,32      ; level 5                dc.w    8,16,128,128    ; level 6: the default level                dc.w    8,32,128,256    ; level 7                dc.w    32,128,258,1024 ; level 8                dc.w    32,258,258,4096 ; level 9: maximum compression, slow;;CAL_SH  MACRO                   ; macro for calling zcalloc();;     IFD    INT16;;        move.w  #2,-(sp);;        move.w  #\1,-(sp);;        jsr     _zcalloc;;        addq    #4,sp;;     ELSE;;        pea     2;;        pea     \1;;        jsr     _zcalloc;;        addq    #8,sp;;     ENDC;;        ENDMCAL_SH  MACRO                   ; Okay, we're back to using regular calloc()...        pea     2        pea     \1        jsr     _calloc        addq    #8,sp        ENDM; ============================================================================; And here we begin our functions.  match_init is for internal use only:        section deflate,codematch_init:    IFD     CPUTEST             ; now check for platform type     IFD    AMIGA               ; Amiga specific test for '020 CPU:        xref    _SysBase        NOLIST        INCLUDE       'exec/execbase.i'        LIST        clr.w   is020                   ; default value is 68000        move.l  _SysBase,a0        btst    #AFB_68020,AttnFlags+1(a0)        beq.s   cheap        move.w  #1,is020cheap:     ELSE   ; !AMIGA        FAIL    Write an '020-detector for your system here!; On the Macintosh, I believe GetEnvironment() provides the information.     ENDC   ; AMIGA    ENDC    ; CPUTEST        rts     ; match_init consists only of rts if CPUTEST unset; ============================================================================; Here is longest_match(), the function that the rest of this was built up; from, the hottest hot spot in the program and therefore the most heavily; optimized.  It has two different versions, one for '020 and higher CPUs, and; one for 68000/68010.  It can test at runtime which version to use if you; create a test function in match_init for your platform.  Currently such a; test is implemented for the Amiga.  It can also be assembled to use '000 or; '020 code only.Cur_Match       equr    d0              ; unsigned int, kept valid as longBest_Len        equr    d1              ; unsigned int, kept valid as longScan_Start      equr    d3              ; pair of bytesScan_End        equr    d4              ; pair of bytesLimit           equr    d5              ; unsigned intChain_Length    equr    d6              ; unsigned intScan_Test       equr    d7              ; counter, pair of bytes sometimesScan            equr    a0              ; pointer to unsigned charMatch           equr    a1              ; pointer to unsigned charPrev_Address    equr    a2              ; pointer to unsigned shortScan_Ini        equr    a3              ; pointer to unsigned charMatch_Ini       equr    a5              ; pointer to unsigned char; Note: "pair of bytes" means the two low order bytes of the register in; 68020 code, but means the lowest and third lowest bytes on the 68000.    IFD     AMIGASAVEREGS        reg     d3-d7/a2/a3/a5      ; don't protect d0/d1/a0/a1    ELSE    ; !AMIGASAVEREGS        reg     d1/d3-d7/a0-a3/a5   ; protect all except d0 return val    ENDC    ; ?AMIGA; d2, a4, a6 not used... on Amiga, a4 is used by small-data memory modellongest_match:        movem.l SAVEREGS,-(sp); setup steps common to byte and word versions:    IFD     INT16        and.l   #$0000FFFF,Cur_Match    ; upper half must be zero!; we use an and.l down here for the sake of ATSIGN/REGARGS.        moveq   #0,Limit                ; so adding to Scan_Ini works    ENDC        move.w  max_chain_len,Chain_Length        move.w  prev_length,Best_Len        MOVINT  _strstart,Limit        BASEPTR _prev,Prev_Address        BASEPTR _window,Match_Ini        move.l  Match_Ini,Scan_Ini        addq    #MIN_MATCH,Match_Ini    ; optimizes inner loop        add.l   Limit,Scan_Ini        sub.w   #MAX_DIST,Limit        bhi.s   limit_ok        moveq   #0,Limitlimit_ok:        cmp.w   good_match,Best_Len        blo.s   length_ok        lsr.w   #2,Chain_Lengthlength_ok:        subq.w  #1,Chain_Length    IFD     CPUTEST        tst.w   is020                   ; can we use '020 stuff today?        bne     WORD_match    ENDC    IFND    CPU020; for 68000 or 68010, use byte operations:        moveq   #0,Scan_Start           ; clear 2nd & 4th bytes, use 1st & 3rd        moveq   #0,Scan_End             ; likewise        moveq   #0,Scan_Test            ; likewise        move.b  (Scan_Ini),Scan_Start        swap    Scan_Start              ; swap is faster than 8 bit shift        move.b  1(Scan_Ini),Scan_Start        move.b  -1(Scan_Ini,Best_Len.w),Scan_End        swap    Scan_End        move.b  0(Scan_Ini,Best_Len.w),Scan_End        bra.s   bdo_scanblong_loop:        move.b  -1(Scan_Ini,Best_Len.w),Scan_End        swap    Scan_End        move.b  0(Scan_Ini,Best_Len.w),Scan_Endbshort_loop:        add.w   Cur_Match,Cur_Match     ; assert value before doubling < 32K     IFNE   32768-WSIZE        and.w   #(WMASK*2),Cur_Match     ENDC        move.w  (Prev_Address,Cur_Match.l),Cur_Match        cmp.w   Limit,Cur_Match        dbls    Chain_Length,bdo_scan        bra     returnbdo_scan:        move.l  Match_Ini,Match        add.l   Cur_Match,Match        move.b  -MIN_MATCH-1(Match,Best_Len.w),Scan_Test        swap    Scan_Test

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -