Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/include/nolibc/arch-riscv.h
26292 views
1
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2
/*
3
* RISCV (32 and 64) specific definitions for NOLIBC
4
* Copyright (C) 2017-2022 Willy Tarreau <[email protected]>
5
*/
6
7
#ifndef _NOLIBC_ARCH_RISCV_H
8
#define _NOLIBC_ARCH_RISCV_H
9
10
#include "compiler.h"
11
#include "crt.h"
12
13
/* Syscalls for RISCV :
14
* - stack is 16-byte aligned
15
* - syscall number is passed in a7
16
* - arguments are in a0, a1, a2, a3, a4, a5
17
* - the system call is performed by calling ecall
18
* - syscall return comes in a0
19
* - the arguments are cast to long and assigned into the target
20
* registers which are then simply passed as registers to the asm code,
21
* so that we don't have to experience issues with register constraints.
22
*/
23
24
#define my_syscall0(num) \
25
({ \
26
register long _num __asm__ ("a7") = (num); \
27
register long _arg1 __asm__ ("a0"); \
28
\
29
__asm__ volatile ( \
30
"ecall\n\t" \
31
: "=r"(_arg1) \
32
: "r"(_num) \
33
: "memory", "cc" \
34
); \
35
_arg1; \
36
})
37
38
#define my_syscall1(num, arg1) \
39
({ \
40
register long _num __asm__ ("a7") = (num); \
41
register long _arg1 __asm__ ("a0") = (long)(arg1); \
42
\
43
__asm__ volatile ( \
44
"ecall\n" \
45
: "+r"(_arg1) \
46
: "r"(_num) \
47
: "memory", "cc" \
48
); \
49
_arg1; \
50
})
51
52
#define my_syscall2(num, arg1, arg2) \
53
({ \
54
register long _num __asm__ ("a7") = (num); \
55
register long _arg1 __asm__ ("a0") = (long)(arg1); \
56
register long _arg2 __asm__ ("a1") = (long)(arg2); \
57
\
58
__asm__ volatile ( \
59
"ecall\n" \
60
: "+r"(_arg1) \
61
: "r"(_arg2), \
62
"r"(_num) \
63
: "memory", "cc" \
64
); \
65
_arg1; \
66
})
67
68
#define my_syscall3(num, arg1, arg2, arg3) \
69
({ \
70
register long _num __asm__ ("a7") = (num); \
71
register long _arg1 __asm__ ("a0") = (long)(arg1); \
72
register long _arg2 __asm__ ("a1") = (long)(arg2); \
73
register long _arg3 __asm__ ("a2") = (long)(arg3); \
74
\
75
__asm__ volatile ( \
76
"ecall\n\t" \
77
: "+r"(_arg1) \
78
: "r"(_arg2), "r"(_arg3), \
79
"r"(_num) \
80
: "memory", "cc" \
81
); \
82
_arg1; \
83
})
84
85
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
86
({ \
87
register long _num __asm__ ("a7") = (num); \
88
register long _arg1 __asm__ ("a0") = (long)(arg1); \
89
register long _arg2 __asm__ ("a1") = (long)(arg2); \
90
register long _arg3 __asm__ ("a2") = (long)(arg3); \
91
register long _arg4 __asm__ ("a3") = (long)(arg4); \
92
\
93
__asm__ volatile ( \
94
"ecall\n" \
95
: "+r"(_arg1) \
96
: "r"(_arg2), "r"(_arg3), "r"(_arg4), \
97
"r"(_num) \
98
: "memory", "cc" \
99
); \
100
_arg1; \
101
})
102
103
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
104
({ \
105
register long _num __asm__ ("a7") = (num); \
106
register long _arg1 __asm__ ("a0") = (long)(arg1); \
107
register long _arg2 __asm__ ("a1") = (long)(arg2); \
108
register long _arg3 __asm__ ("a2") = (long)(arg3); \
109
register long _arg4 __asm__ ("a3") = (long)(arg4); \
110
register long _arg5 __asm__ ("a4") = (long)(arg5); \
111
\
112
__asm__ volatile ( \
113
"ecall\n" \
114
: "+r"(_arg1) \
115
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
116
"r"(_num) \
117
: "memory", "cc" \
118
); \
119
_arg1; \
120
})
121
122
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
123
({ \
124
register long _num __asm__ ("a7") = (num); \
125
register long _arg1 __asm__ ("a0") = (long)(arg1); \
126
register long _arg2 __asm__ ("a1") = (long)(arg2); \
127
register long _arg3 __asm__ ("a2") = (long)(arg3); \
128
register long _arg4 __asm__ ("a3") = (long)(arg4); \
129
register long _arg5 __asm__ ("a4") = (long)(arg5); \
130
register long _arg6 __asm__ ("a5") = (long)(arg6); \
131
\
132
__asm__ volatile ( \
133
"ecall\n" \
134
: "+r"(_arg1) \
135
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
136
"r"(_num) \
137
: "memory", "cc" \
138
); \
139
_arg1; \
140
})
141
142
/* startup code */
143
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
144
{
145
__asm__ volatile (
146
".option push\n"
147
".option norelax\n"
148
"lla gp, __global_pointer$\n"
149
".option pop\n"
150
"mv a0, sp\n" /* save stack pointer to a0, as arg1 of _start_c */
151
"call _start_c\n" /* transfer to c runtime */
152
);
153
__nolibc_entrypoint_epilogue();
154
}
155
156
#endif /* _NOLIBC_ARCH_RISCV_H */
157
158