Skip to content

Commit a6a2a8a

Browse files
committed
tools/nolibc: MIPS: add support for N64 and N32 ABIs
Add support for the MIPS 64bit N64 and ILP32 N32 ABIs. In addition to different byte orders and ABIs there are also different releases of the MIPS architecture. To avoid blowing up the test matrix, only add a subset of all possible test combinations. Signed-off-by: Thomas Weißschuh <[email protected]> Tested-by: Sebastian Andrzej Siewior <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 69891dc commit a6a2a8a

File tree

3 files changed

+117
-16
lines changed

3 files changed

+117
-16
lines changed

tools/include/nolibc/arch-mips.h

Lines changed: 90 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "compiler.h"
1111
#include "crt.h"
1212

13-
#if !defined(_ABIO32)
13+
#if !defined(_ABIO32) && !defined(_ABIN32) && !defined(_ABI64)
1414
#error Unsupported MIPS ABI
1515
#endif
1616

@@ -32,21 +32,42 @@
3232
* - the arguments are cast to long and assigned into the target registers
3333
* which are then simply passed as registers to the asm code, so that we
3434
* don't have to experience issues with register constraints.
35+
*
36+
* Syscalls for MIPS ABI N32, same as ABI O32 with the following differences :
37+
* - arguments are in a0, a1, a2, a3, t0, t1, t2, t3.
38+
* t0..t3 are also known as a4..a7.
39+
* - stack is 16-byte aligned
3540
*/
3641

42+
#if defined(_ABIO32)
43+
3744
#define _NOLIBC_SYSCALL_CLOBBERLIST \
3845
"memory", "cc", "at", "v1", "hi", "lo", \
3946
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9"
47+
#define _NOLIBC_SYSCALL_STACK_RESERVE "addiu $sp, $sp, -32\n"
48+
#define _NOLIBC_SYSCALL_STACK_UNRESERVE "addiu $sp, $sp, 32\n"
49+
50+
#else /* _ABIN32 || _ABI64 */
51+
52+
/* binutils, GCC and clang disagree about register aliases, use numbers instead. */
53+
#define _NOLIBC_SYSCALL_CLOBBERLIST \
54+
"memory", "cc", "at", "v1", \
55+
"10", "11", "12", "13", "14", "15", "24", "25"
56+
57+
#define _NOLIBC_SYSCALL_STACK_RESERVE
58+
#define _NOLIBC_SYSCALL_STACK_UNRESERVE
59+
60+
#endif /* _ABIO32 */
4061

4162
#define my_syscall0(num) \
4263
({ \
4364
register long _num __asm__ ("v0") = (num); \
4465
register long _arg4 __asm__ ("a3"); \
4566
\
4667
__asm__ volatile ( \
47-
"addiu $sp, $sp, -32\n" \
68+
_NOLIBC_SYSCALL_STACK_RESERVE \
4869
"syscall\n" \
49-
"addiu $sp, $sp, 32\n" \
70+
_NOLIBC_SYSCALL_STACK_UNRESERVE \
5071
: "=r"(_num), "=r"(_arg4) \
5172
: "r"(_num) \
5273
: _NOLIBC_SYSCALL_CLOBBERLIST \
@@ -61,9 +82,9 @@
6182
register long _arg4 __asm__ ("a3"); \
6283
\
6384
__asm__ volatile ( \
64-
"addiu $sp, $sp, -32\n" \
85+
_NOLIBC_SYSCALL_STACK_RESERVE \
6586
"syscall\n" \
66-
"addiu $sp, $sp, 32\n" \
87+
_NOLIBC_SYSCALL_STACK_UNRESERVE \
6788
: "=r"(_num), "=r"(_arg4) \
6889
: "0"(_num), \
6990
"r"(_arg1) \
@@ -80,9 +101,9 @@
80101
register long _arg4 __asm__ ("a3"); \
81102
\
82103
__asm__ volatile ( \
83-
"addiu $sp, $sp, -32\n" \
104+
_NOLIBC_SYSCALL_STACK_RESERVE \
84105
"syscall\n" \
85-
"addiu $sp, $sp, 32\n" \
106+
_NOLIBC_SYSCALL_STACK_UNRESERVE \
86107
: "=r"(_num), "=r"(_arg4) \
87108
: "0"(_num), \
88109
"r"(_arg1), "r"(_arg2) \
@@ -100,9 +121,9 @@
100121
register long _arg4 __asm__ ("a3"); \
101122
\
102123
__asm__ volatile ( \
103-
"addiu $sp, $sp, -32\n" \
124+
_NOLIBC_SYSCALL_STACK_RESERVE \
104125
"syscall\n" \
105-
"addiu $sp, $sp, 32\n" \
126+
_NOLIBC_SYSCALL_STACK_UNRESERVE \
106127
: "=r"(_num), "=r"(_arg4) \
107128
: "0"(_num), \
108129
"r"(_arg1), "r"(_arg2), "r"(_arg3) \
@@ -120,9 +141,9 @@
120141
register long _arg4 __asm__ ("a3") = (long)(arg4); \
121142
\
122143
__asm__ volatile ( \
123-
"addiu $sp, $sp, -32\n" \
144+
_NOLIBC_SYSCALL_STACK_RESERVE \
124145
"syscall\n" \
125-
"addiu $sp, $sp, 32\n" \
146+
_NOLIBC_SYSCALL_STACK_UNRESERVE \
126147
: "=r" (_num), "=r"(_arg4) \
127148
: "0"(_num), \
128149
"r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
@@ -131,6 +152,8 @@
131152
_arg4 ? -_num : _num; \
132153
})
133154

155+
#if defined(_ABIO32)
156+
134157
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
135158
({ \
136159
register long _num __asm__ ("v0") = (num); \
@@ -141,10 +164,10 @@
141164
register long _arg5 = (long)(arg5); \
142165
\
143166
__asm__ volatile ( \
144-
"addiu $sp, $sp, -32\n" \
167+
_NOLIBC_SYSCALL_STACK_RESERVE \
145168
"sw %7, 16($sp)\n" \
146169
"syscall\n" \
147-
"addiu $sp, $sp, 32\n" \
170+
_NOLIBC_SYSCALL_STACK_UNRESERVE \
148171
: "=r" (_num), "=r"(_arg4) \
149172
: "0"(_num), \
150173
"r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
@@ -164,11 +187,53 @@
164187
register long _arg6 = (long)(arg6); \
165188
\
166189
__asm__ volatile ( \
167-
"addiu $sp, $sp, -32\n" \
190+
_NOLIBC_SYSCALL_STACK_RESERVE \
168191
"sw %7, 16($sp)\n" \
169192
"sw %8, 20($sp)\n" \
170193
"syscall\n" \
171-
"addiu $sp, $sp, 32\n" \
194+
_NOLIBC_SYSCALL_STACK_UNRESERVE \
195+
: "=r" (_num), "=r"(_arg4) \
196+
: "0"(_num), \
197+
"r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
198+
"r"(_arg6) \
199+
: _NOLIBC_SYSCALL_CLOBBERLIST \
200+
); \
201+
_arg4 ? -_num : _num; \
202+
})
203+
204+
#else /* _ABIN32 || _ABI64 */
205+
206+
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
207+
({ \
208+
register long _num __asm__ ("v0") = (num); \
209+
register long _arg1 __asm__ ("$4") = (long)(arg1); \
210+
register long _arg2 __asm__ ("$5") = (long)(arg2); \
211+
register long _arg3 __asm__ ("$6") = (long)(arg3); \
212+
register long _arg4 __asm__ ("$7") = (long)(arg4); \
213+
register long _arg5 __asm__ ("$8") = (long)(arg5); \
214+
\
215+
__asm__ volatile ( \
216+
"syscall\n" \
217+
: "=r" (_num), "=r"(_arg4) \
218+
: "0"(_num), \
219+
"r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
220+
: _NOLIBC_SYSCALL_CLOBBERLIST \
221+
); \
222+
_arg4 ? -_num : _num; \
223+
})
224+
225+
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
226+
({ \
227+
register long _num __asm__ ("v0") = (num); \
228+
register long _arg1 __asm__ ("$4") = (long)(arg1); \
229+
register long _arg2 __asm__ ("$5") = (long)(arg2); \
230+
register long _arg3 __asm__ ("$6") = (long)(arg3); \
231+
register long _arg4 __asm__ ("$7") = (long)(arg4); \
232+
register long _arg5 __asm__ ("$8") = (long)(arg5); \
233+
register long _arg6 __asm__ ("$9") = (long)(arg6); \
234+
\
235+
__asm__ volatile ( \
236+
"syscall\n" \
172237
: "=r" (_num), "=r"(_arg4) \
173238
: "0"(_num), \
174239
"r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
@@ -178,15 +243,25 @@
178243
_arg4 ? -_num : _num; \
179244
})
180245

246+
#endif /* _ABIO32 */
247+
181248
/* startup code, note that it's called __start on MIPS */
182249
void __start(void);
183250
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector __start(void)
184251
{
185252
__asm__ volatile (
186253
"move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */
254+
#if defined(_ABIO32)
187255
"addiu $sp, $sp, -16\n" /* the callee expects to save a0..a3 there */
256+
#endif /* _ABIO32 */
188257
"lui $t9, %hi(_start_c)\n" /* ABI requires current function address in $t9 */
189258
"ori $t9, %lo(_start_c)\n"
259+
#if defined(_ABI64)
260+
"lui $t0, %highest(_start_c)\n"
261+
"ori $t0, %higher(_start_c)\n"
262+
"dsll $t0, 0x20\n"
263+
"or $t9, $t0\n"
264+
#endif /* _ABI64 */
190265
"jalr $t9\n" /* transfer to c runtime */
191266
);
192267
__nolibc_entrypoint_epilogue();

tools/testing/selftests/nolibc/Makefile.nolibc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ ARCH_ppc64 = powerpc
5353
ARCH_ppc64le = powerpc
5454
ARCH_mips32le = mips
5555
ARCH_mips32be = mips
56+
ARCH_mipsn32le = mips
57+
ARCH_mipsn32be = mips
58+
ARCH_mips64le = mips
59+
ARCH_mips64be = mips
5660
ARCH_riscv32 = riscv
5761
ARCH_riscv64 = riscv
5862
ARCH_s390x = s390
@@ -69,6 +73,10 @@ IMAGE_arm = arch/arm/boot/zImage
6973
IMAGE_armthumb = arch/arm/boot/zImage
7074
IMAGE_mips32le = vmlinuz
7175
IMAGE_mips32be = vmlinuz
76+
IMAGE_mipsn32le = vmlinuz
77+
IMAGE_mipsn32be = vmlinuz
78+
IMAGE_mips64le = vmlinuz
79+
IMAGE_mips64be = vmlinuz
7280
IMAGE_ppc = vmlinux
7381
IMAGE_ppc64 = vmlinux
7482
IMAGE_ppc64le = arch/powerpc/boot/zImage
@@ -93,6 +101,10 @@ DEFCONFIG_arm = multi_v7_defconfig
93101
DEFCONFIG_armthumb = multi_v7_defconfig
94102
DEFCONFIG_mips32le = malta_defconfig
95103
DEFCONFIG_mips32be = malta_defconfig generic/eb.config
104+
DEFCONFIG_mipsn32le = malta_defconfig generic/64r2.config
105+
DEFCONFIG_mipsn32be = malta_defconfig generic/64r6.config generic/eb.config
106+
DEFCONFIG_mips64le = malta_defconfig generic/64r6.config
107+
DEFCONFIG_mips64be = malta_defconfig generic/64r2.config generic/eb.config
96108
DEFCONFIG_ppc = pmac32_defconfig
97109
DEFCONFIG_ppc64 = powernv_be_defconfig
98110
DEFCONFIG_ppc64le = powernv_defconfig
@@ -124,6 +136,10 @@ QEMU_ARCH_arm = arm
124136
QEMU_ARCH_armthumb = arm
125137
QEMU_ARCH_mips32le = mipsel # works with malta_defconfig
126138
QEMU_ARCH_mips32be = mips
139+
QEMU_ARCH_mipsn32le = mips64el
140+
QEMU_ARCH_mipsn32be = mips64
141+
QEMU_ARCH_mips64le = mips64el
142+
QEMU_ARCH_mips64be = mips64
127143
QEMU_ARCH_ppc = ppc
128144
QEMU_ARCH_ppc64 = ppc64
129145
QEMU_ARCH_ppc64le = ppc64
@@ -139,6 +155,8 @@ QEMU_ARCH_m68k = m68k
139155
QEMU_ARCH = $(QEMU_ARCH_$(XARCH))
140156

141157
QEMU_ARCH_USER_ppc64le = ppc64le
158+
QEMU_ARCH_USER_mipsn32le = mipsn32el
159+
QEMU_ARCH_USER_mipsn32be = mipsn32
142160
QEMU_ARCH_USER = $(or $(QEMU_ARCH_USER_$(XARCH)),$(QEMU_ARCH_$(XARCH)))
143161

144162
QEMU_BIOS_DIR = /usr/share/edk2/
@@ -157,6 +175,10 @@ QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
157175
QEMU_ARGS_armthumb = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
158176
QEMU_ARGS_mips32le = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
159177
QEMU_ARGS_mips32be = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
178+
QEMU_ARGS_mipsn32le = -M malta -cpu 5KEc -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
179+
QEMU_ARGS_mipsn32be = -M malta -cpu I6400 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
180+
QEMU_ARGS_mips64le = -M malta -cpu I6400 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
181+
QEMU_ARGS_mips64be = -M malta -cpu 5KEc -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
160182
QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
161183
QEMU_ARGS_ppc64 = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
162184
QEMU_ARGS_ppc64le = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
@@ -191,6 +213,10 @@ CFLAGS_s390x = -m64
191213
CFLAGS_s390 = -m31
192214
CFLAGS_mips32le = -EL -mabi=32 -fPIC
193215
CFLAGS_mips32be = -EB -mabi=32
216+
CFLAGS_mipsn32le = -EL -mabi=n32 -fPIC -march=mips64r2
217+
CFLAGS_mipsn32be = -EB -mabi=n32 -march=mips64r6
218+
CFLAGS_mips64le = -EL -mabi=64 -march=mips64r6
219+
CFLAGS_mips64be = -EB -mabi=64 -march=mips64r2
194220
CFLAGS_sparc32 = $(call cc-option,-m32)
195221
ifeq ($(origin XARCH),command line)
196222
CFLAGS_XARCH = $(CFLAGS_$(XARCH))

tools/testing/selftests/nolibc/run-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ llvm=
2020
all_archs=(
2121
i386 x86_64
2222
arm64 arm armthumb
23-
mips32le mips32be
23+
mips32le mips32be mipsn32le mipsn32be mips64le mips64be
2424
ppc ppc64 ppc64le
2525
riscv32 riscv64
2626
s390x s390

0 commit comments

Comments
 (0)