xref: /linux/tools/include/nolibc/arch-sh.h (revision b1c21075d30c40762750be0cded9822791df422b)
1*02217ad4SThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2*02217ad4SThomas Weißschuh /*
3*02217ad4SThomas Weißschuh  * SuperH specific definitions for NOLIBC
4*02217ad4SThomas Weißschuh  * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
5*02217ad4SThomas Weißschuh  */
6*02217ad4SThomas Weißschuh 
7*02217ad4SThomas Weißschuh #ifndef _NOLIBC_ARCH_SH_H
8*02217ad4SThomas Weißschuh #define _NOLIBC_ARCH_SH_H
9*02217ad4SThomas Weißschuh 
10*02217ad4SThomas Weißschuh #include "compiler.h"
11*02217ad4SThomas Weißschuh #include "crt.h"
12*02217ad4SThomas Weißschuh 
13*02217ad4SThomas Weißschuh /*
14*02217ad4SThomas Weißschuh  * Syscalls for SuperH:
15*02217ad4SThomas Weißschuh  *   - registers are 32bit wide
16*02217ad4SThomas Weißschuh  *   - syscall number is passed in r3
17*02217ad4SThomas Weißschuh  *   - arguments are in r4, r5, r6, r7, r0, r1, r2
18*02217ad4SThomas Weißschuh  *   - the system call is performed by calling trapa #31
19*02217ad4SThomas Weißschuh  *   - syscall return value is in r0
20*02217ad4SThomas Weißschuh  */
21*02217ad4SThomas Weißschuh 
22*02217ad4SThomas Weißschuh #define my_syscall0(num)                                                      \
23*02217ad4SThomas Weißschuh ({                                                                            \
24*02217ad4SThomas Weißschuh 	register long _num __asm__ ("r3") = (num);                            \
25*02217ad4SThomas Weißschuh 	register long _ret __asm__ ("r0");                                    \
26*02217ad4SThomas Weißschuh 									      \
27*02217ad4SThomas Weißschuh 	__asm__ volatile (                                                    \
28*02217ad4SThomas Weißschuh 		"trapa #31"                                                   \
29*02217ad4SThomas Weißschuh 		: "=r"(_ret)                                                  \
30*02217ad4SThomas Weißschuh 		: "r"(_num)                                                   \
31*02217ad4SThomas Weißschuh 		: "memory", "cc"                                              \
32*02217ad4SThomas Weißschuh 	);                                                                    \
33*02217ad4SThomas Weißschuh 	_ret;                                                                 \
34*02217ad4SThomas Weißschuh })
35*02217ad4SThomas Weißschuh 
36*02217ad4SThomas Weißschuh #define my_syscall1(num, arg1)                                                \
37*02217ad4SThomas Weißschuh ({                                                                            \
38*02217ad4SThomas Weißschuh 	register long _num __asm__ ("r3") = (num);                            \
39*02217ad4SThomas Weißschuh 	register long _ret __asm__ ("r0");                                    \
40*02217ad4SThomas Weißschuh 	register long _arg1 __asm__ ("r4") = (long)(arg1);                    \
41*02217ad4SThomas Weißschuh 									      \
42*02217ad4SThomas Weißschuh 	__asm__ volatile (                                                    \
43*02217ad4SThomas Weißschuh 		"trapa #31"                                                   \
44*02217ad4SThomas Weißschuh 		: "=r"(_ret)                                                  \
45*02217ad4SThomas Weißschuh 		: "r"(_num), "r"(_arg1)                                       \
46*02217ad4SThomas Weißschuh 		: "memory", "cc"                                              \
47*02217ad4SThomas Weißschuh 	);                                                                    \
48*02217ad4SThomas Weißschuh 	_ret;                                                                 \
49*02217ad4SThomas Weißschuh })
50*02217ad4SThomas Weißschuh 
51*02217ad4SThomas Weißschuh #define my_syscall2(num, arg1, arg2)                                          \
52*02217ad4SThomas Weißschuh ({                                                                            \
53*02217ad4SThomas Weißschuh 	register long _num __asm__ ("r3") = (num);                            \
54*02217ad4SThomas Weißschuh 	register long _ret __asm__ ("r0");                                    \
55*02217ad4SThomas Weißschuh 	register long _arg1 __asm__ ("r4") = (long)(arg1);                    \
56*02217ad4SThomas Weißschuh 	register long _arg2 __asm__ ("r5") = (long)(arg2);                    \
57*02217ad4SThomas Weißschuh 									      \
58*02217ad4SThomas Weißschuh 	__asm__ volatile (                                                    \
59*02217ad4SThomas Weißschuh 		"trapa #31"                                                   \
60*02217ad4SThomas Weißschuh 		: "=r"(_ret)                                                  \
61*02217ad4SThomas Weißschuh 		: "r"(_num), "r"(_arg1), "r"(_arg2)                           \
62*02217ad4SThomas Weißschuh 		: "memory", "cc"                                              \
63*02217ad4SThomas Weißschuh 	);                                                                    \
64*02217ad4SThomas Weißschuh 	_ret;                                                                 \
65*02217ad4SThomas Weißschuh })
66*02217ad4SThomas Weißschuh 
67*02217ad4SThomas Weißschuh #define my_syscall3(num, arg1, arg2, arg3)                                    \
68*02217ad4SThomas Weißschuh ({                                                                            \
69*02217ad4SThomas Weißschuh 	register long _num __asm__ ("r3") = (num);                            \
70*02217ad4SThomas Weißschuh 	register long _ret __asm__ ("r0");                                    \
71*02217ad4SThomas Weißschuh 	register long _arg1 __asm__ ("r4") = (long)(arg1);                    \
72*02217ad4SThomas Weißschuh 	register long _arg2 __asm__ ("r5") = (long)(arg2);                    \
73*02217ad4SThomas Weißschuh 	register long _arg3 __asm__ ("r6") = (long)(arg3);                    \
74*02217ad4SThomas Weißschuh 									      \
75*02217ad4SThomas Weißschuh 	__asm__ volatile (                                                    \
76*02217ad4SThomas Weißschuh 		"trapa #31"                                                   \
77*02217ad4SThomas Weißschuh 		: "=r"(_ret)                                                  \
78*02217ad4SThomas Weißschuh 		: "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3)               \
79*02217ad4SThomas Weißschuh 		: "memory", "cc"                                              \
80*02217ad4SThomas Weißschuh 	);                                                                    \
81*02217ad4SThomas Weißschuh 	_ret;                                                                 \
82*02217ad4SThomas Weißschuh })
83*02217ad4SThomas Weißschuh 
84*02217ad4SThomas Weißschuh #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
85*02217ad4SThomas Weißschuh ({                                                                            \
86*02217ad4SThomas Weißschuh 	register long _num __asm__ ("r3") = (num);                            \
87*02217ad4SThomas Weißschuh 	register long _ret __asm__ ("r0");                                    \
88*02217ad4SThomas Weißschuh 	register long _arg1 __asm__ ("r4") = (long)(arg1);                    \
89*02217ad4SThomas Weißschuh 	register long _arg2 __asm__ ("r5") = (long)(arg2);                    \
90*02217ad4SThomas Weißschuh 	register long _arg3 __asm__ ("r6") = (long)(arg3);                    \
91*02217ad4SThomas Weißschuh 	register long _arg4 __asm__ ("r7") = (long)(arg4);                    \
92*02217ad4SThomas Weißschuh 									      \
93*02217ad4SThomas Weißschuh 	__asm__ volatile (                                                    \
94*02217ad4SThomas Weißschuh 		"trapa #31"                                                   \
95*02217ad4SThomas Weißschuh 		: "=r"(_ret)                                                  \
96*02217ad4SThomas Weißschuh 		: "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4)   \
97*02217ad4SThomas Weißschuh 		: "memory", "cc"                                              \
98*02217ad4SThomas Weißschuh 	);                                                                    \
99*02217ad4SThomas Weißschuh 	_ret;                                                                 \
100*02217ad4SThomas Weißschuh })
101*02217ad4SThomas Weißschuh 
102*02217ad4SThomas Weißschuh #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
103*02217ad4SThomas Weißschuh ({                                                                            \
104*02217ad4SThomas Weißschuh 	register long _num __asm__ ("r3") = (num);                            \
105*02217ad4SThomas Weißschuh 	register long _ret __asm__ ("r0");                                    \
106*02217ad4SThomas Weißschuh 	register long _arg1 __asm__ ("r4") = (long)(arg1);                    \
107*02217ad4SThomas Weißschuh 	register long _arg2 __asm__ ("r5") = (long)(arg2);                    \
108*02217ad4SThomas Weißschuh 	register long _arg3 __asm__ ("r6") = (long)(arg3);                    \
109*02217ad4SThomas Weißschuh 	register long _arg4 __asm__ ("r7") = (long)(arg4);                    \
110*02217ad4SThomas Weißschuh 	register long _arg5 __asm__ ("r0") = (long)(arg5);                    \
111*02217ad4SThomas Weißschuh 									      \
112*02217ad4SThomas Weißschuh 	__asm__ volatile (                                                    \
113*02217ad4SThomas Weißschuh 		"trapa #31"                                                   \
114*02217ad4SThomas Weißschuh 		: "=r"(_ret)                                                  \
115*02217ad4SThomas Weißschuh 		: "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),  \
116*02217ad4SThomas Weißschuh 		  "r"(_arg5)                                                  \
117*02217ad4SThomas Weißschuh 		: "memory", "cc"                                              \
118*02217ad4SThomas Weißschuh 	);                                                                    \
119*02217ad4SThomas Weißschuh 	_ret;                                                                 \
120*02217ad4SThomas Weißschuh })
121*02217ad4SThomas Weißschuh 
122*02217ad4SThomas Weißschuh #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
123*02217ad4SThomas Weißschuh ({                                                                            \
124*02217ad4SThomas Weißschuh 	register long _num __asm__ ("r3") = (num);                            \
125*02217ad4SThomas Weißschuh 	register long _ret __asm__ ("r0");                                    \
126*02217ad4SThomas Weißschuh 	register long _arg1 __asm__ ("r4") = (long)(arg1);                    \
127*02217ad4SThomas Weißschuh 	register long _arg2 __asm__ ("r5") = (long)(arg2);                    \
128*02217ad4SThomas Weißschuh 	register long _arg3 __asm__ ("r6") = (long)(arg3);                    \
129*02217ad4SThomas Weißschuh 	register long _arg4 __asm__ ("r7") = (long)(arg4);                    \
130*02217ad4SThomas Weißschuh 	register long _arg5 __asm__ ("r0") = (long)(arg5);                    \
131*02217ad4SThomas Weißschuh 	register long _arg6 __asm__ ("r1") = (long)(arg6);                    \
132*02217ad4SThomas Weißschuh 									      \
133*02217ad4SThomas Weißschuh 	__asm__ volatile (                                                    \
134*02217ad4SThomas Weißschuh 		"trapa #31"                                                   \
135*02217ad4SThomas Weißschuh 		: "=r"(_ret)                                                  \
136*02217ad4SThomas Weißschuh 		: "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),  \
137*02217ad4SThomas Weißschuh 		  "r"(_arg5), "r"(_arg6)                                      \
138*02217ad4SThomas Weißschuh 		: "memory", "cc"                                              \
139*02217ad4SThomas Weißschuh 	);                                                                    \
140*02217ad4SThomas Weißschuh 	_ret;                                                                 \
141*02217ad4SThomas Weißschuh })
142*02217ad4SThomas Weißschuh 
143*02217ad4SThomas Weißschuh /* startup code */
144*02217ad4SThomas Weißschuh void _start_wrapper(void);
_start_wrapper(void)145*02217ad4SThomas Weißschuh void __attribute__((weak,noreturn)) __nolibc_entrypoint __no_stack_protector _start_wrapper(void)
146*02217ad4SThomas Weißschuh {
147*02217ad4SThomas Weißschuh 	__asm__ volatile (
148*02217ad4SThomas Weißschuh 		".global _start\n"           /* The C function will have a prologue,         */
149*02217ad4SThomas Weißschuh 		".type _start, @function\n"  /* corrupting "sp"                              */
150*02217ad4SThomas Weißschuh 		".weak _start\n"
151*02217ad4SThomas Weißschuh 		"_start:\n"
152*02217ad4SThomas Weißschuh 
153*02217ad4SThomas Weißschuh 		"mov sp, r4\n"               /* save argc pointer to r4, as arg1 of _start_c */
154*02217ad4SThomas Weißschuh 		"bsr _start_c\n"             /* transfer to c runtime                        */
155*02217ad4SThomas Weißschuh 		"nop\n"                      /* delay slot                                   */
156*02217ad4SThomas Weißschuh 
157*02217ad4SThomas Weißschuh 		".size _start, .-_start\n"
158*02217ad4SThomas Weißschuh 	);
159*02217ad4SThomas Weißschuh 	__nolibc_entrypoint_epilogue();
160*02217ad4SThomas Weißschuh }
161*02217ad4SThomas Weißschuh 
162*02217ad4SThomas Weißschuh #endif /* _NOLIBC_ARCH_SH_H */
163