?? flate.a
字號:
jsr _memflush ; ignores the unshrink flag bra.s fe\@fm\@: jsr _flushfe\@: lea 8+INTSIZE+G_SIZE(sp),sp ENDM ENDC ; ?FUNZIP; Here are the two bit-grabbing macros, defined in their NO_CHECK_EOF form:;; #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}; #define DUMPBITS(n) {b>>=(n);k-=(n);};; Without NO_CHECK_EOF, NEEDBITS reads like this:;; {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;b|=((ulg)c)<<k;k+=8;}};; NEEDBITS clobbers d0, d1, a0, and a1, none of which can be used as the arg; to the macro specifying the number of bits. The arg can be a shortword memory; address, or d2-d7. The result is copied into d1 as a word ready for masking.; DUMPBITS has no side effects; the arg must be a d-register (or immediate in the; range 1-8?) and only the lower byte is significant.NEEDBITS MACRO ; arg is shortnb\@: cmp.w \1,k ; assert 0 < k <= 32 ... arg may be 0 bhs.s ne\@ NEXTBYTE ; returns in d0.l IFND NO_CHECK_EOF cmp.w #EOF,d0 bne.s nok\@ moveq #RET_ERR,d0 bra return ENDC ; !NO_CHECK_EOFnok\@: lsl.l k,d0 or.l d0,b addq.w #8,k bra.s nb\@ne\@: move.l b,d1 ; return a copy of b in d1 xdef nb\@ ; XXX TEMPORARY xdef ne\@ ENDMDUMPBITS MACRO ; arg is byte, not short! lsr.l \1,b ; upper bits of \1 are ignored, right? sub.b \1,k ENDM; This is a longword version of the mask_bits constant array:longmasks: dc.l $00000000,$00000001,$00000003,$00000007,$0000000F dc.l $0000001F,$0000003F,$0000007F,$000000FF,$000001FF dc.l $000003FF,$000007FF,$00000FFF,$00001FFF,$00003FFF dc.l $00007FFF,$0000FFFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0 xdef longmasks ; XXX; ******************************************************************************; Here we go, finally: xdef _inflate_codes_inflate_codes: link a5,#-8 movem.l savregs,-(sp); 8(a5) = tl, 12(a5) = td, 16(a5) = bl, 18|20(a5) = bd... add 4 for REENT_G; -4(a5) = ml, -8(a5) = md, both unsigned long.; Here we cache some globals and args: IFD REENT_G move.l 8(a5),G ELSE lea _G,G ; G is now a global instance ENDC lea longmasks,lmask move.l bb(G),b MOVINT bk(G),k IFD INT16 moveq #0,w ; keep this usable as longword ENDC MOVINT wp(G),w moveq #0,e ; keep this usable as longword too MOVINT 16+G_SIZE(a5),d0 asl.w #2,d0 move.l (lmask,d0.w),-4(a5) ; ml = mask_bits[bl] MOVINT 16+INTSIZE+G_SIZE(a5),d0 asl.w #2,d0 move.l (lmask,d0.w),-8(a5) ; md = mask_bits[bd] xdef main_loop ; XXX TEMPORARY xdef newtop xdef nonlit xdef distop xdef docopy xdef nonleng xdef tailgo xdef finish xdef disbrkmain_loop: nop ; XXX TEMPORARY NEEDBITS 14+INTSIZE+G_SIZE(a5) ; (unsigned) bl and.l -4(a5),d1 ; ml IFNE SIZEOF_huft-8 mulu #SIZEOF_huft,d1 ELSE asl.l #3,d1 ENDC move.l 8+G_SIZE(a5),t ; tl add.l d1,tnewtop: move.b h_b(t),d0 DUMPBITS d0 move.b h_e(t),e cmp.b #32,e ; is it a literal? bne nonlit ; no move.w h_v_n(t),d0 ; yes IFGT SIZEOF_slide-4 lea redirslide(G),a0 ELSE move.l redirslide(G),a0 ENDC move.b d0,(a0,w.l) ; stick in the decoded byte addq.l #1,w cmp.l #WSIZE,w blo main_loop FLUSH w ext.l d0 ; does a test as it casts long bne return moveq #0,w bra main_loop ; break (newtop loop)nonlit: cmp.b #31,e ; is it a length? beq finish ; no, it's the end marker bhi nonleng ; no, it's something else NEEDBITS e ; yes: a duplicate string move.w e,d0 asl.w #2,d0 and.l (lmask,d0.w),d1 moveq #0,n ; cast h_v_n(t) to long move.w h_v_n(t),n add.l d1,n ; length of block to copy DUMPBITS e NEEDBITS 14+(2*INTSIZE)+G_SIZE(a5) ; bd, lower word if long and.l -8(a5),d1 ; md IFNE SIZEOF_huft-8 mulu #SIZEOF_huft,d1 ELSE asl.l #3,d1 ENDC move.l 12+G_SIZE(a5),t ; td add.l d1,tdistop: move.b h_b(t),d0 DUMPBITS d0 move.b h_e(t),e cmp.b #32,e ; is it a literal? blo.s disbrk ; then stop doing this cmp.b #INVALID,e ; is it bogus? bne.s disgo moveq #RET_ERR,d0 ; then fail bra returndisgo: and.w #$001F,e NEEDBITS e move.w e,d0 asl.w #2,d0 and.l (lmask,d0.w),d1 IFNE SIZEOF_huft-8 mulu #SIZEOF_huft,d1 ELSE asl.l #3,d1 ENDC move.l h_v_t(t),t add.l d1,t bra distopdisbrk: NEEDBITS e move.l e,d0 asl.w #2,d0 and.l (lmask,d0.w),d1 move.l w,d move.w h_v_n(t),d0 ; assert top word of d0 is zero sub.l d0,d sub.l d1,d ; distance back to copy the block DUMPBITS edocopy: move.l #WSIZE,e ; copy the duplicated string and.l #WSIZE-1,d ; ...but first check if the length cmp.l d,w ; will overflow the window... blo.s ddgw sub.l w,e bra.s dadwddgw: sub.l d,edadw: cmp.l #$08000,e ; also, only copy <= 32K, so we can bls.s dnox ; use a dbra loop to do it move.l #$08000,ednox: cmp.l n,e bls.s delen move.l n,edelen: sub.l e,n ; size of sub-block to copy in this pass IFGT SIZEOF_slide-4 lea redirslide(G),a0 ELSE move.l redirslide(G),a0 ENDC move.l a0,a1 add.l w,a0 add.l d,a1; Now at this point we could do tests to see if we should use an optimized; large block copying method such as movem's, but since (a) such methods require; the source and destination to be compatibly aligned -- and odd bytes at each; end have to be handled separately, (b) it's only worth checking for if the; block is pretty large, and (c) most strings are only a few bytes long, we're; just not going to bother. Therefore we check above to make sure we move at; most 32K in one sub-block, so a dbra loop can handle it.dshort: move.l e,d0 subq #1,d0 ; assert >= 0dspin: move.b (a1)+,(a0)+ dbra d0,dspin add.l e,w add.l e,d cmp.l #WSIZE,w blo.s dnfl FLUSH w ext.l d0 ; does a test as it casts to long bne return moveq #0,wdnfl: tst.l n ; need to do more sub-blocks? bne docopy ; yes moveq #0,e ; restore zeroness in upper bytes of e bra main_loop ; break (newtop loop)nonleng: cmp.w #INVALID,e ; bottom of newtop loop -- misc. code bne.s tailgo ; invalid code? moveq #RET_ERR,d0 ; then fail bra returntailgo: and.w #$001F,e NEEDBITS e move.w e,d0 asl.w #2,d0 and.l (lmask,d0.w),d1 IFNE SIZEOF_huft-8 mulu #SIZEOF_huft,d1 ELSE asl.l #3,d1 ENDC move.l h_v_t(t),t add.l d1,t bra newtopfinish: MOVINT w,wp(G) ; done: restore cached globals MOVINT k,bk(G) move.l b,bb(G) moveq #RET_OK,d0 ; return "no error"return: movem.l (sp)+,savregs unlk a5 rts
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -