Re: [PATCH] RFT: mips: implement __udivdi3
On Thu, Sep 21, 2023 at 3:42 PM Daniel Schwierzeck 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 > > 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
Re: [PATCH] RFT: mips: implement __udivdi3
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 Cc: Mauro Condarelli Cc: Ralf Baechle Signed-off-by: Linus Walleij --- 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 ..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 (r...@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__(\ + " .setpush\n"\ + " .setnoat\n"\ + " .setnoreorder \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"\ + " .setpop" \ + : "=&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;
[PATCH] RFT: mips: implement __udivdi3
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 Cc: Mauro Condarelli Cc: Ralf Baechle Signed-off-by: Linus Walleij --- 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 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 ..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 (r...@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__(\ + " .setpush\n" \ + " .setnoat\n" \ + " .setnoreorder \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" \ + " .setpop"\ + : "=&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); \ +