uint16_t crc16_ccitt_opt16(
const unsigned char* block,
unsigned int blockLength,
uint16_t crc)
{
/* unsigned int i; */
/* for(i=0U; i<blockLength; i++){ */
/* uint16_t tmp = (crc >> 8) ^ (uint16_t) block[i]; */
/* crc = ((uint16_t)(crc << 8U)) ^ crc16_ccitt_table[tmp]; */
/* } */
/*
r0 -> s
r1 -> len
r2 -> crc16val
r3 -> crc16tab
r4 -> curval[0]
r5 -> (crc >> 8) ^ (uint16_t) block[i]
r6 -> crc16_ccitt_table[(crc >> 8) ^ (uint16_t) block[i])
r7 -> curval[1]
r8 -> curval[2]
r9 -> curval[3]
*/
__asm__ volatile (
"mov r0, %1\n"
"mov r1, %2\n"
"mov r2, %3\n"
"mov r3, %4\n"
"push {r7, r8, r9}\n"
"crc16_opt16_loop:\n"
"ldm r0!, {r4, r7, r8, r9}\n"
// curval[0]
"eor r5, r4, r2, lsr #8\n"
"uxtb r5, r5\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r4, r2\n"
"ubfx r5, r5, #8, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r4, r2, lsl #8\n"
"ubfx r5, r5, #16, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r4, r2, lsl #16\n"
"lsrs r5, r5, #24\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
// curval[1]
"eor r5, r7, r2, lsr #8\n"
"uxtb r5, r5\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r7, r2\n"
"ubfx r5, r5, #8, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r7, r2, lsl #8\n"
"ubfx r5, r5, #16, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r7, r2, lsl #16\n"
"lsrs r5, r5, #24\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
// curval[2]
"eor r5, r8, r2, lsr #8\n"
"uxtb r5, r5\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r8, r2\n"
"ubfx r5, r5, #8, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r8, r2, lsl #8\n"
"ubfx r5, r5, #16, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r8, r2, lsl #16\n"
"lsrs r5, r5, #24\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
// curval[3]
"eor r5, r9, r2, lsr #8\n"
"uxtb r5, r5\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r9, r2\n"
"ubfx r5, r5, #8, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r9, r2, lsl #8\n"
"ubfx r5, r5, #16, #8\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
"eor r2, r6, r2, lsl #8\n"
"eor r5, r9, r2, lsl #16\n"
"lsrs r5, r5, #24\n\n"
"ldrh r6, [r3, r5, lsl #1]\n"
// Last two lines inverted
"subs r1, r1, #16\n"
"eor r2, r6, r2, lsl #8\n"
"bne crc16_opt16_loop\n"
"pop {r7, r8, r9}\n"
"strh r2, %0\n"
: "=m" (crc)
: "r" (block), "r" (blockLength), "r" (crc), "r" (crc16_ccitt_table)
// Missing r7-r9, manually save it
: "r0", "r1", "r2", "r3", "r4", "r5", "r6"
);
return crc;
}