Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ;===========================================================================
  2. ; Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.
  3. ;
  4. ; See the accompanying file LICENSE, version 2000-Apr-09 or later
  5. ; (the contents of which are also included in unzip.h) for terms of use.
  6. ; If, for some reason, all these files are missing, the Info-ZIP license
  7. ; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  8. ;===========================================================================
  9. ; flate.a created by Paul Kienitz, 20 June 94.  Last modified 23 Mar 2002.
  10. ;
  11. ; 68000 assembly language version of inflate_codes(), for Amiga.  Prototype:
  12. ;
  13. ;   int inflate_codes(__GPRO__ struct huft *tl, struct huft *td,
  14. ;                     unsigned bl, unsigned bd);
  15. ;
  16. ; Where __GPRO__ expands to "Uz_Globs *G," if REENTRANT is defined,
  17. ; otherwise to nothing.  In the latter case G is a global variable.
  18. ;
  19. ; Define the symbol FUNZIP if this is for fUnZip.  It overrides REENTRANT.
  20. ;
  21. ; Define AZTEC to use the Aztec C macro version of getc() instead of the
  22. ; library getc() with FUNZIP.  AZTEC is ignored if FUNZIP is not defined.
  23. ;
  24. ; Define NO_CHECK_EOF to not use the fancy paranoid version of NEEDBITS --
  25. ; this is equivalent to removing the #define CHECK_EOF from inflate.c.
  26. ;
  27. ; Define INT16 if ints are short, otherwise it assumes ints are long.
  28. ;
  29. ; Define USE_DEFLATE64 if we're supporting Deflate64 decompression.
  30. ;
  31. ; Do NOT define WSIZE; it is always 32K or 64K depending on USE_DEFLATE64.
  32. ;
  33. ; 1999/09/23: for Human68k: Modified by Shimazaki Ryo.
  34.  
  35. X:              EQU     $7ffe
  36.  
  37.                 IFDEF   INT16
  38. MOVINT           MACRO  _1,_2
  39.         move.w          _1,_2
  40.                  ENDM
  41. INTSIZE equ     2
  42.                 ELSE    ; !INT16
  43. MOVINT           MACRO  _1,_2
  44.         move.l          _1,_2
  45.                  ENDM
  46. INTSIZE equ     4
  47.                 ENDC
  48.  
  49.                 IFDEF   REENTRANT
  50.                  IFNDEF FUNZIP
  51. REENT_G equ     1
  52.                  ENDC
  53.                 ENDC
  54.  
  55. ; The following include file is generated from globals.h, and gives us equates
  56. ; that give the offsets in Uz_Globs of the fields we use, which are:
  57. ;       ulg bb
  58. ;       unsigned int bk, wp
  59. ;       (either array of unsigned char, or pointer to unsigned char) redirslide
  60. ; For fUnZip:
  61. ;       FILE *in
  62. ; For regular UnZip but not fUnZip:
  63. ;       int incnt, mem_mode
  64. ;       long csize
  65. ;       uch *inptr
  66. ; It also defines a value SIZEOF_slide, which tells us whether the appropriate
  67. ; slide field in G (either area.Slide or redirect_pointer) is a pointer or an
  68. ; array instance.  It is 4 in the former case and a large value in the latter.
  69. ; Lastly, this include will define CRYPT as 1 if appropriate.
  70.  
  71.                 IFDEF   FUNZIP
  72.         INCLUDE  human68k/G_offs_.mac
  73.                 ELSE
  74.                  IFDEF  SFX
  75.         INCLUDE  human68k/G_offsf.mac"
  76.                  ELSE
  77.         INCLUDE  human68k/G_offs.mac
  78.                  ENDC
  79.                 ENDC
  80.  
  81. ; struct huft is defined as follows:
  82. ;
  83. ;   struct huft {
  84. ;     uch e;                /* number of extra bits or operation */
  85. ;     uch b;                /* number of bits in this code or subcode */
  86. ;     union {
  87. ;       ush n;              /* literal, length base, or distance base */
  88. ;       struct huft *t;     /* pointer to next level of table */
  89. ;     } v;
  90. ;   };                      /* sizeof(struct huft) == 6 */
  91. ;
  92. ; The G_offs include defines offsets h_e, h_b, h_v_n, and h_v_t in this
  93. ; struct, plus SIZEOF_huft.
  94.  
  95. ; G.bb is the global buffer that holds bits from the huffman code stream, which
  96. ; we cache in the register variable b.  G.bk is the number of valid bits in it,
  97. ; which we cache in k.  The macros NEEDBITS(n) and DUMPBITS(n) have side effects
  98. ; on b and k.
  99.  
  100.                 IFDEF   REENT_G
  101. G_SIZE  equ     4
  102. G_PUSH           MACRO          ; this macro passes "__G__" to functions
  103.         move.l          G,-(sp)
  104.                  ENDM
  105.                 ELSE
  106.         xref    _G              ; Uz_Globs
  107. G_SIZE  equ     0
  108. G_PUSH           MACRO
  109.         ds.b            0       ; does nothing; the assembler dislikes MACRO ENDM
  110.                  ENDM
  111.                 ENDC    ; REENT_G
  112.  
  113. ;;      xref    _mask_bits      ; const unsigned mask_bits[17];
  114.                 IFDEF   FUNZIP
  115.                  IF     CRYPT
  116.         xref    _encrypted      ; int -- boolean flag
  117.         xref    _update_keys    ; int update_keys(__GPRO__ int)
  118.         xref    _decrypt_byte   ; int decrypt_byte(__GPRO)
  119.                  ENDC   ; CRYPT
  120.                 ELSE    ; !FUNZIP
  121.         xref    _memflush       ; int memflush(__GPRO__ uch *, ulg)
  122.         xref    _readbyte       ; int readbyte(__GPRO)
  123.                 ENDC    ; FUNZIP
  124.  
  125.         xref    _flush          ; if FUNZIP:  int flush(__GPRO__ ulg)
  126.                                 ; else:  int flush(__GPRO__ uch *, ulg, int)
  127.  
  128. ; Here are our register variables.
  129.  
  130. b       reg     d2              ; unsigned long
  131. k       reg     d3              ; unsigned short <= 32
  132. e       reg     d4              ; unsigned int, mostly used as unsigned char
  133. w       reg     d5              ; unsigned long (was short before deflate64)
  134. n       reg     d6              ; unsigned long (was short before deflate64)
  135. d       reg     d7              ; unsigned int, used as unsigned short
  136.  
  137. t       reg     a2              ; struct huft *
  138. lmask   reg     a3              ; ulg *
  139. G       reg     a6              ; Uz_Globs *
  140.  
  141. ; Couple other items we need:
  142.  
  143. savregs reg     d2-d7/a2/a3/a6
  144.                 IFDEF   USE_DEFLATE64
  145. WSIZE   equ     $10000          ; 64K... be careful not to treat as short!
  146.                 ELSE
  147. WSIZE   equ     $08000          ; 32K... be careful not to treat as negative!
  148.                 ENDC
  149. EOF     equ     -1
  150. INVALID equ     99
  151.  
  152. ; inflate_codes() returns one of the following status codes:
  153. ;          0  OK
  154. ;          1  internal inflate error or EOF on input stream
  155. ;         the following return codes are passed through from FLUSH() errors
  156. ;          50 (PK_DISK)   "overflow of output space"
  157. ;          80 (IZ_CTRLC)  "canceled by user's request"
  158.  
  159. RET_OK  equ     0
  160. RET_ERR equ     1
  161.  
  162.                 IFDEF   FUNZIP
  163. ; This does getc(in).  LIBC version is based on #define getc(fp) in stdio.h
  164.  
  165. GETC              MACRO
  166.         xref    _fgetc          ; int fgetc(FILE *)
  167.         move.l          in-X(G),-(sp)
  168.         jsr             _fgetc
  169.         addq.l          #4,sp
  170.                   ENDM
  171.                 ENDC    ; FUNZIP
  172.  
  173. ; Input depends on the NEXTBYTE macro.  This exists in three different forms.
  174. ; The first two are for fUnZip, with and without decryption.  The last is for
  175. ; regular UnZip with or without decryption.  The resulting byte is returned
  176. ; in d0 as a longword, and d1, a0, and a1 are clobbered.
  177.  
  178. ; FLUSH also has different forms for UnZip and fUnZip.  Arg must be a longword.
  179. ; The same scratch registers are trashed.
  180.  
  181.                 IFDEF   FUNZIP
  182.  
  183. NEXTBYTE         MACRO
  184.         move.l   d2,-(sp)
  185.         GETC
  186.                   IF    CRYPT
  187.         tst.w           _encrypted+INTSIZE-2    ; test low word if long
  188.         beq.s           @nbe
  189.         MOVINT          d0,-(sp)                ; save thru next call
  190.         G_PUSH
  191.         jsr             _decrypt_byte
  192.         eor.w           d0,G_SIZE+INTSIZE-2(sp) ; becomes arg to update_keys
  193.         jsr             _update_keys
  194.         addq            #INTSIZE+G_SIZE,sp
  195. @nbe:
  196.                   ENDC  ; !CRYPT
  197.                   IFEQ INTSIZE-2
  198.         ext.l           d0              ; assert -1 <= d0 <= 255
  199.                   ENDC
  200.         move.l   (sp)+,d2
  201.                  ENDM
  202.  
  203. FLUSH            MACRO  _1
  204.         move.l          d2,-(sp)
  205.         move.l          _1,-(sp)
  206.         G_PUSH
  207.         jsr             _flush
  208.         addq            #4+G_SIZE,sp
  209.         move.l          (sp)+,d2
  210.                  ENDM
  211.  
  212.                 ELSE    ; !FUNZIP
  213.  
  214. NEXTBYTE         MACRO
  215.         subq.w          #1,incnt+INTSIZE-2-X(G)   ; treat as short
  216.         bge.s           @nbs
  217.                 IFNE INTSIZE-2
  218.         subq.w          #1,incnt-X(G)
  219.         bge.s           @nbs
  220.                 ENDIF
  221.         move.l          d2,-(sp)
  222.         G_PUSH
  223.         jsr             _readbyte
  224.                   IFNE G_SIZE
  225.         addq            #G_SIZE,sp
  226.                   ENDC
  227.         move.l          (sp)+,d2
  228.                   IFEQ 2-INTSIZE
  229.         ext.l           d0            ; assert -1 <= d0 <= 255
  230.                   ENDC
  231.         bra.s           @nbe
  232. @nbs:   moveq           #0,d0
  233.         move.l          inptr-X(G),a0
  234.         move.b          (a0)+,d0
  235.         move.l          a0,inptr-X(G)
  236. @nbe:
  237.                  ENDM
  238.  
  239. FLUSH            MACRO  _1
  240.         move.l          d2,-(sp)
  241.         clr.l           -(sp)                   ; unshrink flag: always false
  242.         move.l          _1,-(sp)                ; length
  243.                   IF    SIZEOF_slide>4
  244.         pea             redirslide-X(G)           ; buffer to flush
  245.                   ELSE
  246.         move.l          redirslide-X(G),-(sp)
  247.                   ENDC
  248.         G_PUSH
  249.         tst.w           mem_mode+INTSIZE-2-X(G)   ; test lower word if long
  250.         beq.s           @fm
  251.         jsr             _memflush               ; ignores the unshrink flag
  252.         bra.s           @fe
  253. @fm:    jsr             _flush
  254. @fe:    lea             8+INTSIZE+G_SIZE(sp),sp
  255.         move.l          (sp)+,d2
  256.                  ENDM
  257.  
  258.                 ENDC    ; ?FUNZIP
  259.  
  260. ; Here are the two bit-grabbing macros, defined in their NO_CHECK_EOF form:
  261. ;
  262. ;   #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
  263. ;   #define DUMPBITS(n) {b>>=(n);k-=(n);}
  264. ;
  265. ; Without NO_CHECK_EOF, NEEDBITS reads like this:
  266. ;
  267. ;   {while((int)k<(int)(n)){int c=NEXTBYTE;
  268. ;                           if(c==EOF){if((int)k>=0)break;return 1};
  269. ;                           b|=((ulg)c)<<k;k+=8;}}
  270. ;
  271. ; NEEDBITS clobbers d0, d1, a0, and a1, none of which can be used as the arg to
  272. ; the macro specifying the number of bits.  The arg can be a shortword memory
  273. ; address, or d2-d7.  The result is copied into d1 as a word ready for masking.
  274. ; DUMPBITS has no side effects; the arg must be a d-register (or immediate in
  275. ; the range 1-8?) and only the lower byte is significant.
  276.  
  277. NEEDBITS        MACRO   _1
  278. @nb:    cmp.w           _1,k            ; assert 0 < k <= 32 ... arg may be 0
  279.         bge.s           @ne             ; signed compare!
  280. @loop:
  281.         NEXTBYTE                        ; returns in d0.l
  282.                  IFNDEF NO_CHECK_EOF
  283.         cmp.w           #EOF,d0
  284.         bne.s           @nok
  285.         tst.w           k
  286.         bge.s           @ne
  287.         bra             error_return
  288.                  ENDC   ; !NO_CHECK_EOF
  289. @nok:   lsl.l           k,d0
  290.         or.l            d0,b
  291.         addq.w          #8,k
  292.         cmp.w           _1,k            ;bra.s @nb
  293.         bcs             @loop           ;
  294. @ne:    move.l          b,d1            ; return a copy of b in d1
  295.                 ENDM
  296.  
  297. DUMPBITS        MACRO   _1
  298.         lsr.l           _1,b            ; upper bits of _1 are ignored??
  299.         sub.b           _1,k
  300.                 ENDM
  301.  
  302.  
  303. ; This is a longword version of the mask_bits constant array:
  304. longmasks:      dc.l    $00000000,$00000001,$00000003,$00000007,$0000000F
  305.                 dc.l    $0000001F,$0000003F,$0000007F,$000000FF,$000001FF
  306.                 dc.l    $000003FF,$000007FF,$00000FFF,$00001FFF,$00003FFF
  307.                 dc.l    $00007FFF,$0000FFFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  308.  
  309.  
  310. ; ******************************************************************************
  311. ; Here we go, finally:
  312.  
  313.         xdef    _inflate_codes
  314.  
  315. _inflate_codes:
  316.         link            a5,#-8
  317.         movem.l         savregs,-(sp)
  318. ; 8(a5) = tl, 12(a5) = td, 16(a5) = bl, 18|20(a5) = bd... add 4 for REENT_G
  319. ; -4(a5) = ml, -8(a5) = md, both unsigned long.
  320. ; Here we cache some globals and args:
  321.                 IFDEF   REENT_G
  322.         move.l          8(a5),G
  323.                 ELSE
  324.         lea             _G,G            ; G is now a global instance
  325.                 IFDEF   X
  326.         lea             (X,G),G
  327.                 ENDIF
  328.                 ENDC
  329.         lea             longmasks,lmask
  330.         move.l          bb-X(G),b
  331.         MOVINT          bk-X(G),k
  332.                 IFDEF   INT16
  333.         moveq           #0,w            ; keep this usable as longword
  334.                 ENDC
  335.         MOVINT          wp-X(G),w
  336.         moveq           #0,e            ; keep this usable as longword too
  337.         MOVINT          16+G_SIZE(a5),d0
  338.         asl.w           #2,d0
  339.         move.l          (lmask,d0.w),-4(a5)     ; ml = mask_bits[bl]
  340.         MOVINT          16+INTSIZE+G_SIZE(a5),d0
  341.         asl.w           #2,d0
  342.         move.l          (lmask,d0.w),-8(a5)     ; md = mask_bits[bd]
  343.  
  344. main_loop:
  345.         NEEDBITS        14+INTSIZE+G_SIZE(a5)   ; (unsigned) bl
  346.         and.l           -4(a5),d1               ; ml
  347.                 IFNE SIZEOF_huft-8
  348.         mulu            #SIZEOF_huft,d1
  349.                 ELSE
  350.         asl.l           #3,d1
  351.                 ENDC
  352.         move.l          8+G_SIZE(a5),t          ; tl
  353.         add.l           d1,t
  354. newtop:  move.b         h_b(t),d0
  355.          DUMPBITS       d0
  356.          move.b         h_e(t),e
  357.          cmp.b          #32,e                   ; is it a literal?
  358.          bne            nonlit                  ; no
  359.           move.w        h_v_n(t),d0             ; yes
  360.                 IFGT SIZEOF_slide-4
  361.           lea           redirslide-X(G),a0
  362.                 ELSE
  363.           move.l        redirslide-X(G),a0
  364.                 ENDC
  365.           move.b        d0,(a0,w.l)             ; stick in the decoded byte
  366.           addq.l        #1,w
  367.           cmp.l         #WSIZE,w
  368.           blo           main_loop
  369.            FLUSH        w
  370.            ext.l        d0                      ; does a test as it casts long
  371.            bne          return
  372.            moveq        #0,w
  373.            bra          main_loop               ; break (newtop loop)
  374.  
  375. nonlit:  cmp.b          #31,e                   ; is it a length?
  376.          beq            finish                  ; no, it's the end marker
  377.          bhi            nonleng                 ; no, it's something else
  378.           NEEDBITS      e                       ; yes: a duplicate string
  379.           move.w        e,d0
  380.           asl.w         #2,d0
  381.           and.l         (lmask,d0.w),d1
  382.           moveq         #0,n                    ; cast h_v_n(t) to long
  383.           move.w        h_v_n(t),n
  384.           add.l         d1,n                    ; length of block to copy
  385.           DUMPBITS      e
  386.           NEEDBITS      14+(2*INTSIZE)+G_SIZE(a5)   ; bd, lower word if long
  387.           and.l         -8(a5),d1                   ; md
  388.                 IFNE SIZEOF_huft-8
  389.           mulu          #SIZEOF_huft,d1
  390.                 ELSE
  391.           asl.l         #3,d1
  392.                 ENDC
  393.           move.l        12+G_SIZE(a5),t                 ; td
  394.           add.l         d1,t
  395. distop:    move.b       h_b(t),d0
  396.            DUMPBITS     d0
  397.            move.b       h_e(t),e
  398.            cmp.b        #32,e                   ; is it a literal?
  399.            blo.s        disbrk                  ; then stop doing this
  400.             cmp.b       #INVALID,e              ; is it bogus?
  401.             bne.s       disgo
  402.              bra        error_return            ; then fail
  403. disgo:      and.w       #$001F,e
  404.             NEEDBITS    e
  405.             move.w      e,d0
  406.             asl.w       #2,d0
  407.             and.l       (lmask,d0.w),d1
  408.                 IFNE SIZEOF_huft-8
  409.             mulu        #SIZEOF_huft,d1
  410.                 ELSE
  411.             asl.l       #3,d1
  412.                 ENDC
  413.             move.l      h_v_t(t),t
  414.             add.l       d1,t
  415.             bra         distop
  416. disbrk:   NEEDBITS      e
  417.           move.l        e,d0
  418.           asl.w         #2,d0
  419.           and.l         (lmask,d0.w),d1
  420.           move.l        w,d
  421.           move.w        h_v_n(t),d0     ; assert top word of d0 is zero
  422.           sub.l         d0,d
  423.           sub.l         d1,d            ; distance back to copy the block
  424.           DUMPBITS      e
  425.  
  426. docopy:    move.l       #WSIZE,e        ; copy the duplicated string
  427.            and.l        #WSIZE-1,d      ; ...but first check if the length
  428.            cmp.l        d,w             ; will overflow the window...
  429.            blo.s        ddgw
  430.             sub.l       w,e
  431.            bra.s        dadw
  432. ddgw:       sub.l       d,e
  433. dadw:      cmp.l        #$08000,e       ; also, only copy <= 32K, so we can
  434.            bls.s        dnox            ; use a dbra loop to do it
  435.             move.l      #$08000,e
  436. dnox:      cmp.l        n,e
  437.            bls.s        delen
  438.             move.l      n,e
  439. delen:     sub.l        e,n             ; size of sub-block to copy in this pass
  440.                 IF      SIZEOF_slide>4
  441.            lea          redirslide-X(G),a0
  442.                 ELSE
  443.            move.l       redirslide-X(G),a0
  444.                 ENDC
  445.            move.l       a0,a1
  446.            add.l        w,a0            ; w and d are valid longwords
  447.            add.l        d,a1
  448. ; Now at this point we could do tests to see if we should use an optimized
  449. ; large block copying method such as movem's, but since (a) such methods require
  450. ; the source and destination to be compatibly aligned -- and odd bytes at each
  451. ; end have to be handled separately, (b) it's only worth checking for if the
  452. ; block is pretty large, and (c) most strings are only a few bytes long, we're
  453. ; just not going to bother.  Therefore we check above to make sure we move at
  454. ; most 32K in one sub-block, so a dbra loop can handle it.
  455. dshort:    move.l       e,d0
  456.            subq         #1,d0           ; assert >= 0
  457. dspin:      move.b      (a1)+,(a0)+
  458.             dbra        d0,dspin
  459.            add.l        e,w
  460.            add.l        e,d
  461.            cmp.l        #WSIZE,w
  462.            blo.s        dnfl
  463.             FLUSH       w
  464.             ext.l       d0              ; does a test as it casts to long
  465.             bne         return
  466.             moveq       #0,w
  467. dnfl:      tst.l        n               ; need to do more sub-blocks?
  468.            bne          docopy          ; yes
  469.           moveq         #0,e            ; restore zeroness in upper bytes of e
  470.           bra           main_loop       ; break (newtop loop)
  471.  
  472. nonleng: cmp.w          #INVALID,e      ; bottom of newtop loop -- misc. code
  473.          bne.s          tailgo          ; invalid code?
  474.           bra           error_return    ; then fail
  475. tailgo:  and.w          #$001F,e
  476.          NEEDBITS       e
  477.          move.w         e,d0
  478.          asl.w          #2,d0
  479.          and.l          (lmask,d0.w),d1
  480.                 IFNE SIZEOF_huft-8
  481.          mulu           #SIZEOF_huft,d1
  482.                 ELSE
  483.          asl.l          #3,d1
  484.                 ENDC
  485.          move.l         h_v_t(t),t
  486.          add.l          d1,t
  487.          bra            newtop
  488.  
  489. finish: MOVINT          w,wp-X(G)       ; done: restore cached globals
  490.         MOVINT          k,bk-X(G)
  491.         move.l          b,bb-X(G)
  492.         moveq           #RET_OK,d0      ; return "no error"
  493. return: movem.l         (sp)+,savregs
  494.         unlk            a5
  495.         rts
  496.  
  497. error_return:
  498.         moveq           #RET_ERR,d0     ; return "error occured"
  499.         bra             return
  500.