ipl: Avoid usage of 64-bit __udivdi3 millicode routine in ext2 code
Avoid using millicode routines in the ext2 code by using a simplified
bit-shifting mechanism to avoid u64 integer divisions.
Signed-off-by: Helge Deller <deller@gmx.de>
diff --git a/ipl/ext2.c b/ipl/ext2.c
index a468790..d05ec6c 100644
--- a/ipl/ext2.c
+++ b/ipl/ext2.c
@@ -64,6 +64,27 @@
#undef DEBUG
#define Debug 0
+/* div_blocksize() and mul_blocksize() are trivial functions to avoid 64-bit
+ __udivdi3 and __muldi3 millicode routines. They only work because the ext2
+ blocksize is a multiple of 2 */
+static __u64 div_blocksize(__u64 devaddr, unsigned blocksize)
+{
+ while (blocksize > 1) {
+ devaddr >>= 1;
+ blocksize >>= 1;
+ }
+ return devaddr;
+}
+static __u64 mul_blocksize(__u64 devaddr, unsigned blocksize)
+{
+ while (blocksize > 1) {
+ devaddr <<= 1;
+ blocksize >>= 1;
+ }
+ return devaddr;
+}
+
+
static struct ext3_extent_header *ext3_extent_header(struct ext2_inode *i)
{
return (struct ext3_extent_header *)&i->i_block[0];
@@ -363,7 +384,7 @@
printf("group is %d\n", group);
#endif
offset = partition_offset
- + ((__u64) ext2_gds(group)->bg_inode_table * ext2_blocksize)
+ + mul_blocksize(ext2_gds(group)->bg_inode_table, ext2_blocksize)
+ (((ino - 1) % EXT2_INODES_PER_GROUP(&sb))
* EXT2_INODE_SIZE(&sb));
#ifdef DEBUG
@@ -583,7 +604,7 @@
/* Read the indirect block */
if (cached_iblkno != iblkno) {
- offset = partition_offset + (__u64)iblkno * ext2_blocksize;
+ offset = partition_offset + mul_blocksize(iblkno, ext2_blocksize);
if (cons_read(dev, iblkbuf, ext2_blocksize, offset)
!= ext2_blocksize)
{
@@ -610,7 +631,7 @@
/* Read in the double-indirect block */
if (cached_diblkno != diblkno) {
- offset = partition_offset + (__u64) diblkno * ext2_blocksize;
+ offset = partition_offset + mul_blocksize(diblkno, ext2_blocksize);
if (cons_read(dev, diblkbuf, ext2_blocksize, offset)
!= ext2_blocksize)
{
@@ -631,7 +652,7 @@
/* Read the indirect block */
if (cached_iblkno != iblkno) {
- offset = partition_offset + (__u64) iblkno * ext2_blocksize;
+ offset = partition_offset + mul_blocksize(iblkno, ext2_blocksize);
if (cons_read(dev, iblkbuf, ext2_blocksize, offset)
!= ext2_blocksize)
{
@@ -699,7 +720,7 @@
memset(buffer, 0, nbytes);
} else {
/* Read it for real */
- offset = partition_offset + (__u64) dev_blkno * ext2_blocksize;
+ offset = partition_offset + mul_blocksize(dev_blkno, ext2_blocksize);
#ifdef DEBUG
printf("ext2_bread: reading %ld bytes at offset %lld\n",
nbytes, offset);
@@ -970,7 +991,7 @@
fd, buf, count, devaddr);
return ext2_breadi(ip,
- devaddr / ext2_blocksize,
+ div_blocksize(devaddr, ext2_blocksize),
count / ext2_blocksize,
buf);
}