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