Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/include/nolibc/arch-sparc.h
26288 views
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 <[email protected]>
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
/* startup code */
156
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
157
{
158
__asm__ volatile (
159
/*
160
* Save argc pointer to o0, as arg1 of _start_c.
161
* Account for the window save area, which is 16 registers wide.
162
*/
163
#ifdef __arch64__
164
"add %sp, 128 + 2047, %o0\n" /* on sparc64 / v9 the stack is offset by 2047 */
165
#else
166
"add %sp, 64, %o0\n"
167
#endif
168
"b,a _start_c\n" /* transfer to c runtime */
169
);
170
__nolibc_entrypoint_epilogue();
171
}
172
173
static pid_t getpid(void);
174
175
static __attribute__((unused))
176
pid_t sys_fork(void)
177
{
178
pid_t parent, ret;
179
180
parent = getpid();
181
ret = my_syscall0(__NR_fork);
182
183
/* The syscall returns the parent pid in the child instead of 0 */
184
if (ret == parent)
185
return 0;
186
else
187
return ret;
188
}
189
#define sys_fork sys_fork
190
191
static __attribute__((unused))
192
pid_t sys_vfork(void)
193
{
194
pid_t parent, ret;
195
196
parent = getpid();
197
ret = my_syscall0(__NR_vfork);
198
199
/* The syscall returns the parent pid in the child instead of 0 */
200
if (ret == parent)
201
return 0;
202
else
203
return ret;
204
}
205
#define sys_vfork sys_vfork
206
207
#endif /* _NOLIBC_ARCH_SPARC_H */
208
209