home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip540.zip / msdos / crc_i86.asm < prev    next >
Assembly Source File  |  1997-04-06  |  10KB  |  434 lines

  1. ; Not copyrighted by Christian Spieler, 02 Apr 1997.
  2. ;
  3.         TITLE   crc_i86.asm
  4.         NAME    crc_i86
  5. ;
  6. ; Optimized 8086 assembler version of the CRC32 calculation loop, intended
  7. ; for real mode Info-ZIP programs (Zip 2.1, UnZip 5.2, and later versions).
  8. ; Supported compilers are Microsoft C (DOS real mode) and Borland C(++)
  9. ; (Turbo C). Watcom C (16bit) should also work.
  10. ; This module was inspired by a similar module for the Amiga (Paul Kienitz).
  11. ;
  12. ; It replaces the `ulg crc32(ulg crc, ZCONST uch *buf, extent len)' function
  13. ; in crc32.c.
  14. ;
  15. ; In March/April 1997, the code has been revised to incorporate Rodney Brown's
  16. ; ideas for optimized access to the data buffer. For 8086 real mode code,
  17. ; the data buffer is now accessed by aligned word-wide read operations.
  18. ; This new optimization may be turned off by defining the macro switch
  19. ; NO_16_BIT_LOADS.
  20. ;
  21. ; The code in this module should work with all kinds of C memory models
  22. ; (except Borland's __HUGE__ model), as long as the following
  23. ; restrictions are not violated:
  24. ;
  25. ; - The implementation assumes that the char buffer is confined to a
  26. ;   64k segment. The pointer `s' to the buffer must be in a format that
  27. ;   all bytes can be accessed by manipulating the offset part, only.
  28. ;   This means:
  29. ;   + no huge pointers
  30. ;   + char buffer size < 64 kByte
  31. ;
  32. ; - Since the buffer size argument `n' is of type `size_t' (= unsigned short)
  33. ;   for this routine, the char buffer size is limited to less than 64 kByte,
  34. ;   anyway. So, the assumption above should be easily fulfilled.
  35. ;
  36. ;==============================================================================
  37. ;
  38. ; Do NOT assemble this source if external crc32 routine from zlib gets used.
  39. ;
  40. ifndef USE_ZLIB
  41. ;
  42. ; Setup of amount of assemble time informational messages:
  43. ;
  44. ifdef     DEBUG
  45.   VERBOSE_INFO EQU 1
  46. else
  47.   ifdef _AS_MSG_
  48.     VERBOSE_INFO EQU 1
  49.   else
  50.     VERBOSE_INFO EQU 0
  51.   endif
  52. endif
  53. ;
  54. ; Selection of memory model, and initialization of memory model
  55. ; related macros:
  56. ;
  57. ifndef __SMALL__
  58.   ifndef __COMPACT__
  59.     ifndef __MEDIUM__
  60.       ifndef __LARGE__
  61.         ifndef __HUGE__
  62. ;         __SMALL__ EQU 1
  63.         endif
  64.       endif
  65.     endif
  66.   endif
  67. endif
  68.  
  69. ifdef __HUGE__
  70. ; .MODEL Huge
  71.    @CodeSize  EQU 1
  72.    @DataSize  EQU 1
  73.    Save_DS    EQU 1
  74.    if VERBOSE_INFO
  75.     if1
  76.       %out Assembling for C, Huge memory model
  77.     endif
  78.    endif
  79. else
  80.    ifdef __LARGE__
  81. ;      .MODEL Large
  82.       @CodeSize  EQU 1
  83.       @DataSize  EQU 1
  84.       if VERBOSE_INFO
  85.        if1
  86.          %out Assembling for C, Large memory model
  87.        endif
  88.       endif
  89.    else
  90.       ifdef __COMPACT__
  91. ;         .MODEL Compact
  92.          @CodeSize  EQU 0
  93.          @DataSize  EQU 1
  94.          if VERBOSE_INFO
  95.           if1
  96.             %out Assembling for C, Compact memory model
  97.           endif
  98.          endif
  99.       else
  100.          ifdef __MEDIUM__
  101. ;            .MODEL Medium
  102.             @CodeSize  EQU 1
  103.             @DataSize  EQU 0
  104.             if VERBOSE_INFO
  105.              if1
  106.                %out Assembling for C, Medium memory model
  107.              endif
  108.             endif
  109.          else
  110. ;            .MODEL Small
  111.             @CodeSize  EQU 0
  112.             @DataSize  EQU 0
  113.             if VERBOSE_INFO
  114.              if1
  115.                %out Assembling for C, Small memory model
  116.              endif
  117.             endif
  118.          endif
  119.       endif
  120.    endif
  121. endif
  122.  
  123. if @CodeSize
  124.         LCOD_OFS        EQU     2
  125. else
  126.         LCOD_OFS        EQU     0
  127. endif
  128.  
  129. IF @DataSize
  130.         LDAT_OFS        EQU     2
  131. else
  132.         LDAT_OFS        EQU     0
  133. endif
  134.  
  135. ifdef Save_DS
  136. ;                       (di,si,ds)+(size, return address)
  137.         SAVE_REGS       EQU     6+(4+LCOD_OFS)
  138. else
  139. ;                       (di,si)+(size, return address)
  140.         SAVE_REGS       EQU     4+(4+LCOD_OFS)
  141. endif
  142.  
  143. ;
  144. ; Selection of the supported CPU instruction set and initialization
  145. ; of CPU type related macros:
  146. ;
  147. ifdef __586
  148.         Use_286_code    EQU     1
  149.         Align_Size      EQU     16      ; paragraph alignment on Pentium
  150.         Alig_PARA       EQU     1       ; paragraph aligned code segment
  151. else
  152. ifdef __486
  153.         Use_286_code     EQU    1
  154.         Align_Size       EQU    4       ; dword alignment on 32 bit processors
  155.         Alig_PARA        EQU    1       ; paragraph aligned code segment
  156. else
  157. ifdef __386
  158.         Use_286_code    EQU     1
  159.         Align_Size      EQU     4       ; dword alignment on 32 bit processors
  160.         Alig_PARA       EQU     1       ; paragraph aligned code segment
  161. else
  162. ifdef __286
  163.         Use_286_code    EQU     1
  164.         Align_Size      EQU     2       ; word alignment on 16 bit processors
  165.         Alig_PARA       EQU     0       ; word aligned code segment
  166. else
  167. ifdef __186
  168.         Use_186_code    EQU     1
  169.         Align_Size      EQU     2       ; word alignment on 16 bit processors
  170.         Alig_PARA       EQU     0       ; word aligned code segment
  171. else
  172.         Align_Size      EQU     2       ; word alignment on 16 bit processors
  173.         Alig_PARA       EQU     0       ; word aligned code segment
  174. endif   ;?__186
  175. endif   ;?__286
  176. endif   ;?__386
  177. endif   ;?__486
  178. endif   ;?__586
  179.  
  180. ifdef Use_286_code
  181.         .286
  182.         Have_80x86      EQU     1
  183. else
  184. ifdef Use_186_code
  185.         .186
  186.         Have_80x86      EQU     1
  187. else
  188.         .8086
  189.         Have_80x86      EQU     0
  190. endif   ;?Use_186_code
  191. endif   ;?Use_286_code
  192.  
  193. ;
  194. ; Declare the segments used in this module:
  195. ;
  196. if @CodeSize
  197. if Alig_PARA
  198. CRC32_TEXT      SEGMENT  PARA PUBLIC 'CODE'
  199. else
  200. CRC32_TEXT      SEGMENT  WORD PUBLIC 'CODE'
  201. endif
  202. CRC32_TEXT      ENDS
  203. else    ;!@CodeSize
  204. if Alig_PARA
  205. _TEXT   SEGMENT  PARA PUBLIC 'CODE'
  206. else
  207. _TEXT   SEGMENT  WORD PUBLIC 'CODE'
  208. endif
  209. _TEXT   ENDS
  210. endif   ;?@CodeSize
  211. _DATA   SEGMENT  WORD PUBLIC 'DATA'
  212. _DATA   ENDS
  213. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  214. _BSS    ENDS
  215. DGROUP  GROUP   _BSS, _DATA
  216. if @DataSize
  217.         ASSUME  DS: nothing, SS: DGROUP
  218. else
  219.         ASSUME  DS: DGROUP, SS: DGROUP
  220. endif
  221.  
  222. if @CodeSize
  223. EXTRN   _get_crc_table:FAR
  224. else
  225. EXTRN   _get_crc_table:NEAR
  226. endif
  227.  
  228.  
  229. Do_CRC  MACRO
  230.         mov     bl,al
  231.         sub     bh,bh
  232. if Have_80x86
  233.         shl     bx,2
  234. else
  235.         shl     bx,1
  236.         shl     bx,1
  237. endif
  238.         mov     al,ah
  239.         mov     ah,dl
  240.         mov     dl,dh
  241.         sub     dh,dh
  242.         xor     ax,WORD PTR [bx][si]
  243.         xor     dx,WORD PTR [bx+2][si]
  244.         ENDM
  245. ;
  246. Do_1    MACRO
  247. if @DataSize
  248.         xor     al,BYTE PTR es:[di]
  249. else
  250.         xor     al,BYTE PTR [di]
  251. endif
  252.         inc     di
  253.         Do_CRC
  254.         ENDM
  255. ;
  256. Do_2    MACRO
  257. ifndef NO_16_BIT_LOADS
  258. if @DataSize
  259.         xor     ax,WORD PTR es:[di]
  260. else
  261.         xor     ax,WORD PTR [di]
  262. endif
  263.         add     di,2
  264.         Do_CRC
  265.         Do_CRC
  266. else
  267.         Do_1
  268.         Do_1
  269. endif
  270.         ENDM
  271. ;
  272. Do_4    MACRO
  273.         Do_2
  274.         Do_2
  275.         ENDM
  276. ;
  277.  
  278. IF @CodeSize
  279. CRC32_TEXT      SEGMENT
  280.         ASSUME  CS: CRC32_TEXT
  281. else
  282. _TEXT   SEGMENT
  283.         ASSUME  CS: _TEXT
  284. endif
  285. ; Line 37
  286.  
  287. ;
  288. ;ulg crc32(ulg crc,
  289. ;    ZCONST uch *buf,
  290. ;    extend len)
  291. ;
  292.         PUBLIC  _crc32
  293. if @CodeSize
  294. _crc32  PROC FAR
  295. else
  296. _crc32  PROC NEAR
  297. endif
  298. if Have_80x86
  299.         enter   WORD PTR 0,0
  300. else
  301.         push    bp
  302.         mov     bp,sp
  303. endif
  304.         push    di
  305.         push    si
  306. if @DataSize
  307. ;       crc = 4+LCOD_OFS        DWORD (unsigned long)
  308. ;       buf = 8+LCOD_OFS        DWORD PTR BYTE (uch *)
  309. ;       len = 12+LCOD_OFS       WORD (unsigned int)
  310. else
  311. ;       crc = 4+LCOD_OFS        DWORD (unsigned long)
  312. ;       buf = 8+LCOD_OFS        WORD PTR BYTE (uch *)
  313. ;       len = 10+LCOD_OFS       WORD (unsigned int)
  314. endif
  315. ;
  316. if @DataSize
  317.         mov     ax,WORD PTR [bp+8+LCOD_OFS]     ; buf
  318.         or      ax,WORD PTR [bp+10+LCOD_OFS]    ;     == NULL ?
  319. else
  320.         cmp     WORD PTR [bp+8+LCOD_OFS],0      ; buf == NULL ?
  321. endif
  322.         jne     crc_update
  323.         sub     ax,ax                           ; crc = 0
  324.         cwd
  325. ifndef NO_UNROLLED_LOOPS
  326.         jmp     fine
  327. else
  328.         jmp     SHORT fine
  329. endif
  330. ;
  331. crc_update:
  332.         call     _get_crc_table
  333. ;  When used with compilers that conform to the Microsoft/Borland standard
  334. ;  C calling convention, model-dependent handling is not needed, because
  335. ;   _get_crc_table returns NEAR pointer.
  336. ;  But Watcom C is different and does not allow one to assume DS pointing to
  337. ;  DGROUP. So, we load DS with DGROUP, to be safe.
  338. ;if @DataSize
  339. ;       push    ds
  340. ;       mov     ds,dx
  341. ;       ASSUME  DS: nothing
  342. ;endif
  343.         mov     si,ax                           ;crc_table
  344. if @DataSize
  345.         push    ds
  346.         mov     ax,SEG DGROUP
  347.         mov     ds,ax
  348.         ASSUME  DS: DGROUP
  349. endif
  350. ;
  351.         mov     ax,WORD PTR [bp+4+LCOD_OFS]     ;crc
  352.         mov     dx,WORD PTR [bp+6+LCOD_OFS]
  353.         not     ax
  354.         not     dx
  355. if @DataSize
  356.         les     di,DWORD PTR [bp+8+LCOD_OFS]    ;buf
  357.         mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len
  358. else
  359.         mov     di,WORD PTR [bp+8+LCOD_OFS]     ;buf
  360.         mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len
  361. endif
  362. ;
  363. ifndef NO_UNROLLED_LOOPS
  364. ifndef NO_16_BIT_LOADS
  365.         test    cx,cx
  366.         jnz     start
  367.         jmp     done
  368. start:  test    di,1
  369.         jz      is_wordaligned
  370.         dec     cx
  371.         Do_1
  372.         mov     WORD PTR [bp+10+LDAT_OFS+LCOD_OFS],cx
  373. is_wordaligned:
  374. endif ; !NO_16_BIT_LOADS
  375. if Have_80x86
  376.         shr     cx,2
  377. else
  378.         shr     cx,1
  379.         shr     cx,1
  380. endif
  381.         jcxz    No_Fours
  382. ;
  383.         align   Align_Size              ; align destination of branch
  384. Next_Four:
  385.         Do_4
  386.         loop    Next_Four
  387. ;
  388. No_Fours:
  389. if @DataSize
  390.         mov     cx,WORD PTR [bp+12+LCOD_OFS]    ;len
  391. else
  392.         mov     cx,WORD PTR [bp+10+LCOD_OFS]    ;len
  393. endif
  394.         and     cx,00003H
  395. endif ; !NO_UNROLLED_LOOPS
  396.         jcxz    done
  397. ;
  398.         align   Align_Size              ; align destination of branch
  399. Next_Byte:
  400.         Do_1
  401.         loop    Next_Byte
  402. ;
  403. done:
  404. if @DataSize
  405.         pop     ds
  406. ;       ASSUME  DS: DGROUP
  407.         ASSUME  DS: nothing
  408. endif
  409.         not     ax
  410.         not     dx
  411. ;
  412. fine:
  413.         pop     si
  414.         pop     di
  415. if Have_80x86
  416.         leave
  417. else
  418.         mov     sp,bp
  419.         pop     bp
  420. endif
  421.         ret
  422.  
  423. _crc32  ENDP
  424.  
  425. if @CodeSize
  426. CRC32_TEXT      ENDS
  427. else
  428. _TEXT   ENDS
  429. endif
  430. ;
  431. endif ;!USE_ZLIB
  432. ;
  433. END
  434.