Subversion Repositories Kolibri OS

Rev

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

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