From 251deaa4cabb434a104b7d86c949d6777a8bb2bf Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Wed, 4 May 2005 22:30:36 +0000 Subject: 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 --- apps/settings.c | 75 +++++++++++++--------------------------------- firmware/drivers/ata_mmc.c | 29 +++++------------- 2 files changed, 29 insertions(+), 75 deletions(-) diff --git a/apps/settings.c b/apps/settings.c index bb2cc4f929..936aa2233e 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<> 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<> (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<>= 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 9e854ce977..02ec72a1f2 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; } -- cgit v1.2.3