Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/include/nolibc/arch-loongarch.h
26289 views
1
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2
/*
3
* LoongArch specific definitions for NOLIBC
4
* Copyright (C) 2023 Loongson Technology Corporation Limited
5
*/
6
7
#ifndef _NOLIBC_ARCH_LOONGARCH_H
8
#define _NOLIBC_ARCH_LOONGARCH_H
9
10
#include "compiler.h"
11
#include "crt.h"
12
13
/* Syscalls for LoongArch :
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 "syscall 0"
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 _NOLIBC_SYSCALL_CLOBBERLIST \
25
"memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
26
27
#define my_syscall0(num) \
28
({ \
29
register long _num __asm__ ("a7") = (num); \
30
register long _arg1 __asm__ ("a0"); \
31
\
32
__asm__ volatile ( \
33
"syscall 0\n" \
34
: "=r"(_arg1) \
35
: "r"(_num) \
36
: _NOLIBC_SYSCALL_CLOBBERLIST \
37
); \
38
_arg1; \
39
})
40
41
#define my_syscall1(num, arg1) \
42
({ \
43
register long _num __asm__ ("a7") = (num); \
44
register long _arg1 __asm__ ("a0") = (long)(arg1); \
45
\
46
__asm__ volatile ( \
47
"syscall 0\n" \
48
: "+r"(_arg1) \
49
: "r"(_num) \
50
: _NOLIBC_SYSCALL_CLOBBERLIST \
51
); \
52
_arg1; \
53
})
54
55
#define my_syscall2(num, arg1, arg2) \
56
({ \
57
register long _num __asm__ ("a7") = (num); \
58
register long _arg1 __asm__ ("a0") = (long)(arg1); \
59
register long _arg2 __asm__ ("a1") = (long)(arg2); \
60
\
61
__asm__ volatile ( \
62
"syscall 0\n" \
63
: "+r"(_arg1) \
64
: "r"(_arg2), \
65
"r"(_num) \
66
: _NOLIBC_SYSCALL_CLOBBERLIST \
67
); \
68
_arg1; \
69
})
70
71
#define my_syscall3(num, arg1, arg2, arg3) \
72
({ \
73
register long _num __asm__ ("a7") = (num); \
74
register long _arg1 __asm__ ("a0") = (long)(arg1); \
75
register long _arg2 __asm__ ("a1") = (long)(arg2); \
76
register long _arg3 __asm__ ("a2") = (long)(arg3); \
77
\
78
__asm__ volatile ( \
79
"syscall 0\n" \
80
: "+r"(_arg1) \
81
: "r"(_arg2), "r"(_arg3), \
82
"r"(_num) \
83
: _NOLIBC_SYSCALL_CLOBBERLIST \
84
); \
85
_arg1; \
86
})
87
88
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
89
({ \
90
register long _num __asm__ ("a7") = (num); \
91
register long _arg1 __asm__ ("a0") = (long)(arg1); \
92
register long _arg2 __asm__ ("a1") = (long)(arg2); \
93
register long _arg3 __asm__ ("a2") = (long)(arg3); \
94
register long _arg4 __asm__ ("a3") = (long)(arg4); \
95
\
96
__asm__ volatile ( \
97
"syscall 0\n" \
98
: "+r"(_arg1) \
99
: "r"(_arg2), "r"(_arg3), "r"(_arg4), \
100
"r"(_num) \
101
: _NOLIBC_SYSCALL_CLOBBERLIST \
102
); \
103
_arg1; \
104
})
105
106
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
107
({ \
108
register long _num __asm__ ("a7") = (num); \
109
register long _arg1 __asm__ ("a0") = (long)(arg1); \
110
register long _arg2 __asm__ ("a1") = (long)(arg2); \
111
register long _arg3 __asm__ ("a2") = (long)(arg3); \
112
register long _arg4 __asm__ ("a3") = (long)(arg4); \
113
register long _arg5 __asm__ ("a4") = (long)(arg5); \
114
\
115
__asm__ volatile ( \
116
"syscall 0\n" \
117
: "+r"(_arg1) \
118
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
119
"r"(_num) \
120
: _NOLIBC_SYSCALL_CLOBBERLIST \
121
); \
122
_arg1; \
123
})
124
125
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
126
({ \
127
register long _num __asm__ ("a7") = (num); \
128
register long _arg1 __asm__ ("a0") = (long)(arg1); \
129
register long _arg2 __asm__ ("a1") = (long)(arg2); \
130
register long _arg3 __asm__ ("a2") = (long)(arg3); \
131
register long _arg4 __asm__ ("a3") = (long)(arg4); \
132
register long _arg5 __asm__ ("a4") = (long)(arg5); \
133
register long _arg6 __asm__ ("a5") = (long)(arg6); \
134
\
135
__asm__ volatile ( \
136
"syscall 0\n" \
137
: "+r"(_arg1) \
138
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
139
"r"(_num) \
140
: _NOLIBC_SYSCALL_CLOBBERLIST \
141
); \
142
_arg1; \
143
})
144
145
/* startup code */
146
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
147
{
148
__asm__ volatile (
149
"move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */
150
"bl _start_c\n" /* transfer to c runtime */
151
);
152
__nolibc_entrypoint_epilogue();
153
}
154
155
#endif /* _NOLIBC_ARCH_LOONGARCH_H */
156
157