CRC Calculations by Paul Guertin
[Up to Source Code Repository]
CRC Calculations
How to compute a CRC error detecting code in 6502 assembly.
By Paul Guertin (pg@sff.net), 18 August 2000.
a. CRC-16 (CCITT version)
Usage
UPDCRC takes 22 cycles per byte if inlined and the tables are page-aligned.
We initialize the CRC to $FFFF instead of zero so that the algorithm will react to null bytes at the beginning of a block of data.
CRC EQU $6 ; 2 bytes in ZP CRCLO EQU $8000 ; Two 256-byte tables for quick lookup CRCHI EQU $8100 ; (should be page-aligned for speed) MAKECRCTABLE: LDX #0 ; X counts from 0 to 255 BYTELOOP LDA #0 ; A contains the low 8 bits of the CRC-16 STX CRC ; and CRC contains the high 8 bits LDY #8 ; Y counts bits in a byte BITLOOP ASL ROL CRC ; Shift CRC left BCC NOADD ; Do nothing if no overflow EOR #$21 ; else add CRC-16 polynomial $1021 PHA ; Save low byte LDA CRC ; Do high byte EOR #$10 STA CRC PLA ; Restore low byte NOADD DEY BNE BITLOOP ; Do next bit STA CRCLO,X ; Save CRC into table, low byte LDA CRC ; then high byte STA CRCHI,X INX BNE BYTELOOP ; Do next byte RTS UPDCRC: EOR CRC+1 ; Quick CRC computation with lookup tables TAX LDA CRC EOR CRCHI,X STA CRC+1 LDA CRCLO,X STA CRC RTSExample: Computing the CRC-16 of 256 bytes of data in $1000-$10FF.
JSR MAKECRCTABLE LDY #$FF STY CRC STY CRC+1 INY LOOP LDA $1000,Y JSR UPDCRC INY BNE LOOP RTS
b. CRC-32
Usage
UPDCRC takes 42 cycles per byte if inlined and the tables are page-aligned.
Why complement the result? Because the CRC-32 standard says so. I guess it made things easier for with hardware compatibility, and now we're stuck with it.
CRC EQU $6 ; 4 bytes in ZP CRCT0 EQU $8000 ; Four 256-byte tables CRCT1 EQU $8100 ; (should be page-aligned for speed) CRCT2 EQU $8200 CRCT3 EQU $8300 MAKECRCTABLE: LDX #0 ; X counts from 0 to 255 BYTELOOP LDA #0 ; A contains the high byte of the CRC-32 STA CRC+2 ; The other three bytes are in memory STA CRC+1 STX CRC LDY #8 ; Y counts bits in a byte BITLOOP LSR ; The CRC-32 algorithm is similar to CRC-16 ROR CRC+2 ; except that it is reversed (originally for ROR CRC+1 ; hardware reasons). This is why we shift ROR CRC ; right instead of left here. BCC NOADD ; Do nothing if no overflow EOR #$ED ; else add CRC-32 polynomial $EDB88320 PHA ; Save high byte while we do others LDA CRC+2 EOR #$B8 ; Most reference books give the CRC-32 poly STA CRC+2 ; as $04C11DB7. This is actually the same if LDA CRC+1 ; you write it in binary and read it right- EOR #$83 ; to-left instead of left-to-right. Doing it STA CRC+1 ; this way means we won't have to explicitly LDA CRC ; reverse things afterwards. EOR #$20 STA CRC PLA ; Restore high byte NOADD DEY BNE BITLOOP ; Do next bit STA CRCT3,X ; Save CRC into table, high to low bytes LDA CRC+2 STA CRCT2,X LDA CRC+1 STA CRCT1,X LDA CRC STA CRCT0,X INX BNE BYTELOOP ; Do next byte RTS UPDCRC: EOR CRC ; Quick CRC computation with lookup tables TAX LDA CRC+1 EOR CRCT0,X STA CRC LDA CRC+2 EOR CRCT1,X STA CRC+1 LDA CRC+3 EOR CRCT2,X STA CRC+2 LDA CRCT3,X STA CRC+3 RTSExample: Computing the CRC-32 of 256 bytes of data in $1000-$10FF.
JSR MAKECRCTABLE LDY #$FF STY CRC STY CRC+1 STY CRC+2 STY CRC+3 INY LOOP LDA $1000,Y JSR UPDCRC INY BNE LOOP LDY #3 COMPL LDA CRC,Y EOR #$FF STA CRC,Y DEY BPL COMPL RTS
c. CRC-8
Usage
UPDCRC clobbers A and X. It can be easily changed to clobber Y instead of X or, at a performance cost, to preserve registers.
The CRC calculation takes 10 cycles per byte if inlined as in the example.
CRC EQU $6 ; 1 byte in ZP (unneeded if you inline) CRCTBL EQU $8000 ; One 256-byte table for quick lookup MAKECRCTABLE: LDX #0 BYTELOOP TXA ; A contains the CRC-8 LDY #8 BITLOOP ASL ; Shift CRC left BCC NOADD ; If no overflow, do nothing EOR #$07 ; else add CRC-8 polynomial $07 NOADD DEY BNE BITLOOP ; Do next bit STA CRCTBL,X ; All bits done, store in table INX BNE BYTELOOP ; Do next byte RTS UPDCRC: EOR CRC ; You really should inline this, TAX ; in which case you don't even need LDA CRCTBL,X ; the CRC zero page location. See STA CRC ; example below. RTSExample: Computing the CRC-8 of 256 bytes of data in $1000-$10FF.
JSR MAKECRCTABLE LDY #0 TYA ; Initialize CRC LOOP EOR $1000,Y ; EOR old CRC with data TAX ; and index into table LDA CRCTBL,X ; to get the new CRC INY BNE LOOP RTS ; Accumulator contains the CRC-8Last page update: August 19, 1999.