xref: /linux/tools/include/nolibc/arch-parisc.h (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
1*d4fe68aeSThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*d4fe68aeSThomas Weißschuh /*
3*d4fe68aeSThomas Weißschuh  * parisc/hppa (32-bit) specific definitions for NOLIBC
4*d4fe68aeSThomas Weißschuh  * Copyright (C) 2026 Thomas Weißschuh <linux@weissschuh.net>
5*d4fe68aeSThomas Weißschuh  */
6*d4fe68aeSThomas Weißschuh 
7*d4fe68aeSThomas Weißschuh #ifndef _NOLIBC_ARCH_PARISC_H
8*d4fe68aeSThomas Weißschuh #define _NOLIBC_ARCH_PARISC_H
9*d4fe68aeSThomas Weißschuh 
10*d4fe68aeSThomas Weißschuh #if defined(__LP64__)
11*d4fe68aeSThomas Weißschuh #error 64-bit not supported
12*d4fe68aeSThomas Weißschuh #endif
13*d4fe68aeSThomas Weißschuh 
14*d4fe68aeSThomas Weißschuh #include "compiler.h"
15*d4fe68aeSThomas Weißschuh #include "crt.h"
16*d4fe68aeSThomas Weißschuh 
17*d4fe68aeSThomas Weißschuh /* Syscalls for parisc :
18*d4fe68aeSThomas Weißschuh  *   - syscall number is passed in r20
19*d4fe68aeSThomas Weißschuh  *   - arguments are in r26 to r21
20*d4fe68aeSThomas Weißschuh  *   - the system call is performed by calling "ble 0x100(%sr2, %r0)",
21*d4fe68aeSThomas Weißschuh  *     the instruction after that is in the delay slot and executed before
22*d4fe68aeSThomas Weißschuh  *     the jump to 0x100 actually happens, use it to load the syscall number
23*d4fe68aeSThomas Weißschuh  *   - syscall return comes in r28
24*d4fe68aeSThomas Weißschuh  *   - the arguments are cast to long and assigned into the target
25*d4fe68aeSThomas Weißschuh  *     registers which are then simply passed as registers to the asm code,
26*d4fe68aeSThomas Weißschuh  *     so that we don't have to experience issues with register constraints.
27*d4fe68aeSThomas Weißschuh  */
28*d4fe68aeSThomas Weißschuh 
29*d4fe68aeSThomas Weißschuh #define _NOLIBC_SYSCALL_CLOBBERLIST \
30*d4fe68aeSThomas Weißschuh 	"memory", "%r1", "%r2", "%r4", "%r20", "%r29", "%r31"
31*d4fe68aeSThomas Weißschuh 
32*d4fe68aeSThomas Weißschuh #define __nolibc_syscall0(num)                                                \
33*d4fe68aeSThomas Weißschuh ({                                                                            \
34*d4fe68aeSThomas Weißschuh 	register long _ret __asm__ ("r28");                                   \
35*d4fe68aeSThomas Weißschuh 									      \
36*d4fe68aeSThomas Weißschuh 	__asm__ volatile (                                                    \
37*d4fe68aeSThomas Weißschuh 		"ble 0x100(%%sr2, %%r0)\n\t"                                  \
38*d4fe68aeSThomas Weißschuh 		"copy %1, %%r20\n\t"                                          \
39*d4fe68aeSThomas Weißschuh 		: "=r"(_ret)                                                  \
40*d4fe68aeSThomas Weißschuh 		: "r"(num)                                                    \
41*d4fe68aeSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST,                                \
42*d4fe68aeSThomas Weißschuh 		  "%r21", "%r22", "%r23", "%r24", "%r25", "%r26"              \
43*d4fe68aeSThomas Weißschuh 	);                                                                    \
44*d4fe68aeSThomas Weißschuh 	_ret;                                                                 \
45*d4fe68aeSThomas Weißschuh })
46*d4fe68aeSThomas Weißschuh 
47*d4fe68aeSThomas Weißschuh #define __nolibc_syscall1(num, arg1)                                          \
48*d4fe68aeSThomas Weißschuh ({                                                                            \
49*d4fe68aeSThomas Weißschuh 	register long _ret __asm__ ("r28");                                   \
50*d4fe68aeSThomas Weißschuh 	register long _arg1 __asm__ ("r26") = (long)(arg1);		      \
51*d4fe68aeSThomas Weißschuh 									      \
52*d4fe68aeSThomas Weißschuh 	__asm__ volatile (                                                    \
53*d4fe68aeSThomas Weißschuh 		"ble 0x100(%%sr2, %%r0)\n\t"                                  \
54*d4fe68aeSThomas Weißschuh 		"copy %2, %%r20\n\t"                                          \
55*d4fe68aeSThomas Weißschuh 		: "=r"(_ret),                                                 \
56*d4fe68aeSThomas Weißschuh 		  "+r"(_arg1)                                                 \
57*d4fe68aeSThomas Weißschuh 		: "r"(num)                                                    \
58*d4fe68aeSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST,                                \
59*d4fe68aeSThomas Weißschuh 		  "%r21", "%r22", "%r23", "%r24", "%r25"                      \
60*d4fe68aeSThomas Weißschuh 	);                                                                    \
61*d4fe68aeSThomas Weißschuh 	_ret;                                                                 \
62*d4fe68aeSThomas Weißschuh })
63*d4fe68aeSThomas Weißschuh 
64*d4fe68aeSThomas Weißschuh #define __nolibc_syscall2(num, arg1, arg2)                                    \
65*d4fe68aeSThomas Weißschuh ({                                                                            \
66*d4fe68aeSThomas Weißschuh 	register long _ret __asm__ ("r28");                                   \
67*d4fe68aeSThomas Weißschuh 	register long _arg1 __asm__ ("r26") = (long)(arg1);		      \
68*d4fe68aeSThomas Weißschuh 	register long _arg2 __asm__ ("r25") = (long)(arg2);		      \
69*d4fe68aeSThomas Weißschuh 									      \
70*d4fe68aeSThomas Weißschuh 	__asm__ volatile (                                                    \
71*d4fe68aeSThomas Weißschuh 		"ble 0x100(%%sr2, %%r0)\n\t"                                  \
72*d4fe68aeSThomas Weißschuh 		"copy %3, %%r20\n\t"                                          \
73*d4fe68aeSThomas Weißschuh 		: "=r"(_ret),                                                 \
74*d4fe68aeSThomas Weißschuh 		  "+r"(_arg1), "+r"(_arg2)                                    \
75*d4fe68aeSThomas Weißschuh 		: "r"(num)                                                    \
76*d4fe68aeSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST,                                \
77*d4fe68aeSThomas Weißschuh 		  "%r21", "%r22", "%r23", "%r24"                              \
78*d4fe68aeSThomas Weißschuh 	);                                                                    \
79*d4fe68aeSThomas Weißschuh 	_ret;                                                                 \
80*d4fe68aeSThomas Weißschuh })
81*d4fe68aeSThomas Weißschuh 
82*d4fe68aeSThomas Weißschuh #define __nolibc_syscall3(num, arg1, arg2, arg3)                              \
83*d4fe68aeSThomas Weißschuh ({                                                                            \
84*d4fe68aeSThomas Weißschuh 	register long _ret __asm__ ("r28");                                   \
85*d4fe68aeSThomas Weißschuh 	register long _arg1 __asm__ ("r26") = (long)(arg1);		      \
86*d4fe68aeSThomas Weißschuh 	register long _arg2 __asm__ ("r25") = (long)(arg2);		      \
87*d4fe68aeSThomas Weißschuh 	register long _arg3 __asm__ ("r24") = (long)(arg3);		      \
88*d4fe68aeSThomas Weißschuh 									      \
89*d4fe68aeSThomas Weißschuh 	__asm__ volatile (                                                    \
90*d4fe68aeSThomas Weißschuh 		"ble 0x100(%%sr2, %%r0)\n\t"                                  \
91*d4fe68aeSThomas Weißschuh 		"copy %4, %%r20\n\t"                                          \
92*d4fe68aeSThomas Weißschuh 		: "=r"(_ret),                                                 \
93*d4fe68aeSThomas Weißschuh 		  "+r"(_arg1), "+r"(_arg2), "+r"(_arg3)                       \
94*d4fe68aeSThomas Weißschuh 		: "r"(num)                                                    \
95*d4fe68aeSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST,                                \
96*d4fe68aeSThomas Weißschuh 		  "%r21", "%r22", "%r23"                                      \
97*d4fe68aeSThomas Weißschuh 	);                                                                    \
98*d4fe68aeSThomas Weißschuh 	_ret;                                                                 \
99*d4fe68aeSThomas Weißschuh })
100*d4fe68aeSThomas Weißschuh 
101*d4fe68aeSThomas Weißschuh #define __nolibc_syscall4(num, arg1, arg2, arg3, arg4)                        \
102*d4fe68aeSThomas Weißschuh ({                                                                            \
103*d4fe68aeSThomas Weißschuh 	register long _ret __asm__ ("r28");                                   \
104*d4fe68aeSThomas Weißschuh 	register long _arg1 __asm__ ("r26") = (long)(arg1);		      \
105*d4fe68aeSThomas Weißschuh 	register long _arg2 __asm__ ("r25") = (long)(arg2);		      \
106*d4fe68aeSThomas Weißschuh 	register long _arg3 __asm__ ("r24") = (long)(arg3);		      \
107*d4fe68aeSThomas Weißschuh 	register long _arg4 __asm__ ("r23") = (long)(arg4);		      \
108*d4fe68aeSThomas Weißschuh 									      \
109*d4fe68aeSThomas Weißschuh 	__asm__ volatile (                                                    \
110*d4fe68aeSThomas Weißschuh 		"ble 0x100(%%sr2, %%r0)\n\t"                                  \
111*d4fe68aeSThomas Weißschuh 		"copy %5, %%r20\n\t"                                          \
112*d4fe68aeSThomas Weißschuh 		: "=r"(_ret),                                                 \
113*d4fe68aeSThomas Weißschuh 		  "+r"(_arg1), "+r"(_arg2), "+r"(_arg3), "+r"(_arg4)          \
114*d4fe68aeSThomas Weißschuh 		: "r"(num)                                                    \
115*d4fe68aeSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST,                                \
116*d4fe68aeSThomas Weißschuh 		  "%r21", "%r22"                                              \
117*d4fe68aeSThomas Weißschuh 	);                                                                    \
118*d4fe68aeSThomas Weißschuh 	_ret;                                                                 \
119*d4fe68aeSThomas Weißschuh })
120*d4fe68aeSThomas Weißschuh 
121*d4fe68aeSThomas Weißschuh #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5)                  \
122*d4fe68aeSThomas Weißschuh ({                                                                            \
123*d4fe68aeSThomas Weißschuh 	register long _ret __asm__ ("r28");                                   \
124*d4fe68aeSThomas Weißschuh 	register long _arg1 __asm__ ("r26") = (long)(arg1);		      \
125*d4fe68aeSThomas Weißschuh 	register long _arg2 __asm__ ("r25") = (long)(arg2);		      \
126*d4fe68aeSThomas Weißschuh 	register long _arg3 __asm__ ("r24") = (long)(arg3);		      \
127*d4fe68aeSThomas Weißschuh 	register long _arg4 __asm__ ("r23") = (long)(arg4);		      \
128*d4fe68aeSThomas Weißschuh 	register long _arg5 __asm__ ("r22") = (long)(arg5);		      \
129*d4fe68aeSThomas Weißschuh 									      \
130*d4fe68aeSThomas Weißschuh 	__asm__ volatile (                                                    \
131*d4fe68aeSThomas Weißschuh 		"ble 0x100(%%sr2, %%r0)\n\t"                                  \
132*d4fe68aeSThomas Weißschuh 		"copy %6, %%r20\n\t"                                          \
133*d4fe68aeSThomas Weißschuh 		: "=r"(_ret),                                                 \
134*d4fe68aeSThomas Weißschuh 		  "+r"(_arg1), "+r"(_arg2), "+r"(_arg3), "+r"(_arg4),         \
135*d4fe68aeSThomas Weißschuh 		  "+r"(_arg5)                                                 \
136*d4fe68aeSThomas Weißschuh 		: "r"(num)                                                    \
137*d4fe68aeSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST,                                \
138*d4fe68aeSThomas Weißschuh 		  "%r21"                                                      \
139*d4fe68aeSThomas Weißschuh 	);                                                                    \
140*d4fe68aeSThomas Weißschuh 	_ret;                                                                 \
141*d4fe68aeSThomas Weißschuh })
142*d4fe68aeSThomas Weißschuh 
143*d4fe68aeSThomas Weißschuh #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)            \
144*d4fe68aeSThomas Weißschuh ({                                                                            \
145*d4fe68aeSThomas Weißschuh 	register long _ret __asm__ ("r28");                                   \
146*d4fe68aeSThomas Weißschuh 	register long _arg1 __asm__ ("r26") = (long)(arg1);		      \
147*d4fe68aeSThomas Weißschuh 	register long _arg2 __asm__ ("r25") = (long)(arg2);		      \
148*d4fe68aeSThomas Weißschuh 	register long _arg3 __asm__ ("r24") = (long)(arg3);		      \
149*d4fe68aeSThomas Weißschuh 	register long _arg4 __asm__ ("r23") = (long)(arg4);		      \
150*d4fe68aeSThomas Weißschuh 	register long _arg5 __asm__ ("r22") = (long)(arg5);		      \
151*d4fe68aeSThomas Weißschuh 	register long _arg6 __asm__ ("r21") = (long)(arg6);		      \
152*d4fe68aeSThomas Weißschuh 									      \
153*d4fe68aeSThomas Weißschuh 	__asm__ volatile (                                                    \
154*d4fe68aeSThomas Weißschuh 		"ble 0x100(%%sr2, %%r0)\n\t"                                  \
155*d4fe68aeSThomas Weißschuh 		"copy %7, %%r20\n\t"                                          \
156*d4fe68aeSThomas Weißschuh 		: "=r"(_ret),                                                 \
157*d4fe68aeSThomas Weißschuh 		  "+r"(_arg1), "+r"(_arg2), "+r"(_arg3), "+r"(_arg4),         \
158*d4fe68aeSThomas Weißschuh 		  "+r"(_arg5), "+r"(_arg6)                                    \
159*d4fe68aeSThomas Weißschuh 		: "r"(num)                                                    \
160*d4fe68aeSThomas Weißschuh 		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
161*d4fe68aeSThomas Weißschuh 	);                                                                    \
162*d4fe68aeSThomas Weißschuh 	_ret;                                                                 \
163*d4fe68aeSThomas Weißschuh })
164*d4fe68aeSThomas Weißschuh 
165*d4fe68aeSThomas Weißschuh #ifndef NOLIBC_NO_RUNTIME
166*d4fe68aeSThomas Weißschuh /* startup code */
167*d4fe68aeSThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_protector _start(void)
168*d4fe68aeSThomas Weißschuh {
169*d4fe68aeSThomas Weißschuh 	__asm__ volatile (
170*d4fe68aeSThomas Weißschuh 		".import $global$\n"           /* Set up the dp register */
171*d4fe68aeSThomas Weißschuh 		"ldil L%$global$, %dp\n"
172*d4fe68aeSThomas Weißschuh 		"ldo R%$global$(%r27), %dp\n"
173*d4fe68aeSThomas Weißschuh 
174*d4fe68aeSThomas Weißschuh 		"b _start_c\n"                 /* Call _start_c, the load below is executed first */
175*d4fe68aeSThomas Weißschuh 
176*d4fe68aeSThomas Weißschuh 		"ldo -4(%r24), %r26\n"         /* The sp register is special on parisc.
177*d4fe68aeSThomas Weißschuh 						* r24 points to argv. Subtract 4 to get &argc.
178*d4fe68aeSThomas Weißschuh 						* Pass that as first argument to _start_c.
179*d4fe68aeSThomas Weißschuh 						*/
180*d4fe68aeSThomas Weißschuh 	);
181*d4fe68aeSThomas Weißschuh 	__nolibc_entrypoint_epilogue();
182*d4fe68aeSThomas Weißschuh }
183*d4fe68aeSThomas Weißschuh #endif /* NOLIBC_NO_RUNTIME */
184*d4fe68aeSThomas Weißschuh 
185*d4fe68aeSThomas Weißschuh #endif /* _NOLIBC_ARCH_PARISC_H */
186