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"
11*61bd4621SZhangjin 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 *
2373f12c6dSFeiyang Chen * On LoongArch, select() is not implemented so we have to use pselect6().
2473f12c6dSFeiyang Chen */
2573f12c6dSFeiyang Chen #define __ARCH_WANT_SYS_PSELECT6
262dca615aSZhangjin Wu #define _NOLIBC_SYSCALL_CLOBBERLIST \
272dca615aSZhangjin Wu "memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
2873f12c6dSFeiyang Chen
2973f12c6dSFeiyang Chen #define my_syscall0(num) \
3073f12c6dSFeiyang Chen ({ \
3173f12c6dSFeiyang Chen register long _num __asm__ ("a7") = (num); \
3273f12c6dSFeiyang Chen register long _arg1 __asm__ ("a0"); \
3373f12c6dSFeiyang Chen \
3473f12c6dSFeiyang Chen __asm__ volatile ( \
3573f12c6dSFeiyang Chen "syscall 0\n" \
3673f12c6dSFeiyang Chen : "=r"(_arg1) \
3773f12c6dSFeiyang Chen : "r"(_num) \
382dca615aSZhangjin Wu : _NOLIBC_SYSCALL_CLOBBERLIST \
3973f12c6dSFeiyang Chen ); \
4073f12c6dSFeiyang Chen _arg1; \
4173f12c6dSFeiyang Chen })
4273f12c6dSFeiyang Chen
4373f12c6dSFeiyang Chen #define my_syscall1(num, arg1) \
4473f12c6dSFeiyang Chen ({ \
4573f12c6dSFeiyang Chen register long _num __asm__ ("a7") = (num); \
4673f12c6dSFeiyang Chen register long _arg1 __asm__ ("a0") = (long)(arg1); \
4773f12c6dSFeiyang Chen \
4873f12c6dSFeiyang Chen __asm__ volatile ( \
4973f12c6dSFeiyang Chen "syscall 0\n" \
5073f12c6dSFeiyang Chen : "+r"(_arg1) \
5173f12c6dSFeiyang Chen : "r"(_num) \
522dca615aSZhangjin Wu : _NOLIBC_SYSCALL_CLOBBERLIST \
5373f12c6dSFeiyang Chen ); \
5473f12c6dSFeiyang Chen _arg1; \
5573f12c6dSFeiyang Chen })
5673f12c6dSFeiyang Chen
5773f12c6dSFeiyang Chen #define my_syscall2(num, arg1, arg2) \
5873f12c6dSFeiyang Chen ({ \
5973f12c6dSFeiyang Chen register long _num __asm__ ("a7") = (num); \
6073f12c6dSFeiyang Chen register long _arg1 __asm__ ("a0") = (long)(arg1); \
6173f12c6dSFeiyang Chen register long _arg2 __asm__ ("a1") = (long)(arg2); \
6273f12c6dSFeiyang Chen \
6373f12c6dSFeiyang Chen __asm__ volatile ( \
6473f12c6dSFeiyang Chen "syscall 0\n" \
6573f12c6dSFeiyang Chen : "+r"(_arg1) \
6673f12c6dSFeiyang Chen : "r"(_arg2), \
6773f12c6dSFeiyang Chen "r"(_num) \
682dca615aSZhangjin Wu : _NOLIBC_SYSCALL_CLOBBERLIST \
6973f12c6dSFeiyang Chen ); \
7073f12c6dSFeiyang Chen _arg1; \
7173f12c6dSFeiyang Chen })
7273f12c6dSFeiyang Chen
7373f12c6dSFeiyang Chen #define my_syscall3(num, arg1, arg2, arg3) \
7473f12c6dSFeiyang Chen ({ \
7573f12c6dSFeiyang Chen register long _num __asm__ ("a7") = (num); \
7673f12c6dSFeiyang Chen register long _arg1 __asm__ ("a0") = (long)(arg1); \
7773f12c6dSFeiyang Chen register long _arg2 __asm__ ("a1") = (long)(arg2); \
7873f12c6dSFeiyang Chen register long _arg3 __asm__ ("a2") = (long)(arg3); \
7973f12c6dSFeiyang Chen \
8073f12c6dSFeiyang Chen __asm__ volatile ( \
8173f12c6dSFeiyang Chen "syscall 0\n" \
8273f12c6dSFeiyang Chen : "+r"(_arg1) \
8373f12c6dSFeiyang Chen : "r"(_arg2), "r"(_arg3), \
8473f12c6dSFeiyang Chen "r"(_num) \
852dca615aSZhangjin Wu : _NOLIBC_SYSCALL_CLOBBERLIST \
8673f12c6dSFeiyang Chen ); \
8773f12c6dSFeiyang Chen _arg1; \
8873f12c6dSFeiyang Chen })
8973f12c6dSFeiyang Chen
9073f12c6dSFeiyang Chen #define my_syscall4(num, arg1, arg2, arg3, arg4) \
9173f12c6dSFeiyang Chen ({ \
9273f12c6dSFeiyang Chen register long _num __asm__ ("a7") = (num); \
9373f12c6dSFeiyang Chen register long _arg1 __asm__ ("a0") = (long)(arg1); \
9473f12c6dSFeiyang Chen register long _arg2 __asm__ ("a1") = (long)(arg2); \
9573f12c6dSFeiyang Chen register long _arg3 __asm__ ("a2") = (long)(arg3); \
9673f12c6dSFeiyang Chen register long _arg4 __asm__ ("a3") = (long)(arg4); \
9773f12c6dSFeiyang Chen \
9873f12c6dSFeiyang Chen __asm__ volatile ( \
9973f12c6dSFeiyang Chen "syscall 0\n" \
10073f12c6dSFeiyang Chen : "+r"(_arg1) \
10173f12c6dSFeiyang Chen : "r"(_arg2), "r"(_arg3), "r"(_arg4), \
10273f12c6dSFeiyang Chen "r"(_num) \
1032dca615aSZhangjin Wu : _NOLIBC_SYSCALL_CLOBBERLIST \
10473f12c6dSFeiyang Chen ); \
10573f12c6dSFeiyang Chen _arg1; \
10673f12c6dSFeiyang Chen })
10773f12c6dSFeiyang Chen
10873f12c6dSFeiyang Chen #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
10973f12c6dSFeiyang Chen ({ \
11073f12c6dSFeiyang Chen register long _num __asm__ ("a7") = (num); \
11173f12c6dSFeiyang Chen register long _arg1 __asm__ ("a0") = (long)(arg1); \
11273f12c6dSFeiyang Chen register long _arg2 __asm__ ("a1") = (long)(arg2); \
11373f12c6dSFeiyang Chen register long _arg3 __asm__ ("a2") = (long)(arg3); \
11473f12c6dSFeiyang Chen register long _arg4 __asm__ ("a3") = (long)(arg4); \
11573f12c6dSFeiyang Chen register long _arg5 __asm__ ("a4") = (long)(arg5); \
11673f12c6dSFeiyang Chen \
11773f12c6dSFeiyang Chen __asm__ volatile ( \
11873f12c6dSFeiyang Chen "syscall 0\n" \
11973f12c6dSFeiyang Chen : "+r"(_arg1) \
12073f12c6dSFeiyang Chen : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
12173f12c6dSFeiyang Chen "r"(_num) \
1222dca615aSZhangjin Wu : _NOLIBC_SYSCALL_CLOBBERLIST \
12373f12c6dSFeiyang Chen ); \
12473f12c6dSFeiyang Chen _arg1; \
12573f12c6dSFeiyang Chen })
12673f12c6dSFeiyang Chen
12773f12c6dSFeiyang Chen #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
12873f12c6dSFeiyang Chen ({ \
12973f12c6dSFeiyang Chen register long _num __asm__ ("a7") = (num); \
13073f12c6dSFeiyang Chen register long _arg1 __asm__ ("a0") = (long)(arg1); \
13173f12c6dSFeiyang Chen register long _arg2 __asm__ ("a1") = (long)(arg2); \
13273f12c6dSFeiyang Chen register long _arg3 __asm__ ("a2") = (long)(arg3); \
13373f12c6dSFeiyang Chen register long _arg4 __asm__ ("a3") = (long)(arg4); \
13473f12c6dSFeiyang Chen register long _arg5 __asm__ ("a4") = (long)(arg5); \
13573f12c6dSFeiyang Chen register long _arg6 __asm__ ("a5") = (long)(arg6); \
13673f12c6dSFeiyang Chen \
13773f12c6dSFeiyang Chen __asm__ volatile ( \
13873f12c6dSFeiyang Chen "syscall 0\n" \
13973f12c6dSFeiyang Chen : "+r"(_arg1) \
14073f12c6dSFeiyang Chen : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
14173f12c6dSFeiyang Chen "r"(_num) \
1422dca615aSZhangjin Wu : _NOLIBC_SYSCALL_CLOBBERLIST \
14373f12c6dSFeiyang Chen ); \
14473f12c6dSFeiyang Chen _arg1; \
14573f12c6dSFeiyang Chen })
14673f12c6dSFeiyang Chen
14773f12c6dSFeiyang Chen #if __loongarch_grlen == 32
14873f12c6dSFeiyang Chen #define LONG_BSTRINS "bstrins.w"
149fddc8f81SThomas Weißschuh #else /* __loongarch_grlen == 64 */
15073f12c6dSFeiyang Chen #define LONG_BSTRINS "bstrins.d"
15173f12c6dSFeiyang Chen #endif
15273f12c6dSFeiyang Chen
15373f12c6dSFeiyang Chen /* startup code */
_start(void)154bff60150SZhangjin Wu void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
15573f12c6dSFeiyang Chen {
15673f12c6dSFeiyang Chen __asm__ volatile (
157*61bd4621SZhangjin Wu "move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */
158*61bd4621SZhangjin Wu LONG_BSTRINS " $sp, $zero, 3, 0\n" /* $sp must be 16-byte aligned */
159*61bd4621SZhangjin Wu "bl _start_c\n" /* transfer to c runtime */
16073f12c6dSFeiyang Chen );
16173f12c6dSFeiyang Chen __builtin_unreachable();
16273f12c6dSFeiyang Chen }
16373f12c6dSFeiyang Chen
164fddc8f81SThomas Weißschuh #endif /* _NOLIBC_ARCH_LOONGARCH_H */
165