xref: /linux/tools/include/nolibc/arch-sparc.h (revision 015a99fa76650e7d6efa3e36f20c0f5b346fe9ce)
1*8e193029SThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*8e193029SThomas Weißschuh /*
3*8e193029SThomas Weißschuh  * SPARC (32bit and 64bit) specific definitions for NOLIBC
4*8e193029SThomas Weißschuh  * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
5*8e193029SThomas Weißschuh  */
6*8e193029SThomas Weißschuh 
7*8e193029SThomas Weißschuh #ifndef _NOLIBC_ARCH_SPARC_H
8*8e193029SThomas Weißschuh #define _NOLIBC_ARCH_SPARC_H
9*8e193029SThomas Weißschuh 
10*8e193029SThomas Weißschuh #include <linux/unistd.h>
11*8e193029SThomas Weißschuh 
12*8e193029SThomas Weißschuh #include "compiler.h"
13*8e193029SThomas Weißschuh #include "crt.h"
14*8e193029SThomas Weißschuh 
15*8e193029SThomas Weißschuh /*
16*8e193029SThomas Weißschuh  * Syscalls for SPARC:
17*8e193029SThomas Weißschuh  *   - registers are native word size
18*8e193029SThomas Weißschuh  *   - syscall number is passed in g1
19*8e193029SThomas Weißschuh  *   - arguments are in o0-o5
20*8e193029SThomas Weißschuh  *   - the system call is performed by calling a trap instruction
21*8e193029SThomas Weißschuh  *   - syscall return value is in o0
22*8e193029SThomas Weißschuh  *   - syscall error flag is in the carry bit of the processor status register
23*8e193029SThomas Weißschuh  */
24*8e193029SThomas Weißschuh 
25*8e193029SThomas Weißschuh #ifdef __arch64__
26*8e193029SThomas Weißschuh 
27*8e193029SThomas Weißschuh #define _NOLIBC_SYSCALL "t	0x6d\n"                                       \
28*8e193029SThomas Weißschuh 			"bcs,a	%%xcc, 1f\n"                                  \
29*8e193029SThomas Weißschuh 			"sub	%%g0, %%o0, %%o0\n"                           \
30*8e193029SThomas Weißschuh 			"1:\n"
31*8e193029SThomas Weißschuh 
32*8e193029SThomas Weißschuh #else
33*8e193029SThomas Weißschuh 
34*8e193029SThomas Weißschuh #define _NOLIBC_SYSCALL "t	0x10\n"                                       \
35*8e193029SThomas Weißschuh 			"bcs,a	1f\n"                                         \
36*8e193029SThomas Weißschuh 			"sub	%%g0, %%o0, %%o0\n"                           \
37*8e193029SThomas Weißschuh 			"1:\n"
38*8e193029SThomas Weißschuh 
39*8e193029SThomas Weißschuh #endif /* __arch64__ */
40*8e193029SThomas Weißschuh 
41*8e193029SThomas Weißschuh #define my_syscall0(num)                                                      \
42*8e193029SThomas Weißschuh ({                                                                            \
43*8e193029SThomas Weißschuh 	register long _num  __asm__ ("g1") = (num);                           \
44*8e193029SThomas Weißschuh 	register long _arg1 __asm__ ("o0");                                   \
45*8e193029SThomas Weißschuh 									      \
46*8e193029SThomas Weißschuh 	__asm__ volatile (                                                    \
47*8e193029SThomas Weißschuh 		_NOLIBC_SYSCALL                                               \
48*8e193029SThomas Weißschuh 		: "+r"(_arg1)                                                 \
49*8e193029SThomas Weißschuh 		: "r"(_num)                                                   \
50*8e193029SThomas Weißschuh 		: "memory", "cc"                                              \
51*8e193029SThomas Weißschuh 	);                                                                    \
52*8e193029SThomas Weißschuh 	_arg1;                                                                \
53*8e193029SThomas Weißschuh })
54*8e193029SThomas Weißschuh 
55*8e193029SThomas Weißschuh #define my_syscall1(num, arg1)                                                \
56*8e193029SThomas Weißschuh ({                                                                            \
57*8e193029SThomas Weißschuh 	register long _num  __asm__ ("g1") = (num);                           \
58*8e193029SThomas Weißschuh 	register long _arg1 __asm__ ("o0") = (long)(arg1);                    \
59*8e193029SThomas Weißschuh 									      \
60*8e193029SThomas Weißschuh 	__asm__ volatile (                                                    \
61*8e193029SThomas Weißschuh 		_NOLIBC_SYSCALL                                               \
62*8e193029SThomas Weißschuh 		: "+r"(_arg1)                                                 \
63*8e193029SThomas Weißschuh 		: "r"(_num)                                                   \
64*8e193029SThomas Weißschuh 		: "memory", "cc"                                              \
65*8e193029SThomas Weißschuh 	);                                                                    \
66*8e193029SThomas Weißschuh 	_arg1;                                                                \
67*8e193029SThomas Weißschuh })
68*8e193029SThomas Weißschuh 
69*8e193029SThomas Weißschuh #define my_syscall2(num, arg1, arg2)                                          \
70*8e193029SThomas Weißschuh ({                                                                            \
71*8e193029SThomas Weißschuh 	register long _num  __asm__ ("g1") = (num);                           \
72*8e193029SThomas Weißschuh 	register long _arg1 __asm__ ("o0") = (long)(arg1);                    \
73*8e193029SThomas Weißschuh 	register long _arg2 __asm__ ("o1") = (long)(arg2);                    \
74*8e193029SThomas Weißschuh 									      \
75*8e193029SThomas Weißschuh 	__asm__ volatile (                                                    \
76*8e193029SThomas Weißschuh 		_NOLIBC_SYSCALL                                               \
77*8e193029SThomas Weißschuh 		: "+r"(_arg1)                                                 \
78*8e193029SThomas Weißschuh 		: "r"(_arg2), "r"(_num)                                       \
79*8e193029SThomas Weißschuh 		: "memory", "cc"                                              \
80*8e193029SThomas Weißschuh 	);                                                                    \
81*8e193029SThomas Weißschuh 	_arg1;                                                                \
82*8e193029SThomas Weißschuh })
83*8e193029SThomas Weißschuh 
84*8e193029SThomas Weißschuh #define my_syscall3(num, arg1, arg2, arg3)                                    \
85*8e193029SThomas Weißschuh ({                                                                            \
86*8e193029SThomas Weißschuh 	register long _num  __asm__ ("g1") = (num);                           \
87*8e193029SThomas Weißschuh 	register long _arg1 __asm__ ("o0") = (long)(arg1);                    \
88*8e193029SThomas Weißschuh 	register long _arg2 __asm__ ("o1") = (long)(arg2);                    \
89*8e193029SThomas Weißschuh 	register long _arg3 __asm__ ("o2") = (long)(arg3);                    \
90*8e193029SThomas Weißschuh 									      \
91*8e193029SThomas Weißschuh 	__asm__ volatile (                                                    \
92*8e193029SThomas Weißschuh 		_NOLIBC_SYSCALL                                               \
93*8e193029SThomas Weißschuh 		: "+r"(_arg1)                                                 \
94*8e193029SThomas Weißschuh 		: "r"(_arg2), "r"(_arg3), "r"(_num)                           \
95*8e193029SThomas Weißschuh 		: "memory", "cc"                                              \
96*8e193029SThomas Weißschuh 	);                                                                    \
97*8e193029SThomas Weißschuh 	_arg1;                                                                \
98*8e193029SThomas Weißschuh })
99*8e193029SThomas Weißschuh 
100*8e193029SThomas Weißschuh #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
101*8e193029SThomas Weißschuh ({                                                                            \
102*8e193029SThomas Weißschuh 	register long _num  __asm__ ("g1") = (num);                           \
103*8e193029SThomas Weißschuh 	register long _arg1 __asm__ ("o0") = (long)(arg1);                    \
104*8e193029SThomas Weißschuh 	register long _arg2 __asm__ ("o1") = (long)(arg2);                    \
105*8e193029SThomas Weißschuh 	register long _arg3 __asm__ ("o2") = (long)(arg3);                    \
106*8e193029SThomas Weißschuh 	register long _arg4 __asm__ ("o3") = (long)(arg4);                    \
107*8e193029SThomas Weißschuh 									      \
108*8e193029SThomas Weißschuh 	__asm__ volatile (                                                    \
109*8e193029SThomas Weißschuh 		_NOLIBC_SYSCALL                                               \
110*8e193029SThomas Weißschuh 		: "+r"(_arg1)                                                 \
111*8e193029SThomas Weißschuh 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_num)               \
112*8e193029SThomas Weißschuh 		: "memory", "cc"                                              \
113*8e193029SThomas Weißschuh 	);                                                                    \
114*8e193029SThomas Weißschuh 	_arg1;                                                                \
115*8e193029SThomas Weißschuh })
116*8e193029SThomas Weißschuh 
117*8e193029SThomas Weißschuh #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
118*8e193029SThomas Weißschuh ({                                                                            \
119*8e193029SThomas Weißschuh 	register long _num  __asm__ ("g1") = (num);                           \
120*8e193029SThomas Weißschuh 	register long _arg1 __asm__ ("o0") = (long)(arg1);                    \
121*8e193029SThomas Weißschuh 	register long _arg2 __asm__ ("o1") = (long)(arg2);                    \
122*8e193029SThomas Weißschuh 	register long _arg3 __asm__ ("o2") = (long)(arg3);                    \
123*8e193029SThomas Weißschuh 	register long _arg4 __asm__ ("o3") = (long)(arg4);                    \
124*8e193029SThomas Weißschuh 	register long _arg5 __asm__ ("o4") = (long)(arg5);                    \
125*8e193029SThomas Weißschuh 									      \
126*8e193029SThomas Weißschuh 	__asm__ volatile (                                                    \
127*8e193029SThomas Weißschuh 		_NOLIBC_SYSCALL                                               \
128*8e193029SThomas Weißschuh 		: "+r"(_arg1)                                                 \
129*8e193029SThomas Weißschuh 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_num)   \
130*8e193029SThomas Weißschuh 		: "memory", "cc"                                              \
131*8e193029SThomas Weißschuh 	);                                                                    \
132*8e193029SThomas Weißschuh 	_arg1;                                                                \
133*8e193029SThomas Weißschuh })
134*8e193029SThomas Weißschuh 
135*8e193029SThomas Weißschuh #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
136*8e193029SThomas Weißschuh ({                                                                            \
137*8e193029SThomas Weißschuh 	register long _num  __asm__ ("g1") = (num);                           \
138*8e193029SThomas Weißschuh 	register long _arg1 __asm__ ("o0") = (long)(arg1);                    \
139*8e193029SThomas Weißschuh 	register long _arg2 __asm__ ("o1") = (long)(arg2);                    \
140*8e193029SThomas Weißschuh 	register long _arg3 __asm__ ("o2") = (long)(arg3);                    \
141*8e193029SThomas Weißschuh 	register long _arg4 __asm__ ("o3") = (long)(arg4);                    \
142*8e193029SThomas Weißschuh 	register long _arg5 __asm__ ("o4") = (long)(arg5);                    \
143*8e193029SThomas Weißschuh 	register long _arg6 __asm__ ("o5") = (long)(arg6);                    \
144*8e193029SThomas Weißschuh 									      \
145*8e193029SThomas Weißschuh 	__asm__ volatile (                                                    \
146*8e193029SThomas Weißschuh 		_NOLIBC_SYSCALL                                               \
147*8e193029SThomas Weißschuh 		: "+r"(_arg1)                                                 \
148*8e193029SThomas Weißschuh 		: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
149*8e193029SThomas Weißschuh 		  "r"(_num)                                                   \
150*8e193029SThomas Weißschuh 		: "memory", "cc"                                              \
151*8e193029SThomas Weißschuh 	);                                                                    \
152*8e193029SThomas Weißschuh 	_arg1;                                                                \
153*8e193029SThomas Weißschuh })
154*8e193029SThomas Weißschuh 
155*8e193029SThomas Weißschuh /* startup code */
_start(void)156*8e193029SThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
157*8e193029SThomas Weißschuh {
158*8e193029SThomas Weißschuh 	__asm__ volatile (
159*8e193029SThomas Weißschuh 		/*
160*8e193029SThomas Weißschuh 		 * Save argc pointer to o0, as arg1 of _start_c.
161*8e193029SThomas Weißschuh 		 * Account for the window save area, which is 16 registers wide.
162*8e193029SThomas Weißschuh 		 */
163*8e193029SThomas Weißschuh #ifdef __arch64__
164*8e193029SThomas Weißschuh 		"add %sp, 128 + 2047, %o0\n" /* on sparc64 / v9 the stack is offset by 2047 */
165*8e193029SThomas Weißschuh #else
166*8e193029SThomas Weißschuh 		"add %sp, 64, %o0\n"
167*8e193029SThomas Weißschuh #endif
168*8e193029SThomas Weißschuh 		"b,a _start_c\n"     /* transfer to c runtime */
169*8e193029SThomas Weißschuh 	);
170*8e193029SThomas Weißschuh 	__nolibc_entrypoint_epilogue();
171*8e193029SThomas Weißschuh }
172*8e193029SThomas Weißschuh 
173*8e193029SThomas Weißschuh static pid_t getpid(void);
174*8e193029SThomas Weißschuh 
175*8e193029SThomas Weißschuh static __attribute__((unused))
sys_fork(void)176*8e193029SThomas Weißschuh pid_t sys_fork(void)
177*8e193029SThomas Weißschuh {
178*8e193029SThomas Weißschuh 	pid_t parent, ret;
179*8e193029SThomas Weißschuh 
180*8e193029SThomas Weißschuh 	parent = getpid();
181*8e193029SThomas Weißschuh 	ret = my_syscall0(__NR_fork);
182*8e193029SThomas Weißschuh 
183*8e193029SThomas Weißschuh 	/* The syscall returns the parent pid in the child instead of 0 */
184*8e193029SThomas Weißschuh 	if (ret == parent)
185*8e193029SThomas Weißschuh 		return 0;
186*8e193029SThomas Weißschuh 	else
187*8e193029SThomas Weißschuh 		return ret;
188*8e193029SThomas Weißschuh }
189*8e193029SThomas Weißschuh #define sys_fork sys_fork
190*8e193029SThomas Weißschuh 
191*8e193029SThomas Weißschuh #endif /* _NOLIBC_ARCH_SPARC_H */
192