File Index
Files and directories
Sign in
FILE

arch-sparc.h

File preview with syntax highlighting.

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