Message ID | 20230918061139.810552-1-linus.walleij@linaro.org |
---|---|
State | New |
Headers | show |
Series | RFT: mips: implement __udivdi3 | expand |
Hi Linus, On 9/18/23 08:11, Linus Walleij wrote: > Squashfs wasn't compiling because the lldiv() directives > turn into __udivdi3 and we are using private libgcc. > This is just copied from the Linux kernel v6.6-rc1 > arch/mips/include/asm/div64.h and then adjusted for > U-Boot. > > After this squashfs compiles for MIPS. > > Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> > Cc: Mauro Condarelli <mc5686@mclink.it> > Cc: Ralf Baechle <ralf@linux-mips.org> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org> > --- > I can't test this because it didn't work for MTD devices > as I had expected, but I saw Mauro had this problem > before so I think I might have fixed it. I better put > the patch out there rather than let it sit on my drive. thanks for the patch. IIRC the problem was due to the usage of a/b vs. do_div(a,b). We already thought about two options: fix the SquashFS code or add __udivdi3(). Because no upstream MIPS board enabled SquashFS, this issue remained unresolved. > --- > arch/mips/lib/Makefile | 2 +- > arch/mips/lib/udivdi3.c | 86 +++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 87 insertions(+), 1 deletion(-) > create mode 100644 arch/mips/lib/udivdi3.c > > diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile > index 9ee1fcb5c702..1621cc9a1ff9 100644 > --- a/arch/mips/lib/Makefile > +++ b/arch/mips/lib/Makefile > @@ -14,4 +14,4 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o > obj-$(CONFIG_CMD_GO) += boot.o > obj-$(CONFIG_SPL_BUILD) += spl.o > > -lib-$(CONFIG_USE_PRIVATE_LIBGCC) += ashldi3.o ashrdi3.o lshrdi3.o > +lib-$(CONFIG_USE_PRIVATE_LIBGCC) += ashldi3.o ashrdi3.o lshrdi3.o udivdi3.o > diff --git a/arch/mips/lib/udivdi3.c b/arch/mips/lib/udivdi3.c > new file mode 100644 > index 000000000000..6a4ee5fa46ab > --- /dev/null > +++ b/arch/mips/lib/udivdi3.c > @@ -0,0 +1,86 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (C) 2000, 2004, 2021 Maciej W. Rozycki > + * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org) > + */ > + > +#include "libgcc.h" > + > +/* > + * No traps on overflows for any of these... > + */ > + > +#define do_div64_32(res, high, low, base) ({ \ > + unsigned long __cf, __tmp, __tmp2, __i; \ > + unsigned long __quot32, __mod32; \ > + \ > + __asm__( \ > + " .set push \n" \ > + " .set noat \n" \ > + " .set noreorder \n" \ > + " move %2, $0 \n" \ > + " move %3, $0 \n" \ > + " b 1f \n" \ > + " li %4, 0x21 \n" \ > + "0: \n" \ > + " sll $1, %0, 0x1 \n" \ > + " srl %3, %0, 0x1f \n" \ > + " or %0, $1, %5 \n" \ > + " sll %1, %1, 0x1 \n" \ > + " sll %2, %2, 0x1 \n" \ > + "1: \n" \ > + " bnez %3, 2f \n" \ > + " sltu %5, %0, %z6 \n" \ > + " bnez %5, 3f \n" \ > + "2: \n" \ > + " addiu %4, %4, -1 \n" \ > + " subu %0, %0, %z6 \n" \ > + " addiu %2, %2, 1 \n" \ > + "3: \n" \ > + " bnez %4, 0b \n" \ > + " srl %5, %1, 0x1f \n" \ > + " .set pop" \ > + : "=&r" (__mod32), "=&r" (__tmp), \ > + "=&r" (__quot32), "=&r" (__cf), \ > + "=&r" (__i), "=&r" (__tmp2) \ > + : "Jr" (base), "0" (high), "1" (low)); \ > + \ > + (res) = __quot32; \ > + __mod32; \ > +}) > + > +#define __div64_32(n, base) ({ \ > + unsigned long __upper, __low, __high, __radix; \ > + unsigned long long __quot; \ > + unsigned long long __div; \ > + unsigned long __mod; \ > + \ > + __div = (*n); \ > + __radix = (base); \ > + \ > + __high = __div >> 32; \ > + __low = __div; \ > + \ > + if (__high < __radix) { \ > + __upper = __high; \ > + __high = 0; \ > + } else { \ > + __upper = __high % __radix; \ > + __high /= __radix; \ > + } \ > + \ > + __mod = do_div64_32(__low, __upper, __low, __radix); \ > + \ > + __quot = __high; \ > + __quot = __quot << 32 | __low; \ > + (*n) = __quot; \ > + __mod; \ > +}) > + > +long long __udivdi3(long long u, word_type b) > +{ > + long long ret = u; > + > + __div64_32(&ret, b); > + return ret; > +} the call to __udivdi3() won't be generated on MIPS64, so the code should be guarded with #if BITS_PER_LONG == 32 as done in Linux. Also we could simply use the generic div64.h implementation. I played around a bit and following simplified code compiles on various MIPS32 and MIPS64 boards. (E.g. "echo CONFIG_FS_SQUASHFS=y >> configs/malta[|64|el|64el]_defconfig && make malta[|64|el|64el]_defconfig") /* SPDX-License-Identifier: GPL-2.0 */ #include "libgcc.h" #if BITS_PER_LONG == 32 #include <div64.h> long long __udivdi3(long long u, word_type b) { long long ret = u; __div64_32(&ret, b); return ret; } #endif /* BITS_PER_LONG == 32 */ What do you think?
On Thu, Sep 21, 2023 at 3:42 PM Daniel Schwierzeck <daniel.schwierzeck@gmail.com> wrote: > I played around a bit and following simplified code compiles on various > MIPS32 and MIPS64 boards. (E.g. "echo CONFIG_FS_SQUASHFS=y >> > configs/malta[|64|el|64el]_defconfig && make malta[|64|el|64el]_defconfig") > > > > /* SPDX-License-Identifier: GPL-2.0 */ > > #include "libgcc.h" > > #if BITS_PER_LONG == 32 > > #include <div64.h> > > long long __udivdi3(long long u, word_type b) > { > long long ret = u; > > __div64_32(&ret, b); > return ret; > } > > #endif /* BITS_PER_LONG == 32 */ > > What do you think? Looks good to me! You can just modify the patch, sign off and apply, I guess? Go ahead! Yours, Linus Walleij
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 9ee1fcb5c702..1621cc9a1ff9 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -14,4 +14,4 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-$(CONFIG_CMD_GO) += boot.o obj-$(CONFIG_SPL_BUILD) += spl.o -lib-$(CONFIG_USE_PRIVATE_LIBGCC) += ashldi3.o ashrdi3.o lshrdi3.o +lib-$(CONFIG_USE_PRIVATE_LIBGCC) += ashldi3.o ashrdi3.o lshrdi3.o udivdi3.o diff --git a/arch/mips/lib/udivdi3.c b/arch/mips/lib/udivdi3.c new file mode 100644 index 000000000000..6a4ee5fa46ab --- /dev/null +++ b/arch/mips/lib/udivdi3.c @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2000, 2004, 2021 Maciej W. Rozycki + * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org) + */ + +#include "libgcc.h" + +/* + * No traps on overflows for any of these... + */ + +#define do_div64_32(res, high, low, base) ({ \ + unsigned long __cf, __tmp, __tmp2, __i; \ + unsigned long __quot32, __mod32; \ + \ + __asm__( \ + " .set push \n" \ + " .set noat \n" \ + " .set noreorder \n" \ + " move %2, $0 \n" \ + " move %3, $0 \n" \ + " b 1f \n" \ + " li %4, 0x21 \n" \ + "0: \n" \ + " sll $1, %0, 0x1 \n" \ + " srl %3, %0, 0x1f \n" \ + " or %0, $1, %5 \n" \ + " sll %1, %1, 0x1 \n" \ + " sll %2, %2, 0x1 \n" \ + "1: \n" \ + " bnez %3, 2f \n" \ + " sltu %5, %0, %z6 \n" \ + " bnez %5, 3f \n" \ + "2: \n" \ + " addiu %4, %4, -1 \n" \ + " subu %0, %0, %z6 \n" \ + " addiu %2, %2, 1 \n" \ + "3: \n" \ + " bnez %4, 0b \n" \ + " srl %5, %1, 0x1f \n" \ + " .set pop" \ + : "=&r" (__mod32), "=&r" (__tmp), \ + "=&r" (__quot32), "=&r" (__cf), \ + "=&r" (__i), "=&r" (__tmp2) \ + : "Jr" (base), "0" (high), "1" (low)); \ + \ + (res) = __quot32; \ + __mod32; \ +}) + +#define __div64_32(n, base) ({ \ + unsigned long __upper, __low, __high, __radix; \ + unsigned long long __quot; \ + unsigned long long __div; \ + unsigned long __mod; \ + \ + __div = (*n); \ + __radix = (base); \ + \ + __high = __div >> 32; \ + __low = __div; \ + \ + if (__high < __radix) { \ + __upper = __high; \ + __high = 0; \ + } else { \ + __upper = __high % __radix; \ + __high /= __radix; \ + } \ + \ + __mod = do_div64_32(__low, __upper, __low, __radix); \ + \ + __quot = __high; \ + __quot = __quot << 32 | __low; \ + (*n) = __quot; \ + __mod; \ +}) + +long long __udivdi3(long long u, word_type b) +{ + long long ret = u; + + __div64_32(&ret, b); + return ret; +}
Squashfs wasn't compiling because the lldiv() directives turn into __udivdi3 and we are using private libgcc. This is just copied from the Linux kernel v6.6-rc1 arch/mips/include/asm/div64.h and then adjusted for U-Boot. After this squashfs compiles for MIPS. Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com> Cc: Mauro Condarelli <mc5686@mclink.it> Cc: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- I can't test this because it didn't work for MTD devices as I had expected, but I saw Mauro had this problem before so I think I might have fixed it. I better put the patch out there rather than let it sit on my drive. --- arch/mips/lib/Makefile | 2 +- arch/mips/lib/udivdi3.c | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 arch/mips/lib/udivdi3.c