flate.s 19 KB

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