aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Starkjohann <cs+github@obdev.at>2013-11-22 15:48:48 +0100
committerChristian Starkjohann <cs+github@obdev.at>2013-11-22 15:48:48 +0100
commite1a453ce38d77f80c171b2752bedd1be54fd0eb4 (patch)
treebeabb15589e776df64ed77460d7b6b678c825151
parent4b174f6ed96d82dc8c76209057626abc8ceea338 (diff)
downloadv-usb-e1a453ce38d77f80c171b2752bedd1be54fd0eb4.tar.gz
v-usb-e1a453ce38d77f80c171b2752bedd1be54fd0eb4.tar.bz2
v-usb-e1a453ce38d77f80c171b2752bedd1be54fd0eb4.zip
Optimized fast CRC routine to be shorter and faster.
-rw-r--r--usbdrv/usbdrvasm.S37
1 files changed, 16 insertions, 21 deletions
diff --git a/usbdrv/usbdrvasm.S b/usbdrv/usbdrvasm.S
index 32ce8ef..6fa575d 100644
--- a/usbdrv/usbdrvasm.S
+++ b/usbdrv/usbdrvasm.S
@@ -145,7 +145,8 @@ RTMODEL "__rt_version", "3"
#if USB_USE_FAST_CRC
; This implementation is faster, but has bigger code size
-; Thanks to Slawomir Fras (BoskiDialer) for this code!
+; Thanks to Slawomir Fras (BoskiDialer) for this code and to Shay Green for
+; even further optimizations!
; It implements the following C pseudo-code:
; unsigned table(unsigned char x)
; {
@@ -175,35 +176,29 @@ RTMODEL "__rt_version", "3"
; resCrc r24+r25 / r16+r17
; ptr X / Z
usbCrc16:
- mov ptrL, argPtrL
- mov ptrH, argPtrH
+ movw ptrL, argPtrL
ldi resCrcL, 0xFF
ldi resCrcH, 0xFF
+ clr bitCnt ; zero reg
rjmp usbCrc16LoopTest
usbCrc16ByteLoop:
ld byte, ptr+
- eor resCrcL, byte ; resCrcL is now 'x' in table()
- mov byte, resCrcL ; compute parity of 'x'
+ eor byte, resCrcL ; scratch is now 'x' in table()
+ mov scratch, byte ; compute parity of 'x'
swap byte
- eor byte, resCrcL
- mov scratch, byte
+ eor byte, scratch
+ mov resCrcL, byte
lsr byte
lsr byte
- eor byte, scratch
+ eor byte, resCrcL
inc byte
- lsr byte
- andi byte, 1 ; byte is now parity(x)
- mov scratch, resCrcL
- mov resCrcL, resCrcH
- eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
- neg byte
- andi byte, 0xc0
- mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
- clr byte
- lsr scratch
- ror byte
- eor resCrcH, scratch
- eor resCrcL, byte
+ andi byte, 2 ; byte is now parity(x) << 1
+ cp bitCnt, byte ; c = (byte != 0), then put in high bit
+ ror scratch ; so that after xoring, shifting, and xoring, it gives
+ ror byte ; the desired 0xC0 with resCrcH
+ mov resCrcL, byte
+ eor resCrcL, resCrcH
+ mov resCrcH, scratch
lsr scratch
ror byte
eor resCrcH, scratch