;
; Copyright © 1991, 1992 by Walter Rothe. You may freely use and modify this
; program, but not for commercial profit. A modest fee for distribution is
; allowed. Derivative works must be released with source along with the
; executable or provisions made to provide the user source, if requested.
; Uploading source to a major bulletin board system within 6 months of the
; time of the request satisfies this requirement. This copyright notice
; must not be deleted from the source.
;
;:ts=8
        far     data
        machine mc68020
;/* adbfcrc.c
;
;addbfcrc() accepts a buffer address and a count and adds the CRC for
;all bytes in the buffer to the global variable crccode using
;CRC-16.
;*/
;
;#define TABLEN  256
;
;unsigned int crccode;
;unsigned char crctabl[TABLEN], crctabr[TABLEN];
;
;int addbfcrc(buffer,count)
;unsigned char *buffer;
;unsigned count;
;
;{
        xdef    _addbfcrc
_addbfcrc:
        movem.l d2/d3/d4/d5/a2/a3,-(sp)
        move.l  28(sp),a2
;   register unsigned char crcl, crcr, crct;
;   register unsigned char *ptr = buffer;
;   register unsigned char *endptr = &buffer[count];
;   crcl = crccode >> 8;
        move.l  32(sp),a3
        add.l   a2,a3
        move.l  _crccode,d3
        lsr.l   #8,d3
        and.l   #255,d3
;   crcr = crccode & 0xff;
        move.l  _crccode,d4
        and.l   #255,d4
;
        lea     _crctabr,a0
        lea     _crctabl,a1
        move.l  #0,d2
;
;   for ( ; ptr<endptr; ptr++) {
        cmp.l   a3,a2
        bcc     .10003
.10001
;      crct = crcr ^ *ptr;
        move.b  (a2)+,d2
        eor.b   d4,d2
;      crcr = crcl ^ crctabr[ crct ];
        move.b  (a0,d2.w),d4
        eor.b   d3,d4
;      crcl = crctabl[ crct ];
        move.b  (a1,d2.w),d3
;   }
        cmp.l   a3,a2
        bcs     .10001
.10003
;   crccode = (crcl << 8) | crcr;
        asl.l   #8,d3
        or.w    d3,d4
        move.l  d4,_crccode
;}
.2
        movem.l (sp)+,d2/d3/d4/d5/a2/a3
        rts
;
;/* gentab() generates table for CRC calculation, as described in
;"C Programmer's Guide to Serial Communications" by Joe Campbell */
;
;/* reverse CRC-16 polynomial */
;#define CRC_FUNC        (unsigned) 0xa001
;
;unsigned int calcterm();
;
;unsigned int calcterm (data)
;register unsigned int data;
;{
        xdef    _calcterm
_calcterm:
        movem.l d2/d3/d4,-(sp)
        move.l  16(sp),d4
;   int i;
;   register unsigned int accum = 0;
;
;   data <<= 1;
        move.l  #0,d2
        add.l   d4,d4
;   for (i = 8;  i > 0;  i--) {
        move.l  #8,d3
        bra     .10005
.10004
        sub.l   #1,d3
.10005
        tst.l   d3
        ble     .10006
;      data >>= 1;
        lsr.l   #1,d4
;      if ((data ^ accum) & 0x0001)
;         accum = (accum >> 1) ^ CRC_FUNC;
        move.l  d4,d0
        eor.l   d2,d0
        btst.l  #0,d0
        beq     .10007
        move.l  d2,d0
        lsr.l   #1,d0
        move.l  d0,d2
        eor.l   #40961,d2
;      else
        bra     .10008
.10007
;         accum >>= 1;
        lsr.l   #1,d2
.10008
;   }
        bra     .10004
.10006
;   return accum;
        move.l  d2,d0
.3
        movem.l (sp)+,d2/d3/d4
        rts
;}
;
;int gentab()
;{
        xdef    _gentab
_gentab:
        movem.l d2/d3,-(sp)
;   register unsigned int i, cx;
;   for (i = 0;  i < TABLEN;  i++) {
        move.l  #0,d2
        bra     .10010
.10009
        add.l   #1,d2
.10010
        cmp.l   #256,d2
        bcc     .10011
;      cx = calcterm(i);
        move.l  d2,-(sp)
        jsr     _calcterm
        move.l  d0,d3
;      crctabl[i] = cx >> 8;
        move.l  d3,d0
        lsr.l   #8,d0
        lea     _crctabl,a0
        move.b  d0,(a0,d2.l)
;      crctabr[i] = cx & 0xff;
        move.l  d3,d0
        and.l   #255,d0
        lea     _crctabr,a0
        move.b  d0,(a0,d2.l)
;   }
        add.w   #4,sp
        bra     .10009
.10011
;}
.4
        movem.l (sp)+,d2/d3
        rts
;
        xref    .begin
        dseg
        global  _crctabr,256
        global  _crctabl,256
        global  _crccode,4
        end
