Adopted crc32c xor trick to avoid masking valid bits

Turns out these are equivalent:

  cksum' = crc32c([d & ~0x80], cksum)
  cksum' = crc32c([d], cksum ^ (d & 0x80))

Which is quite nice. The second form is a bit cheaper and works better
in situations where you may have an immutable buffer.

I took the long way to find this and may or may not have brute forced
an xor mask for the valid bit:

  crc32c(62 95 e3 fd 00) => c7844d4d
  crc32c(00 00 00 00 80) => c7844d4d

But this is equivalent to 00000080 after xoring in the init junk.

If you look at the naive lfs_crc32c impl, the first step is to xor the
first byte, so really xoring any byte will cancel it out of our crc32c.

Code changes, thought this would save more because we can reuse bd
checksumming a bit better... Oh well, at least the theory works:

           code          stack
  before: 33916           2824
  after:  33908 (-0.0%)   2824 (+0.0%)
This commit is contained in:
Christopher Haster
2024-05-01 09:59:43 -05:00
parent 8a75a68d8b
commit 1c9cc63994
+8 -9
View File
@@ -1087,9 +1087,10 @@ static lfs_ssize_t lfsr_bd_readtag_(lfs_t *lfs,
LFS_ASSERT(size <= 0x0fffffff);
d += d_;
// ignore the valid bit when calculating optional checksum
tag_buf[0] &= ~0x80;
// optional checksum
if (cksum_) {
// ignore the valid bit when calculating checksums
*cksum_ ^= tag_buf[0] & 0x80;
*cksum_ = lfs_crc32c(*cksum_, tag_buf, d);
}
@@ -1146,19 +1147,17 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs,
}
d += d_;
// ignore the valid bit when calculating checksums
if (cksum_) {
*cksum_ ^= tag_buf[0] & 0x80;
}
int err = lfsr_bd_prog(lfs, block, off, &tag_buf, d,
NULL);
cksum_);
if (err) {
LFS_ASSERT(err < 0);
return err;
}
// ignore the valid bit when calculating optional checksum
tag_buf[0] &= ~0x80;
if (cksum_) {
*cksum_ = lfs_crc32c(*cksum_, tag_buf, d);
}
return d;
}