summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-05-04 22:30:36 +0000
committerJens Arnold <amiconn@rockbox.org>2005-05-04 22:30:36 +0000
commit251deaa4cabb434a104b7d86c949d6777a8bb2bf (patch)
tree42dd645e11ef795fe7eb8a8f19e0c849d806fffe
parent116e4646b0eed98bec965145698ee89c05f400e7 (diff)
downloadrockbox-251deaa4cabb434a104b7d86c949d6777a8bb2bf.zip
rockbox-251deaa4cabb434a104b7d86c949d6777a8bb2bf.tar.gz
rockbox-251deaa4cabb434a104b7d86c949d6777a8bb2bf.tar.bz2
rockbox-251deaa4cabb434a104b7d86c949d6777a8bb2bf.tar.xz
Improved bitfield handling for settings and MMC (more straigtforward, smaller code). This switches the order for fields crossing a longword boundary, so the config block version bump is necessary. Save your settings to a file before upgrading.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6404 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/settings.c75
-rw-r--r--firmware/drivers/ata_mmc.c29
2 files changed, 29 insertions, 75 deletions
diff --git a/apps/settings.c b/apps/settings.c
index bb2cc4f..936aa22 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -73,7 +73,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
-#define CONFIG_BLOCK_VERSION 20
+#define CONFIG_BLOCK_VERSION 21
#define CONFIG_BLOCK_SIZE 512
#define RTC_BLOCK_SIZE 44
@@ -382,82 +382,49 @@ static const struct bit_entry hd_bits[] =
/* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */
};
-
-/* helper function to extract n (<=32) bits from an arbitrary position */
+/* helper function to extract n (<=32) bits from an arbitrary position
+ * counting from LSB to MSB */
static unsigned long get_bits(
const unsigned long* p, /* the start of the bitfield array */
unsigned int from, /* bit no. to start reading from */
unsigned int size) /* how many bits to read */
{
- unsigned int bit_index;
- unsigned int bits_to_use;
-
- unsigned long mask;
+ unsigned int long_index = from / 32;
+ unsigned int bit_index = from % 32;
unsigned long result;
- if (size==1)
- { /* short cut */
- return (p[from/32] & 1<<from%32) != 0;
- }
+ result = p[long_index] >> bit_index;
- result = 0;
- while (size)
- {
- bit_index = from % 32;
- bits_to_use = MIN(32 - bit_index, size);
- mask = 0xFFFFFFFF >> (32 - bits_to_use);
- mask <<= bit_index;
-
- result <<= bits_to_use; /* from last round */
- result |= (p[from/32] & mask) >> bit_index;
+ if (bit_index + size > 32) /* crossing longword boundary */
+ result |= p[long_index+1] << (32 - bit_index);
- from += bits_to_use;
- size -= bits_to_use;
- }
+ result &= 0xFFFFFFFF >> (32 - size);
return result;
}
-/* helper function to set n (<=32) bits to an arbitrary position */
+/* helper function to set n (<=32) bits to an arbitrary position,
+ * counting from LSB to MSB */
static void set_bits(
unsigned long* p, /* the start of the bitfield array */
unsigned int from, /* bit no. to start writing into */
unsigned int size, /* how many bits to change */
unsigned long value) /* content (LSBs will be taken) */
{
- unsigned int end;
- unsigned int word_index, bit_index;
- unsigned int bits_to_use;
-
+ unsigned int long_index = from / 32;
+ unsigned int bit_index = from % 32;
unsigned long mask;
- if (size==1)
- { /* short cut */
- if (value & 1)
- p[from/32] |= 1<<from%32;
- else
- p[from/32] &= ~(1<<from%32);
- return;
- }
+ mask = 0xFFFFFFFF >> (32 - size);
+ value &= mask;
+ mask <<= bit_index;
- end = from + size - 1;
+ if (bit_index + size > 32)
+ p[long_index+1] =
+ (p[long_index+1] & (0xFFFFFFFF << (bit_index + size - 32)))
+ | (value >> (32 - bit_index));
- /* write back to front, least to most significant */
- while (size)
- {
- word_index = end / 32;
- bit_index = (end % 32) + 1;
- bits_to_use = MIN(bit_index, size);
- bit_index -= bits_to_use;
- mask = 0xFFFFFFFF >> (32 - bits_to_use);
- mask <<= bit_index;
-
- p[word_index] = (p[word_index] & ~mask) | (value<<bit_index & mask);
-
- value >>= bits_to_use;
- size -= bits_to_use;
- end -= bits_to_use;
- }
+ p[long_index] = (p[long_index] & ~mask) | (value << bit_index);
}
/*
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index 9e854ce..02ec72a 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -395,29 +395,16 @@ unsigned long mmc_extract_bits(
unsigned int start, /* bit no. to start reading */
unsigned int size) /* how many bits to read */
{
- unsigned int bit_index;
- unsigned int bits_to_use;
- unsigned long mask;
+ unsigned int long_index = start / 32;
+ unsigned int bit_index = start % 32;
unsigned long result;
+
+ result = p[long_index] << bit_index;
- if (size == 1)
- { /* short cut */
- return ((p[start/32] >> (31 - (start % 32))) & 1);
- }
-
- result = 0;
- while (size)
- {
- bit_index = start % 32;
- bits_to_use = MIN(32 - bit_index, size);
- mask = 0xFFFFFFFF >> (32 - bits_to_use);
-
- result <<= bits_to_use; /* start last round */
- result |= (p[start/32] >> (32 - bits_to_use - bit_index)) & mask;
-
- start += bits_to_use;
- size -= bits_to_use;
- }
+ if (bit_index + size > 32) /* crossing longword boundary */
+ result |= p[long_index+1] >> (32 - bit_index);
+
+ result >>= 32 - size;
return result;
}