Re: [PATCH] tools/nolibc: MIPS: fix clobbers of 'lo' and 'hi' registers on different ISAs
From: Maciej W. Rozycki
Date: Sat Mar 14 2026 - 14:01:41 EST
On Wed, 18 Feb 2026, Thomas Weißschuh wrote:
> Earlier MIPS64 ISAs still provide the 'lo' and 'hi' special registers.
> These are clobbered by system calls and need to be marked as such to
> avoid miscompilations.
Correct.
> Also 32-bit ISAs from r6 on do not define the 'lo' and 'hi' registers.
There's no MIPS ISA beyond R6 (nanoMIPS is a completely different ISA).
Also MIPS64r6 is the same in this respect as MIPS32r6 is.
> diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
> index a72506ceec6b..210bd907b51f 100644
> --- a/tools/include/nolibc/arch-mips.h
> +++ b/tools/include/nolibc/arch-mips.h
> @@ -41,23 +41,44 @@
>
> #if defined(_ABIO32)
>
> -#define _NOLIBC_SYSCALL_CLOBBERLIST \
> - "memory", "cc", "at", "v1", "hi", "lo", \
> - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
> #define _NOLIBC_SYSCALL_STACK_RESERVE "addiu $sp, $sp, -32\n"
> #define _NOLIBC_SYSCALL_STACK_UNRESERVE "addiu $sp, $sp, 32\n"
>
> #else /* _ABIN32 || _ABI64 */
>
> +#define _NOLIBC_SYSCALL_STACK_RESERVE
> +#define _NOLIBC_SYSCALL_STACK_UNRESERVE
> +
> +#endif /* _ABIO32 */
> +
> +
> +#if defined(_ABIO32) && __mips_isa_rev >= 6
> +
> +#define _NOLIBC_SYSCALL_CLOBBERLIST \
> + "memory", "cc", "at", "v1", \
> + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
> +
> +#elif defined(_ABIO32) && __mips_isa_rev < 6
> +
> +#define _NOLIBC_SYSCALL_CLOBBERLIST \
> + "memory", "cc", "at", "v1", "hi", "lo", \
> + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
> +
> +#elif __mips_isa_rev >= 6 /* _ABIN32 || _ABI64 */
> +
> /* binutils, GCC and clang disagree about register aliases, use numbers instead. */
> #define _NOLIBC_SYSCALL_CLOBBERLIST \
> "memory", "cc", "at", "v1", \
> "10", "11", "12", "13", "14", "15", "24", "25"
>
> -#define _NOLIBC_SYSCALL_STACK_RESERVE
> -#define _NOLIBC_SYSCALL_STACK_UNRESERVE
> +#else /* __mips_is_rev < 6 && (_ABIN32 || _ABI64) */
s/__mips_is_rev/__mips_isa_rev/
> +
> +#define _NOLIBC_SYSCALL_CLOBBERLIST \
> + "memory", "cc", "at", "v1", "hi", "lo", \
> + "10", "11", "12", "13", "14", "15", "24", "25"
> +
> +#endif /* __mips_isa_rev and ABI */
>
> -#endif /* _ABIO32 */
I think this would be more readable/maintainable if you did something
such as:
#if __mips_isa_rev < 6
#define _NOLIBC_SYSCALL_CLOBBER_HI "hi"
#define _NOLIBC_SYSCALL_CLOBBER_LO "lo"
#else
#define _NOLIBC_SYSCALL_CLOBBER_HI "$0"
#define _NOLIBC_SYSCALL_CLOBBER_LO "$0"
#endif
and then used the macros rather than duplicating the clobber lists. Or
you could reuse the approach taken with VDSO_SYSCALL_CLOBBERS, perhaps a
bit messy, also when it comes to the name of the macro.