xref: /linux/tools/include/nolibc/arch-alpha.h (revision 67f8bc848ee31831336bd478e57d2f993551902e)
1*b58afc8dSThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*b58afc8dSThomas Weißschuh /*
3*b58afc8dSThomas Weißschuh  * Alpha specific definitions for NOLIBC
4*b58afc8dSThomas Weißschuh  * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
5*b58afc8dSThomas Weißschuh  */
6*b58afc8dSThomas Weißschuh 
7*b58afc8dSThomas Weißschuh #ifndef _NOLIBC_ARCH_ALPHA_H
8*b58afc8dSThomas Weißschuh #define _NOLIBC_ARCH_ALPHA_H
9*b58afc8dSThomas Weißschuh 
10*b58afc8dSThomas Weißschuh #include "compiler.h"
11*b58afc8dSThomas Weißschuh #include "crt.h"
12*b58afc8dSThomas Weißschuh 
13*b58afc8dSThomas Weißschuh /*
14*b58afc8dSThomas Weißschuh  * Syscalls for Alpha:
15*b58afc8dSThomas Weißschuh  *   - registers are 64-bit
16*b58afc8dSThomas Weißschuh  *   - syscall number is passed in $0/v0
17*b58afc8dSThomas Weißschuh  *   - the system call is performed by calling callsys
18*b58afc8dSThomas Weißschuh  *   - syscall return comes in $0/v0, error flag in $19/a3
19*b58afc8dSThomas Weißschuh  *   - arguments are passed in $16/a0 to $21/a5
20*b58afc8dSThomas Weißschuh  *   - GCC does not support symbol register names
21*b58afc8dSThomas Weißschuh  */
22*b58afc8dSThomas Weißschuh 
23*b58afc8dSThomas Weißschuh #define _NOLIBC_SYSCALL_CLOBBERLIST \
24*b58afc8dSThomas Weißschuh 	"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
25*b58afc8dSThomas Weißschuh 	"$22", "$23", "$24", "$25", "$27", "$28", "memory", "cc"
26*b58afc8dSThomas Weißschuh 
27*b58afc8dSThomas Weißschuh #define __nolibc_syscall0(num)                                                \
28*b58afc8dSThomas Weißschuh ({                                                                            \
29*b58afc8dSThomas Weißschuh 	register long _num __asm__ ("$0") = (num);                            \
30*b58afc8dSThomas Weißschuh 	register long _err __asm__ ("$19");                                   \
31*b58afc8dSThomas Weißschuh                                                                               \
32*b58afc8dSThomas Weißschuh 	__asm__ volatile (                                                    \
33*b58afc8dSThomas Weißschuh 		"callsys"                                                     \
34*b58afc8dSThomas Weißschuh 		: "+r"(_num), "=r"(_err)                                      \
35*b58afc8dSThomas Weißschuh 		:                                                             \
36*b58afc8dSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST,                                \
37*b58afc8dSThomas Weißschuh 		  "$16", "$17", "$18", "$20", "$21"                           \
38*b58afc8dSThomas Weißschuh 	);                                                                    \
39*b58afc8dSThomas Weißschuh 	_err ? -_num : _num;                                                  \
40*b58afc8dSThomas Weißschuh })
41*b58afc8dSThomas Weißschuh 
42*b58afc8dSThomas Weißschuh #define __nolibc_syscall1(num, arg1)                                          \
43*b58afc8dSThomas Weißschuh ({                                                                            \
44*b58afc8dSThomas Weißschuh 	register long _num __asm__ ("$0") = (num);                            \
45*b58afc8dSThomas Weißschuh 	register long _err __asm__ ("$19");                                   \
46*b58afc8dSThomas Weißschuh 	register long _arg1 __asm__ ("$16") = (long)(arg1);                   \
47*b58afc8dSThomas Weißschuh                                                                               \
48*b58afc8dSThomas Weißschuh 	__asm__ volatile (                                                    \
49*b58afc8dSThomas Weißschuh 		"callsys"                                                     \
50*b58afc8dSThomas Weißschuh 		: "+r"(_num), "=r"(_err)                                      \
51*b58afc8dSThomas Weißschuh 		: "r"(_arg1)                                                  \
52*b58afc8dSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST, "$17", "$18", "$20", "$21"     \
53*b58afc8dSThomas Weißschuh 	);                                                                    \
54*b58afc8dSThomas Weißschuh 	_err ? -_num : _num;                                                  \
55*b58afc8dSThomas Weißschuh })
56*b58afc8dSThomas Weißschuh 
57*b58afc8dSThomas Weißschuh #define __nolibc_syscall2(num, arg1, arg2)                                    \
58*b58afc8dSThomas Weißschuh ({                                                                            \
59*b58afc8dSThomas Weißschuh 	register long _num __asm__ ("$0") = (num);                            \
60*b58afc8dSThomas Weißschuh 	register long _err __asm__ ("$19");                                   \
61*b58afc8dSThomas Weißschuh 	register long _arg1 __asm__ ("$16") = (long)(arg1);                   \
62*b58afc8dSThomas Weißschuh 	register long _arg2 __asm__ ("$17") = (long)(arg2);                   \
63*b58afc8dSThomas Weißschuh                                                                               \
64*b58afc8dSThomas Weißschuh 	__asm__ volatile (                                                    \
65*b58afc8dSThomas Weißschuh 		"callsys"                                                     \
66*b58afc8dSThomas Weißschuh 		: "+r"(_num), "=r"(_err)                                      \
67*b58afc8dSThomas Weißschuh 		: "r"(_arg1), "r"(_arg2)                                      \
68*b58afc8dSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST, "$18", "$20", "$21"            \
69*b58afc8dSThomas Weißschuh 	);                                                                    \
70*b58afc8dSThomas Weißschuh 	_err ? -_num : _num;                                                  \
71*b58afc8dSThomas Weißschuh })
72*b58afc8dSThomas Weißschuh 
73*b58afc8dSThomas Weißschuh #define __nolibc_syscall3(num, arg1, arg2, arg3)                              \
74*b58afc8dSThomas Weißschuh ({                                                                            \
75*b58afc8dSThomas Weißschuh 	register long _num __asm__ ("$0") = (num);                            \
76*b58afc8dSThomas Weißschuh 	register long _err __asm__ ("$19");                                   \
77*b58afc8dSThomas Weißschuh 	register long _arg1 __asm__ ("$16") = (long)(arg1);                   \
78*b58afc8dSThomas Weißschuh 	register long _arg2 __asm__ ("$17") = (long)(arg2);                   \
79*b58afc8dSThomas Weißschuh 	register long _arg3 __asm__ ("$18") = (long)(arg3);                   \
80*b58afc8dSThomas Weißschuh                                                                               \
81*b58afc8dSThomas Weißschuh 	__asm__ volatile (                                                    \
82*b58afc8dSThomas Weißschuh 		"callsys"                                                     \
83*b58afc8dSThomas Weißschuh 		: "+r"(_num), "=r"(_err)                                      \
84*b58afc8dSThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3)                          \
85*b58afc8dSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST, "$20", "$21"                   \
86*b58afc8dSThomas Weißschuh 	);                                                                    \
87*b58afc8dSThomas Weißschuh 	_err ? -_num : _num;                                                  \
88*b58afc8dSThomas Weißschuh })
89*b58afc8dSThomas Weißschuh 
90*b58afc8dSThomas Weißschuh #define __nolibc_syscall4(num, arg1, arg2, arg3, arg4)                        \
91*b58afc8dSThomas Weißschuh ({                                                                            \
92*b58afc8dSThomas Weißschuh 	register long _num __asm__ ("$0") = (num);                            \
93*b58afc8dSThomas Weißschuh 	register long _arg1 __asm__ ("$16") = (long)(arg1);                   \
94*b58afc8dSThomas Weißschuh 	register long _arg2 __asm__ ("$17") = (long)(arg2);                   \
95*b58afc8dSThomas Weißschuh 	register long _arg3 __asm__ ("$18") = (long)(arg3);                   \
96*b58afc8dSThomas Weißschuh 	register long _arg4 __asm__ ("$19") = (long)(arg4);                   \
97*b58afc8dSThomas Weißschuh                                                                               \
98*b58afc8dSThomas Weißschuh 	__asm__ volatile (                                                    \
99*b58afc8dSThomas Weißschuh 		"callsys"                                                     \
100*b58afc8dSThomas Weißschuh 		: "+r"(_num), "+r"(_arg4)                                     \
101*b58afc8dSThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3)                          \
102*b58afc8dSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST, "$20", "$21"                   \
103*b58afc8dSThomas Weißschuh 	);                                                                    \
104*b58afc8dSThomas Weißschuh 	_arg4 ? -_num : _num;                                                 \
105*b58afc8dSThomas Weißschuh })
106*b58afc8dSThomas Weißschuh 
107*b58afc8dSThomas Weißschuh #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5)                  \
108*b58afc8dSThomas Weißschuh ({                                                                            \
109*b58afc8dSThomas Weißschuh 	register long _num __asm__ ("$0") = (num);                            \
110*b58afc8dSThomas Weißschuh 	register long _arg1 __asm__ ("$16") = (long)(arg1);                   \
111*b58afc8dSThomas Weißschuh 	register long _arg2 __asm__ ("$17") = (long)(arg2);                   \
112*b58afc8dSThomas Weißschuh 	register long _arg3 __asm__ ("$18") = (long)(arg3);                   \
113*b58afc8dSThomas Weißschuh 	register long _arg4 __asm__ ("$19") = (long)(arg4);                   \
114*b58afc8dSThomas Weißschuh 	register long _arg5 __asm__ ("$20") = (long)(arg5);                   \
115*b58afc8dSThomas Weißschuh                                                                               \
116*b58afc8dSThomas Weißschuh 	__asm__ volatile (                                                    \
117*b58afc8dSThomas Weißschuh 		"callsys"                                                     \
118*b58afc8dSThomas Weißschuh 		: "+r"(_num), "+r"(_arg4)                                     \
119*b58afc8dSThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg5)              \
120*b58afc8dSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST, "$21"                          \
121*b58afc8dSThomas Weißschuh 	);                                                                    \
122*b58afc8dSThomas Weißschuh 	_arg4 ? -_num : _num;                                                 \
123*b58afc8dSThomas Weißschuh })
124*b58afc8dSThomas Weißschuh 
125*b58afc8dSThomas Weißschuh #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)            \
126*b58afc8dSThomas Weißschuh ({                                                                            \
127*b58afc8dSThomas Weißschuh 	register long _num __asm__ ("$0") = (num);                            \
128*b58afc8dSThomas Weißschuh 	register long _arg1 __asm__ ("$16") = (long)(arg1);                   \
129*b58afc8dSThomas Weißschuh 	register long _arg2 __asm__ ("$17") = (long)(arg2);                   \
130*b58afc8dSThomas Weißschuh 	register long _arg3 __asm__ ("$18") = (long)(arg3);                   \
131*b58afc8dSThomas Weißschuh 	register long _arg4 __asm__ ("$19") = (long)(arg4);                   \
132*b58afc8dSThomas Weißschuh 	register long _arg5 __asm__ ("$20") = (long)(arg5);                   \
133*b58afc8dSThomas Weißschuh 	register long _arg6 __asm__ ("$21") = (long)(arg6);                   \
134*b58afc8dSThomas Weißschuh                                                                               \
135*b58afc8dSThomas Weißschuh 	__asm__ volatile (                                                    \
136*b58afc8dSThomas Weißschuh 		"callsys"                                                     \
137*b58afc8dSThomas Weißschuh 		: "+r"(_num), "+r"(_arg4)                                     \
138*b58afc8dSThomas Weißschuh 		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg5),             \
139*b58afc8dSThomas Weißschuh 		  "r"(_arg6)                                                  \
140*b58afc8dSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
141*b58afc8dSThomas Weißschuh 	);                                                                    \
142*b58afc8dSThomas Weißschuh 	_arg4 ? -_num : _num;                                                 \
143*b58afc8dSThomas Weißschuh })
144*b58afc8dSThomas Weißschuh 
145*b58afc8dSThomas Weißschuh /* startup code */
146*b58afc8dSThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_protector
147*b58afc8dSThomas Weißschuh _start(void)
148*b58afc8dSThomas Weißschuh {
149*b58afc8dSThomas Weißschuh 	__asm__ volatile (
150*b58afc8dSThomas Weißschuh 		"br $gp, 0f\n"               /* setup $gp, so that 'lda' works                */
151*b58afc8dSThomas Weißschuh 		"0: ldgp $gp, 0($gp)\n"
152*b58afc8dSThomas Weißschuh 		"lda $27, _start_c\n"        /* setup current function address for _start_c   */
153*b58afc8dSThomas Weißschuh 		"mov $sp, $16\n"             /* save argc pointer to $16, as arg1 of _start_c */
154*b58afc8dSThomas Weißschuh 		"br  _start_c\n"             /* transfer to c runtime                         */
155*b58afc8dSThomas Weißschuh 	);
156*b58afc8dSThomas Weißschuh 	__nolibc_entrypoint_epilogue();
157*b58afc8dSThomas Weißschuh }
158*b58afc8dSThomas Weißschuh 
159*b58afc8dSThomas Weißschuh #endif /* _NOLIBC_ARCH_ALPHA_H */
160