GNU Linux-libre 6.1.90-gnu
[releases.git] / tools / include / nolibc / arch-riscv.h
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 <w@1wt.eu>
5  */
6
7 #ifndef _NOLIBC_ARCH_RISCV_H
8 #define _NOLIBC_ARCH_RISCV_H
9
10 /* O_* macros for fcntl/open are architecture-specific */
11 #define O_RDONLY            0
12 #define O_WRONLY            1
13 #define O_RDWR              2
14 #define O_CREAT          0x40
15 #define O_EXCL           0x80
16 #define O_NOCTTY        0x100
17 #define O_TRUNC         0x200
18 #define O_APPEND        0x400
19 #define O_NONBLOCK      0x800
20 #define O_DIRECTORY   0x10000
21
22 struct sys_stat_struct {
23         unsigned long   st_dev;         /* Device.  */
24         unsigned long   st_ino;         /* File serial number.  */
25         unsigned int    st_mode;        /* File mode.  */
26         unsigned int    st_nlink;       /* Link count.  */
27         unsigned int    st_uid;         /* User ID of the file's owner.  */
28         unsigned int    st_gid;         /* Group ID of the file's group. */
29         unsigned long   st_rdev;        /* Device number, if device.  */
30         unsigned long   __pad1;
31         long            st_size;        /* Size of file, in bytes.  */
32         int             st_blksize;     /* Optimal block size for I/O.  */
33         int             __pad2;
34         long            st_blocks;      /* Number 512-byte blocks allocated. */
35         long            st_atime;       /* Time of last access.  */
36         unsigned long   st_atime_nsec;
37         long            st_mtime;       /* Time of last modification.  */
38         unsigned long   st_mtime_nsec;
39         long            st_ctime;       /* Time of last status change.  */
40         unsigned long   st_ctime_nsec;
41         unsigned int    __unused4;
42         unsigned int    __unused5;
43 };
44
45 #if   __riscv_xlen == 64
46 #define PTRLOG "3"
47 #define SZREG  "8"
48 #elif __riscv_xlen == 32
49 #define PTRLOG "2"
50 #define SZREG  "4"
51 #endif
52
53 /* Syscalls for RISCV :
54  *   - stack is 16-byte aligned
55  *   - syscall number is passed in a7
56  *   - arguments are in a0, a1, a2, a3, a4, a5
57  *   - the system call is performed by calling ecall
58  *   - syscall return comes in a0
59  *   - the arguments are cast to long and assigned into the target
60  *     registers which are then simply passed as registers to the asm code,
61  *     so that we don't have to experience issues with register constraints.
62  *
63  * On riscv, select() is not implemented so we have to use pselect6().
64  */
65 #define __ARCH_WANT_SYS_PSELECT6
66
67 #define my_syscall0(num)                                                      \
68 ({                                                                            \
69         register long _num  __asm__ ("a7") = (num);                           \
70         register long _arg1 __asm__ ("a0");                                   \
71                                                                               \
72         __asm__  volatile (                                                   \
73                 "ecall\n\t"                                                   \
74                 : "=r"(_arg1)                                                 \
75                 : "r"(_num)                                                   \
76                 : "memory", "cc"                                              \
77         );                                                                    \
78         _arg1;                                                                \
79 })
80
81 #define my_syscall1(num, arg1)                                                \
82 ({                                                                            \
83         register long _num  __asm__ ("a7") = (num);                           \
84         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
85                                                                               \
86         __asm__  volatile (                                                   \
87                 "ecall\n"                                                     \
88                 : "+r"(_arg1)                                                 \
89                 : "r"(_num)                                                   \
90                 : "memory", "cc"                                              \
91         );                                                                    \
92         _arg1;                                                                \
93 })
94
95 #define my_syscall2(num, arg1, arg2)                                          \
96 ({                                                                            \
97         register long _num  __asm__ ("a7") = (num);                           \
98         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
99         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
100                                                                               \
101         __asm__  volatile (                                                   \
102                 "ecall\n"                                                     \
103                 : "+r"(_arg1)                                                 \
104                 : "r"(_arg2),                                                 \
105                   "r"(_num)                                                   \
106                 : "memory", "cc"                                              \
107         );                                                                    \
108         _arg1;                                                                \
109 })
110
111 #define my_syscall3(num, arg1, arg2, arg3)                                    \
112 ({                                                                            \
113         register long _num  __asm__ ("a7") = (num);                           \
114         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
115         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
116         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
117                                                                               \
118         __asm__  volatile (                                                   \
119                 "ecall\n\t"                                                   \
120                 : "+r"(_arg1)                                                 \
121                 : "r"(_arg2), "r"(_arg3),                                     \
122                   "r"(_num)                                                   \
123                 : "memory", "cc"                                              \
124         );                                                                    \
125         _arg1;                                                                \
126 })
127
128 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
129 ({                                                                            \
130         register long _num  __asm__ ("a7") = (num);                           \
131         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
132         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
133         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
134         register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
135                                                                               \
136         __asm__  volatile (                                                   \
137                 "ecall\n"                                                     \
138                 : "+r"(_arg1)                                                 \
139                 : "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
140                   "r"(_num)                                                   \
141                 : "memory", "cc"                                              \
142         );                                                                    \
143         _arg1;                                                                \
144 })
145
146 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
147 ({                                                                            \
148         register long _num  __asm__ ("a7") = (num);                           \
149         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
150         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
151         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
152         register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
153         register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
154                                                                               \
155         __asm__  volatile (                                                   \
156                 "ecall\n"                                                     \
157                 : "+r"(_arg1)                                                 \
158                 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
159                   "r"(_num)                                                   \
160                 : "memory", "cc"                                              \
161         );                                                                    \
162         _arg1;                                                                \
163 })
164
165 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
166 ({                                                                            \
167         register long _num  __asm__ ("a7") = (num);                           \
168         register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
169         register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
170         register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
171         register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
172         register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
173         register long _arg6 __asm__ ("a5") = (long)(arg6);                    \
174                                                                               \
175         __asm__  volatile (                                                   \
176                 "ecall\n"                                                     \
177                 : "+r"(_arg1)                                                 \
178                 : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
179                   "r"(_num)                                                   \
180                 : "memory", "cc"                                              \
181         );                                                                    \
182         _arg1;                                                                \
183 })
184
185 /* startup code */
186 __asm__ (".section .text\n"
187     ".weak _start\n"
188     "_start:\n"
189     ".option push\n"
190     ".option norelax\n"
191     "lla   gp, __global_pointer$\n"
192     ".option pop\n"
193     "lw    a0, 0(sp)\n"          // argc (a0) was in the stack
194     "add   a1, sp, "SZREG"\n"    // argv (a1) = sp
195     "slli  a2, a0, "PTRLOG"\n"   // envp (a2) = SZREG*argc ...
196     "add   a2, a2, "SZREG"\n"    //             + SZREG (skip null)
197     "add   a2,a2,a1\n"           //             + argv
198     "andi  sp,a1,-16\n"          // sp must be 16-byte aligned
199     "call  main\n"               // main() returns the status code, we'll exit with it.
200     "li a7, 93\n"                // NR_exit == 93
201     "ecall\n"
202     "");
203
204 #endif // _NOLIBC_ARCH_RISCV_H