xref: /linux/tools/include/nolibc/arch-openrisc.h (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
1*97d66550SThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*97d66550SThomas Weißschuh /*
3*97d66550SThomas Weißschuh  * OpenRISC specific definitions for NOLIBC
4*97d66550SThomas Weißschuh  * Copyright (C) 2026 Thomas Weißschuh <linux@weissschuh.net>
5*97d66550SThomas Weißschuh  */
6*97d66550SThomas Weißschuh 
7*97d66550SThomas Weißschuh #ifndef _NOLIBC_ARCH_OPENRISC_H
8*97d66550SThomas Weißschuh #define _NOLIBC_ARCH_OPENRISC_H
9*97d66550SThomas Weißschuh 
10*97d66550SThomas Weißschuh #include "compiler.h"
11*97d66550SThomas Weißschuh #include "crt.h"
12*97d66550SThomas Weißschuh 
13*97d66550SThomas Weißschuh /*
14*97d66550SThomas Weißschuh  * Syscalls for OpenRISC:
15*97d66550SThomas Weißschuh  *   - syscall number is passed in r11
16*97d66550SThomas Weißschuh  *   - arguments are in r3, r4, r5, r6, r7, r8
17*97d66550SThomas Weißschuh  *   - the system call is performed by calling l.sys 1
18*97d66550SThomas Weißschuh  *   - syscall return value is in r11
19*97d66550SThomas Weißschuh  */
20*97d66550SThomas Weißschuh 
21*97d66550SThomas Weißschuh #define _NOLIBC_SYSCALL_CLOBBERLIST \
22*97d66550SThomas Weißschuh 	"r12", "r13", "r15", "r17", "r19", "r21", "r23", "r25", "r27", "r29", "r31", "memory"
23*97d66550SThomas Weißschuh 
24*97d66550SThomas Weißschuh #define __nolibc_syscall0(num)                                                \
25*97d66550SThomas Weißschuh ({                                                                            \
26*97d66550SThomas Weißschuh 	register long _num __asm__ ("r11") = (num);                           \
27*97d66550SThomas Weißschuh 									      \
28*97d66550SThomas Weißschuh 	__asm__ volatile (                                                    \
29*97d66550SThomas Weißschuh 		"l.sys 1\n"                                                   \
30*97d66550SThomas Weißschuh 		: "+r"(_num)                                                  \
31*97d66550SThomas Weißschuh 		:                                                             \
32*97d66550SThomas Weißschuh 		: "r3", "r4", "r5", "r6", "r7", "r8",                         \
33*97d66550SThomas Weißschuh 		  _NOLIBC_SYSCALL_CLOBBERLIST                                 \
34*97d66550SThomas Weißschuh 	);                                                                    \
35*97d66550SThomas Weißschuh 	_num;                                                                 \
36*97d66550SThomas Weißschuh })
37*97d66550SThomas Weißschuh 
38*97d66550SThomas Weißschuh #define __nolibc_syscall1(num, arg1)                                          \
39*97d66550SThomas Weißschuh ({                                                                            \
40*97d66550SThomas Weißschuh 	register long _num __asm__ ("r11") = (num);                           \
41*97d66550SThomas Weißschuh 	register long _arg1 __asm__ ("r3") = (long)(arg1);                    \
42*97d66550SThomas Weißschuh 									      \
43*97d66550SThomas Weißschuh 	__asm__ volatile (                                                    \
44*97d66550SThomas Weißschuh 		"l.sys 1\n"                                                   \
45*97d66550SThomas Weißschuh 		: "+r"(_num)                                                  \
46*97d66550SThomas Weißschuh 		: "r"(_arg1)                                                  \
47*97d66550SThomas Weißschuh 		: "r4", "r5", "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST   \
48*97d66550SThomas Weißschuh 	);                                                                    \
49*97d66550SThomas Weißschuh 	_num;                                                                 \
50*97d66550SThomas Weißschuh })
51*97d66550SThomas Weißschuh 
52*97d66550SThomas Weißschuh #define __nolibc_syscall2(num, arg1, arg2)                                    \
53*97d66550SThomas Weißschuh ({                                                                            \
54*97d66550SThomas Weißschuh 	register long _num __asm__ ("r11") = (num);                           \
55*97d66550SThomas Weißschuh 	register long _arg1 __asm__ ("r3") = (long)(arg1);                    \
56*97d66550SThomas Weißschuh 	register long _arg2 __asm__ ("r4") = (long)(arg2);                    \
57*97d66550SThomas Weißschuh 									      \
58*97d66550SThomas Weißschuh 	__asm__ volatile (                                                    \
59*97d66550SThomas Weißschuh 		"l.sys 1\n"                                                   \
60*97d66550SThomas Weißschuh 		: "+r"(_num)                                                  \
61*97d66550SThomas Weißschuh 		: "r"(_arg1), "r"(_arg2)                                      \
62*97d66550SThomas Weißschuh 		: "r5", "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST         \
63*97d66550SThomas Weißschuh 	);                                                                    \
64*97d66550SThomas Weißschuh 	_num;                                                                 \
65*97d66550SThomas Weißschuh })
66*97d66550SThomas Weißschuh 
67*97d66550SThomas Weißschuh #define __nolibc_syscall3(num, arg1, arg2, arg3)                              \
68*97d66550SThomas Weißschuh ({                                                                            \
69*97d66550SThomas Weißschuh 	register long _num __asm__ ("r11") = (num);                           \
70*97d66550SThomas Weißschuh 	register long _arg1 __asm__ ("r3") = (long)(arg1);                    \
71*97d66550SThomas Weißschuh 	register long _arg2 __asm__ ("r4") = (long)(arg2);                    \
72*97d66550SThomas Weißschuh 	register long _arg3 __asm__ ("r5") = (long)(arg3);                    \
73*97d66550SThomas Weißschuh 									      \
74*97d66550SThomas Weißschuh 	__asm__ volatile (                                                    \
75*97d66550SThomas Weißschuh 		"l.sys 1\n"                                                   \
76*97d66550SThomas Weißschuh 		: "+r"(_num)                                                  \
77*97d66550SThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3)                          \
78*97d66550SThomas Weißschuh 		: "r6", "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST               \
79*97d66550SThomas Weißschuh 	);                                                                    \
80*97d66550SThomas Weißschuh 	_num;                                                                 \
81*97d66550SThomas Weißschuh })
82*97d66550SThomas Weißschuh 
83*97d66550SThomas Weißschuh #define __nolibc_syscall4(num, arg1, arg2, arg3, arg4)                        \
84*97d66550SThomas Weißschuh ({                                                                            \
85*97d66550SThomas Weißschuh 	register long _num __asm__ ("r11") = (num);                           \
86*97d66550SThomas Weißschuh 	register long _arg1 __asm__ ("r3") = (long)(arg1);                    \
87*97d66550SThomas Weißschuh 	register long _arg2 __asm__ ("r4") = (long)(arg2);                    \
88*97d66550SThomas Weißschuh 	register long _arg3 __asm__ ("r5") = (long)(arg3);                    \
89*97d66550SThomas Weißschuh 	register long _arg4 __asm__ ("r6") = (long)(arg4);                    \
90*97d66550SThomas Weißschuh 									      \
91*97d66550SThomas Weißschuh 	__asm__ volatile (                                                    \
92*97d66550SThomas Weißschuh 		"l.sys 1\n"                                                   \
93*97d66550SThomas Weißschuh 		: "+r"(_num)                                                  \
94*97d66550SThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4)              \
95*97d66550SThomas Weißschuh 		: "r7", "r8", _NOLIBC_SYSCALL_CLOBBERLIST                     \
96*97d66550SThomas Weißschuh 	);                                                                    \
97*97d66550SThomas Weißschuh 	_num;                                                                 \
98*97d66550SThomas Weißschuh })
99*97d66550SThomas Weißschuh 
100*97d66550SThomas Weißschuh #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5)                  \
101*97d66550SThomas Weißschuh ({                                                                            \
102*97d66550SThomas Weißschuh 	register long _num __asm__ ("r11") = (num);                           \
103*97d66550SThomas Weißschuh 	register long _arg1 __asm__ ("r3") = (long)(arg1);                    \
104*97d66550SThomas Weißschuh 	register long _arg2 __asm__ ("r4") = (long)(arg2);                    \
105*97d66550SThomas Weißschuh 	register long _arg3 __asm__ ("r5") = (long)(arg3);                    \
106*97d66550SThomas Weißschuh 	register long _arg4 __asm__ ("r6") = (long)(arg4);                    \
107*97d66550SThomas Weißschuh 	register long _arg5 __asm__ ("r7") = (long)(arg5);                    \
108*97d66550SThomas Weißschuh 									      \
109*97d66550SThomas Weißschuh 	__asm__ volatile (                                                    \
110*97d66550SThomas Weißschuh 		"l.sys 1\n"                                                   \
111*97d66550SThomas Weißschuh 		: "+r"(_num)                                                  \
112*97d66550SThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5)  \
113*97d66550SThomas Weißschuh 		: "r8", _NOLIBC_SYSCALL_CLOBBERLIST                           \
114*97d66550SThomas Weißschuh 	);                                                                    \
115*97d66550SThomas Weißschuh 	_num;                                                                 \
116*97d66550SThomas Weißschuh })
117*97d66550SThomas Weißschuh 
118*97d66550SThomas Weißschuh #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)            \
119*97d66550SThomas Weißschuh ({                                                                            \
120*97d66550SThomas Weißschuh 	register long _num __asm__ ("r11") = (num);                           \
121*97d66550SThomas Weißschuh 	register long _arg1 __asm__ ("r3") = (long)(arg1);                    \
122*97d66550SThomas Weißschuh 	register long _arg2 __asm__ ("r4") = (long)(arg2);                    \
123*97d66550SThomas Weißschuh 	register long _arg3 __asm__ ("r5") = (long)(arg3);                    \
124*97d66550SThomas Weißschuh 	register long _arg4 __asm__ ("r6") = (long)(arg4);                    \
125*97d66550SThomas Weißschuh 	register long _arg5 __asm__ ("r7") = (long)(arg5);                    \
126*97d66550SThomas Weißschuh 	register long _arg6 __asm__ ("r8") = (long)(arg6);                    \
127*97d66550SThomas Weißschuh 									      \
128*97d66550SThomas Weißschuh 	__asm__ volatile (                                                    \
129*97d66550SThomas Weißschuh 		"l.sys 1\n"                                                   \
130*97d66550SThomas Weißschuh 		: "+r"(_num)                                                  \
131*97d66550SThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
132*97d66550SThomas Weißschuh 		  "r"(_arg6)                                                  \
133*97d66550SThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
134*97d66550SThomas Weißschuh 	);                                                                    \
135*97d66550SThomas Weißschuh 	_num;                                                                 \
136*97d66550SThomas Weißschuh })
137*97d66550SThomas Weißschuh 
138*97d66550SThomas Weißschuh #ifndef NOLIBC_NO_RUNTIME
139*97d66550SThomas Weißschuh /* startup code */
140*97d66550SThomas Weißschuh void _start_wrapper(void);
141*97d66550SThomas Weißschuh void __attribute__((weak,noreturn))
142*97d66550SThomas Weißschuh __nolibc_entrypoint __nolibc_no_stack_protector
143*97d66550SThomas Weißschuh _start_wrapper(void)
144*97d66550SThomas Weißschuh {
145*97d66550SThomas Weißschuh 	__asm__ volatile (
146*97d66550SThomas Weißschuh 		".global _start\n"           /* The C function will have a prologue,         */
147*97d66550SThomas Weißschuh 		".type _start, @function\n"  /* corrupting "sp/r1"                           */
148*97d66550SThomas Weißschuh 		".weak _start\n"
149*97d66550SThomas Weißschuh 		"_start:\n"
150*97d66550SThomas Weißschuh 
151*97d66550SThomas Weißschuh 		"l.jal _start_c\n"           /* transfer to c runtime                        */
152*97d66550SThomas Weißschuh 		"l.or r3,r1,r1\n"            /* save stack pointer to r3, as arg1 of _start_c */
153*97d66550SThomas Weißschuh 
154*97d66550SThomas Weißschuh 		".size _start, .-_start\n"
155*97d66550SThomas Weißschuh 	);
156*97d66550SThomas Weißschuh 	__nolibc_entrypoint_epilogue();
157*97d66550SThomas Weißschuh }
158*97d66550SThomas Weißschuh #endif /* NOLIBC_NO_RUNTIME */
159*97d66550SThomas Weißschuh 
160*97d66550SThomas Weißschuh #endif /* _NOLIBC_ARCH_OPENRISC_H */
161