xref: /linux/tools/include/nolibc/arch-loongarch.h (revision 395b15778e8f1b580334c558c9a6e9f1b28fcc76)
173f12c6dSFeiyang Chen /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
273f12c6dSFeiyang Chen /*
373f12c6dSFeiyang Chen  * LoongArch specific definitions for NOLIBC
473f12c6dSFeiyang Chen  * Copyright (C) 2023 Loongson Technology Corporation Limited
573f12c6dSFeiyang Chen  */
673f12c6dSFeiyang Chen 
773f12c6dSFeiyang Chen #ifndef _NOLIBC_ARCH_LOONGARCH_H
873f12c6dSFeiyang Chen #define _NOLIBC_ARCH_LOONGARCH_H
973f12c6dSFeiyang Chen 
10818924d1SThomas Weißschuh #include "compiler.h"
1161bd4621SZhangjin Wu #include "crt.h"
12818924d1SThomas Weißschuh 
1373f12c6dSFeiyang Chen /* Syscalls for LoongArch :
1473f12c6dSFeiyang Chen  *   - stack is 16-byte aligned
1573f12c6dSFeiyang Chen  *   - syscall number is passed in a7
1673f12c6dSFeiyang Chen  *   - arguments are in a0, a1, a2, a3, a4, a5
1773f12c6dSFeiyang Chen  *   - the system call is performed by calling "syscall 0"
1873f12c6dSFeiyang Chen  *   - syscall return comes in a0
1973f12c6dSFeiyang Chen  *   - the arguments are cast to long and assigned into the target
2073f12c6dSFeiyang Chen  *     registers which are then simply passed as registers to the asm code,
2173f12c6dSFeiyang Chen  *     so that we don't have to experience issues with register constraints.
2273f12c6dSFeiyang Chen  */
23eaa8c9a8SThomas Weißschuh 
242dca615aSZhangjin Wu #define _NOLIBC_SYSCALL_CLOBBERLIST \
252dca615aSZhangjin Wu 	"memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
2673f12c6dSFeiyang Chen 
2773f12c6dSFeiyang Chen #define my_syscall0(num)                                                      \
2873f12c6dSFeiyang Chen ({                                                                            \
2973f12c6dSFeiyang Chen 	register long _num  __asm__ ("a7") = (num);                           \
3073f12c6dSFeiyang Chen 	register long _arg1 __asm__ ("a0");                                   \
3173f12c6dSFeiyang Chen 									      \
3273f12c6dSFeiyang Chen 	__asm__ volatile (                                                    \
3373f12c6dSFeiyang Chen 		"syscall 0\n"                                                 \
3473f12c6dSFeiyang Chen 		: "=r"(_arg1)                                                 \
3573f12c6dSFeiyang Chen 		: "r"(_num)                                                   \
362dca615aSZhangjin Wu 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
3773f12c6dSFeiyang Chen 	);                                                                    \
3873f12c6dSFeiyang Chen 	_arg1;                                                                \
3973f12c6dSFeiyang Chen })
4073f12c6dSFeiyang Chen 
4173f12c6dSFeiyang Chen #define my_syscall1(num, arg1)                                                \
4273f12c6dSFeiyang Chen ({                                                                            \
4373f12c6dSFeiyang Chen 	register long _num  __asm__ ("a7") = (num);                           \
4473f12c6dSFeiyang Chen 	register long _arg1 __asm__ ("a0") = (long)(arg1);		      \
4573f12c6dSFeiyang Chen 									      \
4673f12c6dSFeiyang Chen 	__asm__ volatile (                                                    \
4773f12c6dSFeiyang Chen 		"syscall 0\n"                                                 \
4873f12c6dSFeiyang Chen 		: "+r"(_arg1)                                                 \
4973f12c6dSFeiyang Chen 		: "r"(_num)                                                   \
502dca615aSZhangjin Wu 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
5173f12c6dSFeiyang Chen 	);                                                                    \
5273f12c6dSFeiyang Chen 	_arg1;                                                                \
5373f12c6dSFeiyang Chen })
5473f12c6dSFeiyang Chen 
5573f12c6dSFeiyang Chen #define my_syscall2(num, arg1, arg2)                                          \
5673f12c6dSFeiyang Chen ({                                                                            \
5773f12c6dSFeiyang Chen 	register long _num  __asm__ ("a7") = (num);                           \
5873f12c6dSFeiyang Chen 	register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
5973f12c6dSFeiyang Chen 	register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
6073f12c6dSFeiyang Chen 									      \
6173f12c6dSFeiyang Chen 	__asm__ volatile (                                                    \
6273f12c6dSFeiyang Chen 		"syscall 0\n"                                                 \
6373f12c6dSFeiyang Chen 		: "+r"(_arg1)                                                 \
6473f12c6dSFeiyang Chen 		: "r"(_arg2),                                                 \
6573f12c6dSFeiyang Chen 		  "r"(_num)                                                   \
662dca615aSZhangjin Wu 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
6773f12c6dSFeiyang Chen 	);                                                                    \
6873f12c6dSFeiyang Chen 	_arg1;                                                                \
6973f12c6dSFeiyang Chen })
7073f12c6dSFeiyang Chen 
7173f12c6dSFeiyang Chen #define my_syscall3(num, arg1, arg2, arg3)                                    \
7273f12c6dSFeiyang Chen ({                                                                            \
7373f12c6dSFeiyang Chen 	register long _num  __asm__ ("a7") = (num);                           \
7473f12c6dSFeiyang Chen 	register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
7573f12c6dSFeiyang Chen 	register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
7673f12c6dSFeiyang Chen 	register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
7773f12c6dSFeiyang Chen 									      \
7873f12c6dSFeiyang Chen 	__asm__ volatile (                                                    \
7973f12c6dSFeiyang Chen 		"syscall 0\n"                                                 \
8073f12c6dSFeiyang Chen 		: "+r"(_arg1)                                                 \
8173f12c6dSFeiyang Chen 		: "r"(_arg2), "r"(_arg3),                                     \
8273f12c6dSFeiyang Chen 		  "r"(_num)                                                   \
832dca615aSZhangjin Wu 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
8473f12c6dSFeiyang Chen 	);                                                                    \
8573f12c6dSFeiyang Chen 	_arg1;                                                                \
8673f12c6dSFeiyang Chen })
8773f12c6dSFeiyang Chen 
8873f12c6dSFeiyang Chen #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
8973f12c6dSFeiyang Chen ({                                                                            \
9073f12c6dSFeiyang Chen 	register long _num  __asm__ ("a7") = (num);                           \
9173f12c6dSFeiyang Chen 	register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
9273f12c6dSFeiyang Chen 	register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
9373f12c6dSFeiyang Chen 	register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
9473f12c6dSFeiyang Chen 	register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
9573f12c6dSFeiyang Chen 									      \
9673f12c6dSFeiyang Chen 	__asm__ volatile (                                                    \
9773f12c6dSFeiyang Chen 		"syscall 0\n"                                                 \
9873f12c6dSFeiyang Chen 		: "+r"(_arg1)                                                 \
9973f12c6dSFeiyang Chen 		: "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
10073f12c6dSFeiyang Chen 		  "r"(_num)                                                   \
1012dca615aSZhangjin Wu 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
10273f12c6dSFeiyang Chen 	);                                                                    \
10373f12c6dSFeiyang Chen 	_arg1;                                                                \
10473f12c6dSFeiyang Chen })
10573f12c6dSFeiyang Chen 
10673f12c6dSFeiyang Chen #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
10773f12c6dSFeiyang Chen ({                                                                            \
10873f12c6dSFeiyang Chen 	register long _num  __asm__ ("a7") = (num);                           \
10973f12c6dSFeiyang Chen 	register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
11073f12c6dSFeiyang Chen 	register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
11173f12c6dSFeiyang Chen 	register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
11273f12c6dSFeiyang Chen 	register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
11373f12c6dSFeiyang Chen 	register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
11473f12c6dSFeiyang Chen 									      \
11573f12c6dSFeiyang Chen 	__asm__ volatile (                                                    \
11673f12c6dSFeiyang Chen 		"syscall 0\n"                                                 \
11773f12c6dSFeiyang Chen 		: "+r"(_arg1)                                                 \
11873f12c6dSFeiyang Chen 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
11973f12c6dSFeiyang Chen 		  "r"(_num)                                                   \
1202dca615aSZhangjin Wu 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
12173f12c6dSFeiyang Chen 	);                                                                    \
12273f12c6dSFeiyang Chen 	_arg1;                                                                \
12373f12c6dSFeiyang Chen })
12473f12c6dSFeiyang Chen 
12573f12c6dSFeiyang Chen #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
12673f12c6dSFeiyang Chen ({                                                                            \
12773f12c6dSFeiyang Chen 	register long _num  __asm__ ("a7") = (num);                           \
12873f12c6dSFeiyang Chen 	register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
12973f12c6dSFeiyang Chen 	register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
13073f12c6dSFeiyang Chen 	register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
13173f12c6dSFeiyang Chen 	register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
13273f12c6dSFeiyang Chen 	register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
13373f12c6dSFeiyang Chen 	register long _arg6 __asm__ ("a5") = (long)(arg6);                    \
13473f12c6dSFeiyang Chen 									      \
13573f12c6dSFeiyang Chen 	__asm__ volatile (                                                    \
13673f12c6dSFeiyang Chen 		"syscall 0\n"                                                 \
13773f12c6dSFeiyang Chen 		: "+r"(_arg1)                                                 \
13873f12c6dSFeiyang Chen 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
13973f12c6dSFeiyang Chen 		  "r"(_num)                                                   \
1402dca615aSZhangjin Wu 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
14173f12c6dSFeiyang Chen 	);                                                                    \
14273f12c6dSFeiyang Chen 	_arg1;                                                                \
14373f12c6dSFeiyang Chen })
14473f12c6dSFeiyang Chen 
14573f12c6dSFeiyang Chen #if __loongarch_grlen == 32
14673f12c6dSFeiyang Chen #define LONG_BSTRINS "bstrins.w"
147fddc8f81SThomas Weißschuh #else /* __loongarch_grlen == 64 */
14873f12c6dSFeiyang Chen #define LONG_BSTRINS "bstrins.d"
14973f12c6dSFeiyang Chen #endif
15073f12c6dSFeiyang Chen 
15173f12c6dSFeiyang Chen /* startup code */
152*ef32e9b6SThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
15373f12c6dSFeiyang Chen {
15473f12c6dSFeiyang Chen 	__asm__ volatile (
15561bd4621SZhangjin Wu 		"move          $a0, $sp\n"         /* save stack pointer to $a0, as arg1 of _start_c */
15661bd4621SZhangjin Wu 		LONG_BSTRINS " $sp, $zero, 3, 0\n" /* $sp must be 16-byte aligned                    */
15761bd4621SZhangjin Wu 		"bl            _start_c\n"         /* transfer to c runtime                          */
15873f12c6dSFeiyang Chen 	);
159*ef32e9b6SThomas Weißschuh 	__nolibc_entrypoint_epilogue();
16073f12c6dSFeiyang Chen }
16173f12c6dSFeiyang Chen 
162fddc8f81SThomas Weißschuh #endif /* _NOLIBC_ARCH_LOONGARCH_H */
163