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