The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
;===========================================================================
; Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
;
; See the accompanying file LICENSE, version 2000-Apr-09 or later
; (the contents of which are also included in zip.h) for terms of use.
; If, for some reason, all these files are missing, the Info-ZIP license
; also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
;===========================================================================
; crc_68 created by Paul Kienitz, last modified 04 Jan 96.
;
; Return an updated 32 bit CRC value, given the old value and a block of data.
; The CRC table used to compute the value is gotten by calling get_crc_table().
; This replaces the older updcrc() function used in Zip and fUnZip.  The
; prototype of the function is:
;
;    ulg crc32(ulg crcval, uch *text, extent textlen);
;
; On the Amiga, type extent is always unsigned long, not unsigned int, because
; int can be short or long at whim, but size_t is long.
;
; If using this source on a non-Amiga 680x0 system, note that we treat
; a0/a1/d0/d1 as scratch registers not preserved across function calls.
; We do not bother to support registerized arguments for crc32() -- the
; textlen parm is usually large enough so that savings outside the loop
; are pointless.
;
; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more
; efficient on certain machines with dinky instruction caches ('020?), or for
; processing short strings.  If loops are unrolled, the textlen parm must be
; less than 512K; if not unrolled, it must be less than 64K.

        xdef    _crc32          ; (ulg val, uch *buf, extent bufsize)

DO_CRC0 MACRO
        moveq  #0,ltemp
        move.b (textbuf)+,ltemp
        eor.b  crcval,ltemp
        lsl.w  #2,ltemp
        move.l (crc_table,ltemp.w),ltemp
        lsr.l  #8,crcval
        eor.l  ltemp,crcval
        ENDM

        machine mc68020

DO_CRC2 MACRO
        move.b (textbuf)+,btemp
        eor.b  crcval,btemp
        lsr.l  #8,crcval
        move.l (crc_table,btemp.w*4),ltemp
        eor.l  ltemp,crcval
        ENDM

crc_table       equr    a0      array of unsigned long
crcval          equr    d0      unsigned long initial value
textbuf         equr    a1      array of unsigned char
textbufsize     equr    d1      unsigned long (count of bytes in textbuf)
btemp           equr    d2
ltemp           equr    d3


        xref    _get_crc_table  ; ulg *get_crc_table(void)

        NOLIST
        INCLUDE 'exec/execbase.i'
        LIST
        xref    _SysBase        ; struct ExecBase *


_crc32:
        move.l  8(sp),d0
        bne.s   valid
         moveq  #0,d0
         rts
valid:  movem.l btemp/ltemp,-(sp)
        jsr     _get_crc_table
        move.l  d0,ltemp
        move.l  12(sp),crcval
        move.l  16(sp),textbuf
        move.l  20(sp),textbufsize
        not.l   crcval
        move.l  _SysBase,crc_table
        move.w  AttnFlags(crc_table),btemp
        move.l  ltemp,crc_table
        btst    #AFB_68020,btemp
        bne     twenty

    IFD     NO_UNROLLED_LOOPS

        bra.s   decr
loop:    DO_CRC0
decr:    dbra   textbufsize,loop
        bra.s   done

twenty: moveq   #0,btemp
        bra.s   decr2
loop2:   DO_CRC2
decr2:   dbra   textbufsize,loop2

    ELSE    ; !NO_UNROLLED_LOOPS

        move.l  textbufsize,btemp
        lsr.l   #3,textbufsize
        bra     decr8
loop8:   DO_CRC0
         DO_CRC0
         DO_CRC0
         DO_CRC0
         DO_CRC0
         DO_CRC0
         DO_CRC0
         DO_CRC0
decr8:   dbra   textbufsize,loop8
        and.w   #7,btemp
        bra.s   decr1
loop1:   DO_CRC0
decr1:   dbra   btemp,loop1
        bra     done

twenty: moveq   #0,btemp
        move.l  textbufsize,-(sp)
        lsr.l   #3,textbufsize
        bra     decr82
loop82:  DO_CRC2
         DO_CRC2
         DO_CRC2
         DO_CRC2
         DO_CRC2
         DO_CRC2
         DO_CRC2
         DO_CRC2
decr82:  dbra   textbufsize,loop82
        move.l  (sp)+,textbufsize
        and.w   #7,textbufsize
        bra.s   decr12
loop12:  DO_CRC2
decr12:  dbra   textbufsize,loop12

    ENDC    ; ?NO_UNROLLED_LOOPS

done:   movem.l (sp)+,btemp/ltemp
        not.l   crcval
;;;;;   move.l  crcval,d0               ; crcval already is d0
        rts