| CODE |
; ; A fast implementation of the IP checksum for the AVR CPU ; ipsum: ;ipsum(void *buffer, unsigned length) - checksum as per IP spec. ;Required if you are doing any kind if IP traffic. ; ;r25:r24=pointer, r23:r22=length_in_bytes ;r31,r30,r27,r26 clobbered. r27:r26 is not used as a pointer. ; ;execution time: 16 + length*4.5 + 2*length_is_odd + 4 ret ;size : 26 words ; ; ;Comment: This is a bit convoluted! ; The description does add, addcarry, and finally complement. ; This one does subtractcarry and finally adjust. ; The outcome is the same, just faster. ; (the length counter works a bit odd too.) mov r31,r25 ;transplant the pointer mov r30,r24 bst r22,0 ;store length bit0 lsr r23 ;divide length by 2 ror r22 com r22 ;set up length. we're counting inverted. com r23 sub r24,r24 ;clear the sum. and clears carry. dec r24 ;make FF without setting carry mov r25,r24 ;the sum is now FFFF and carry is clear rjmp iplen ipsloop: ld r27,Z+ ld r26,Z+ sbc r24,r26 sbc r25,r27 iplen: inc r22 ;inc does not affect carry, so no need for carryadd. brne ipsloop ;4.5 clocks per byte inc r23 brne ipsloop brtc ips_even ;if length is odd then ld r27,Z+ ;add the lone byte at the end sbci r24,0 sbc r25,r27 ips_even: sbci r24,0x00 ;the rest sbci r25,0x00 ; ret |