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

📄 deflate.a

📁 infozip2.2源码
💻 A
📖 第 1 页 / 共 3 页
字号:
        move.b  -MIN_MATCH(Match,Best_Len.w),Scan_Test        cmp.l   Scan_Test,Scan_End        bne.s   bshort_loop        move.b  -MIN_MATCH(Match),Scan_Test        swap    Scan_Test        move.b  -MIN_MATCH+1(Match),Scan_Test        cmp.l   Scan_Test,Scan_Start        bne.s   bshort_loop        move.w  #(MAX_MATCH-3),Scan_Test        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loopbscan_loop:        cmp.b   (Match)+,(Scan)+        dbne    Scan_Test,bscan_loop        subq    #1,Scan        sub.l   Scan_Ini,Scan           ; assert difference is 16 bits        cmp.w   Best_Len,Scan        bls.s   bshort_loop        MOVINT  Scan,Best_Len        move.w  Cur_Match,match_start        cmp.w   nice_match,Best_Len        blo.s   blong_loop     IFD    CPUTEST        bra     return     ENDC    ENDC    ; !CPU020    IFND    CPU000        MACHINE MC68020; for 68020 or higher, use word operations even on odd addresses:WORD_match:        move.w  (Scan_Ini),Scan_Start        move.w  -1(Scan_Ini,Best_Len.w),Scan_End        bra.s   wdo_scanwlong_loop:        move.w  -1(Scan_Ini,Best_Len.w),Scan_Endwshort_loop:        and.w   #WMASK,Cur_Match        move.w  (Prev_Address,Cur_Match.w*2),Cur_Match  ; '020 addressing mode        cmp.w   Limit,Cur_Match        dbls    Chain_Length,wdo_scan        bra.s   returnwdo_scan:        move.l  Match_Ini,Match        add.l   Cur_Match,Match        cmp.w   -MIN_MATCH-1(Match,Best_Len.w),Scan_End        bne.s   wshort_loop        cmp.w   -MIN_MATCH(Match),Scan_Start        bne.s   wshort_loop     IFD    QUADLONG; By some measurements, this version of the code is a little tiny bit faster.; But on some files it's slower.  It probably pays off only when there are; long match strings, and costs in the most common case of three-byte matches.        moveq   #((MAX_MATCH-MIN_MATCH)/16),Scan_Test     ; value = 15        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loopwscan_loop:        cmp.l   (Match)+,(Scan)+                ; test four bytes at a time        bne.s   odd        cmp.l   (Match)+,(Scan)+        bne.s   odd        cmp.l   (Match)+,(Scan)+        bne.s   odd        cmp.l   (Match)+,(Scan)+        dbne    Scan_Test,wscan_loop            ; '020 can cache a bigger loopodd:        subq    #4,Scan        subq    #4,Match        cmp.b   (Match)+,(Scan)+        ; find good bytes in bad longword        bne.s   even        cmp.b   (Match)+,(Scan)+        bne.s   even        cmp.b   (Match)+,(Scan)+        beq.s   steveneven:   subq    #1,Scan     ELSE   ; !QUADLONG        moveq   #((MAX_MATCH-MIN_MATCH)/2),Scan_Test    ; value = 127        lea     MIN_MATCH(Scan_Ini),Scan        ; offset optimizes inner loopwscan_loop:        cmp.w   (Match)+,(Scan)+        dbne    Scan_Test,wscan_loop        subq    #2,Scan        move.b  -2(Match),Scan_Test        cmp.b   (Scan),Scan_Test        bne.s   steven        addq    #1,Scan     ENDC   ; ?QUADLONGsteven:        sub.l   Scan_Ini,Scan           ; assert: difference is 16 bits        cmp.w   Best_Len,Scan        bls.s   wshort_loop        MOVINT  Scan,Best_Len        move.w  Cur_Match,match_start        cmp.w   nice_match,Best_Len        blo.s   wlong_loop        MACHINE MC68000    ENDC    ; !CPU000return:        MOVINT  Best_Len,d0         ; return value (upper half should be clear)        movem.l (sp)+,SAVEREGS        rts; =============================================================================; This is the deflate() function itself, our main entry point.  It calls; longest_match, above, and some outside functions.  It is a hot spot, but not; as hot as longest_match.  It uses no special '020 code.; ================== Several macros used in deflate() and later functions:; Arg 1 is D-reg that new ins_h value is to be left in,; arg 2 is the byte value to be hashed into it, which must not be the same regUP_HASH MACRO        move.w  ins_h,\1        asl.w   #H_SHIFT,\1        eor.b   \2,\1        and.w   #HASH_MASK,\1           ; ((ins_h << H_SHIFT) ^ c) & HASH_MASK        move.w  \1,ins_h                ; ins_h = that        ENDM; Arg 1 is scratch A, arg 2 is scratch DIN_STR  MACRO        move.l  Strst,\2        addq.w  #MIN_MATCH-1,\2        move.b  (Window,\2.l),\2        ; window[strstart + MIN_MATCH - 1]        UP_HASH Head,\2        add.l   Head,Head               ; assert upper word is zero before add        BASEPTR _head,\1        add.l   Head,\1        move.w  (\1),Head               ; hash_head = head[ins_h]        move.w  Strst,(\1)              ; head[ins_h] = strstart        move.l  Strst,\2    IFNE    WSIZE-32768        and.w   #WMASK,\2    ENDC        add.w   \2,\2                   ; masks implicitly when WSIZE == 32768        move.w  Head,(Prev,\2.l)        ; prev[str_start & WMASK] = hash_head        ENDM; Arg 1 is bool (int) EOF flag, flush_block result is in d0, trashes d1/a0/a1FLUSH_B MACRO    IFC     '\1','#0'        CLRINT  -(sp)    ELSE        MOVINT  \1,-(sp)    ENDC        move.l  _block_start,d0        blt.s   nenu\@        move.l  Window,a0        add.l   d0,a0        bra.s   nun\@nenu\@: sub.l   a0,a0           ; if block_start < 0, push NULLnun\@:  sub.l   Strst,d0        neg.l   d0        move.l  d0,-(sp)        move.l  a0,-(sp)        jsr     _flush_block        lea     8+INTSIZE(sp),sp        ENDM; This expands to nothing unless DEBUG is defined.; Arg 1 is a byte to be trace-outputted -- if it is d0 it must be a valid intTRACE_C MACRO    IFD    DEBUG        cmp.w  #1,_verbose+INTSIZE-2    ; test lower word only        ble.s   qui\@     IFNC    '\1','d0'        moveq   #0,d0        move.b  \1,d0     ENDC        move.l  _stderr,-(sp)        MOVINT  d0,-(sp)        jsr     _fputc        addq    #4+INTSIZE,spqui\@:    ENDC    ; DEBUG        ENDM; ================== Here are the register vars we use, and deflate() itself:Window  equr    a2              ; cached address of window[]Prev    equr    a3              ; cached address of prev[]Strst   equr    d7              ; strstart cached as a longwordLook    equr    d6              ; lookahead cached as shortHead    equr    d5              ; local variable hash_head, shortPrevL   equr    d4              ; prev_length cached as shortMatchL  equr    d3              ; local variable match_length, unsigned shortAvail   equr    d2              ; local variable available_match, boolPrevM   equr    a5              ; local variable prev_match, int in an A-reg    IFD     AMIGADEFREGS reg     d2-d7/a2/a3/a5    ELSEDEFREGS reg     d0-d7/a0/a2/a3/a5       ; play it safe, preserve all regs    ENDC_deflate:           ; first, setup steps common to deflate and deflate_fast:        movem.l DEFREGS,-(sp)    IFD     INT16        moveq   #0,Strst                ; make sure strstart is valid as a long    ENDC        moveq   #0,Head                 ; ditto for hash_head        MOVINT  _strstart,Strst        move.w  lookahead,Look        move.w  prev_length,PrevL        BASEPTR _window,Window        BASEPTR _prev,Prev        MOVINT  _level,d0        cmp.w   #3,d0        ble     deflate_fast        moveq   #MIN_MATCH-1,MatchL        moveq   #0,Availlook_loop:        tst.w   Look        beq     last_tally        IN_STR  a0,d0        move.w  MatchL,PrevL        move.w  match_start,PrevM        move.w  #MIN_MATCH-1,MatchL        tst.w   Head        beq.s   no_new_match        cmp.w   max_lazy_match,PrevL        bhs.s   no_new_match        move.w  Strst,d0        sub.w   Head,d0        cmp.w   #MAX_DIST,d0        bhi.s   no_new_match        move.w  PrevL,prev_length       ; longest_match reads these variables        MOVINT  Strst,_strstart        MOVINT  Head,d0                 ; parm for longest_match        bsr     longest_match           ; sets match_start        cmp.w   Look,d0                 ; does length exceed valid data?        bls.s   stml        move.w  Look,d0stml:   move.w  d0,MatchL               ; valid length of match        cmp.w   #MIN_MATCH,MatchL       ; is the match only three bytes?        bne.s   no_new_match        move.w  match_start,d0        sub.w   Strst,d0        cmp.w   #-TOO_FAR,d0        bge.s   no_new_match        moveq   #MIN_MATCH-1,MatchL     ; mark the current match as no goodno_new_match:        cmp.w   #MIN_MATCH,PrevL        blo     literal        cmp.w   MatchL,PrevL        blo     literal        ; CHECK_MATCH   Strst-1,PrevM,PrevL        MOVINT  Strst,_strstart         ; ct_tally reads this variable        move.l  PrevL,d0        subq.w  #MIN_MATCH,d0        MOVINT  d0,-(sp)        move.l  Strst,d0        sub.w   PrevM,d0        subq.w  #1,d0        MOVINT  d0,-(sp)        jsr     _ct_tally               ; sets d0 true if we have to flush        addq    #2*INTSIZE,sp        subq.w  #3,PrevL                ; convert for dbra (prev_length - 2)        sub.w   PrevL,Look        subq.w  #2,Lookinsertmatch:        addq.w  #1,Strst        IN_STR  a0,d1                   ; don't clobber d0        dbra    PrevL,insertmatch        moveq   #0,Avail        moveq   #0,PrevL                ; not needed?        moveq   #MIN_MATCH-1,MatchL        addq.w  #1,Strst        tst.w   d0        beq     refill        FLUSH_B #0        move.l  Strst,_block_start        bra.s   refillliteral:        tst.w   Avail        bne.s   yeslit        moveq   #1,Avail        bra.s   skipliteralyeslit: TRACE_C <-1(Window,Strst.l)>        MOVINT  Strst,_strstart         ; ct_tally reads this variable        moveq   #0,d0        move.b  -1(Window,Strst.l),d0        MOVINT  d0,-(sp)        CLRINT  -(sp)        jsr     _ct_tally        addq    #2*INTSIZE,sp        tst.w   d0        beq.s   skipliteral        FLUSH_B #0        move.l  Strst,_block_startskipliteral:        addq.w  #1,Strst        subq.w  #1,Lookrefill:        cmp.w   #MIN_LOOKAHEAD,Look        bhs     look_loop        bsr     fill_window        bra     look_looplast_tally:        tst.w   Avail        beq     last_flush        MOVINT  Strst,_strstart         ; ct_tally reads this variable        moveq   #0,d0        move.b  -1(Window,Strst.l),d0        MOVINT  d0,-(sp)        CLRINT  -(sp)        jsr     _ct_tally        addq    #2*INTSIZE,splast_flush:        FLUSH_B #1        bra     deflate_exit; ================== This is another version used for low compression levels:deflate_fast:        moveq   #0,MatchL        moveq   #MIN_MATCH-1,PrevLflook_loop:        tst.w   Look        beq     flast_flush        IN_STR  a0,d0        tst.w   Head        beq.s   fno_new_match        move.w  Strst,d0        sub.w   Head,d0        cmp.w   #MAX_DIST,d0        bhi.s   fno_new_match        move.w  PrevL,prev_length       ; longest_match reads these variables        MOVINT  Strst,_strstart        MOVINT  Head,d0                 ; parm for longest_match        bsr     longest_match           ; sets match_start

⌨️ 快捷键说明

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