Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
0002 /*
0003  * RISCV (32 and 64) specific definitions for NOLIBC
0004  * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
0005  */
0006 
0007 #ifndef _NOLIBC_ARCH_RISCV_H
0008 #define _NOLIBC_ARCH_RISCV_H
0009 
0010 /* O_* macros for fcntl/open are architecture-specific */
0011 #define O_RDONLY            0
0012 #define O_WRONLY            1
0013 #define O_RDWR              2
0014 #define O_CREAT         0x100
0015 #define O_EXCL          0x200
0016 #define O_NOCTTY        0x400
0017 #define O_TRUNC        0x1000
0018 #define O_APPEND       0x2000
0019 #define O_NONBLOCK     0x4000
0020 #define O_DIRECTORY  0x200000
0021 
0022 struct sys_stat_struct {
0023     unsigned long   st_dev;     /* Device.  */
0024     unsigned long   st_ino;     /* File serial number.  */
0025     unsigned int    st_mode;    /* File mode.  */
0026     unsigned int    st_nlink;   /* Link count.  */
0027     unsigned int    st_uid;     /* User ID of the file's owner.  */
0028     unsigned int    st_gid;     /* Group ID of the file's group. */
0029     unsigned long   st_rdev;    /* Device number, if device.  */
0030     unsigned long   __pad1;
0031     long        st_size;    /* Size of file, in bytes.  */
0032     int     st_blksize; /* Optimal block size for I/O.  */
0033     int     __pad2;
0034     long        st_blocks;  /* Number 512-byte blocks allocated. */
0035     long        st_atime;   /* Time of last access.  */
0036     unsigned long   st_atime_nsec;
0037     long        st_mtime;   /* Time of last modification.  */
0038     unsigned long   st_mtime_nsec;
0039     long        st_ctime;   /* Time of last status change.  */
0040     unsigned long   st_ctime_nsec;
0041     unsigned int    __unused4;
0042     unsigned int    __unused5;
0043 };
0044 
0045 #if   __riscv_xlen == 64
0046 #define PTRLOG "3"
0047 #define SZREG  "8"
0048 #elif __riscv_xlen == 32
0049 #define PTRLOG "2"
0050 #define SZREG  "4"
0051 #endif
0052 
0053 /* Syscalls for RISCV :
0054  *   - stack is 16-byte aligned
0055  *   - syscall number is passed in a7
0056  *   - arguments are in a0, a1, a2, a3, a4, a5
0057  *   - the system call is performed by calling ecall
0058  *   - syscall return comes in a0
0059  *   - the arguments are cast to long and assigned into the target
0060  *     registers which are then simply passed as registers to the asm code,
0061  *     so that we don't have to experience issues with register constraints.
0062  *
0063  * On riscv, select() is not implemented so we have to use pselect6().
0064  */
0065 #define __ARCH_WANT_SYS_PSELECT6
0066 
0067 #define my_syscall0(num)                                                      \
0068 ({                                                                            \
0069     register long _num  __asm__ ("a7") = (num);                           \
0070     register long _arg1 __asm__ ("a0");                                   \
0071                                           \
0072     __asm__  volatile (                                                   \
0073         "ecall\n\t"                                                   \
0074         : "=r"(_arg1)                                                 \
0075         : "r"(_num)                                                   \
0076         : "memory", "cc"                                              \
0077     );                                                                    \
0078     _arg1;                                                                \
0079 })
0080 
0081 #define my_syscall1(num, arg1)                                                \
0082 ({                                                                            \
0083     register long _num  __asm__ ("a7") = (num);                           \
0084     register long _arg1 __asm__ ("a0") = (long)(arg1);            \
0085                                           \
0086     __asm__  volatile (                                                   \
0087         "ecall\n"                                                     \
0088         : "+r"(_arg1)                                                 \
0089         : "r"(_num)                                                   \
0090         : "memory", "cc"                                              \
0091     );                                                                    \
0092     _arg1;                                                                \
0093 })
0094 
0095 #define my_syscall2(num, arg1, arg2)                                          \
0096 ({                                                                            \
0097     register long _num  __asm__ ("a7") = (num);                           \
0098     register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
0099     register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
0100                                           \
0101     __asm__  volatile (                                                   \
0102         "ecall\n"                                                     \
0103         : "+r"(_arg1)                                                 \
0104         : "r"(_arg2),                                                 \
0105           "r"(_num)                                                   \
0106         : "memory", "cc"                                              \
0107     );                                                                    \
0108     _arg1;                                                                \
0109 })
0110 
0111 #define my_syscall3(num, arg1, arg2, arg3)                                    \
0112 ({                                                                            \
0113     register long _num  __asm__ ("a7") = (num);                           \
0114     register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
0115     register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
0116     register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
0117                                           \
0118     __asm__  volatile (                                                   \
0119         "ecall\n\t"                                                   \
0120         : "+r"(_arg1)                                                 \
0121         : "r"(_arg2), "r"(_arg3),                                     \
0122           "r"(_num)                                                   \
0123         : "memory", "cc"                                              \
0124     );                                                                    \
0125     _arg1;                                                                \
0126 })
0127 
0128 #define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
0129 ({                                                                            \
0130     register long _num  __asm__ ("a7") = (num);                           \
0131     register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
0132     register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
0133     register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
0134     register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
0135                                           \
0136     __asm__  volatile (                                                   \
0137         "ecall\n"                                                     \
0138         : "+r"(_arg1)                                                 \
0139         : "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
0140           "r"(_num)                                                   \
0141         : "memory", "cc"                                              \
0142     );                                                                    \
0143     _arg1;                                                                \
0144 })
0145 
0146 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
0147 ({                                                                            \
0148     register long _num  __asm__ ("a7") = (num);                           \
0149     register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
0150     register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
0151     register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
0152     register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
0153     register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
0154                                           \
0155     __asm__  volatile (                                                   \
0156         "ecall\n"                                                     \
0157         : "+r"(_arg1)                                                 \
0158         : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
0159           "r"(_num)                                                   \
0160         : "memory", "cc"                                              \
0161     );                                                                    \
0162     _arg1;                                                                \
0163 })
0164 
0165 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
0166 ({                                                                            \
0167     register long _num  __asm__ ("a7") = (num);                           \
0168     register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
0169     register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
0170     register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
0171     register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
0172     register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
0173     register long _arg6 __asm__ ("a5") = (long)(arg6);                    \
0174                                           \
0175     __asm__  volatile (                                                   \
0176         "ecall\n"                                                     \
0177         : "+r"(_arg1)                                                 \
0178         : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
0179           "r"(_num)                                                   \
0180         : "memory", "cc"                                              \
0181     );                                                                    \
0182     _arg1;                                                                \
0183 })
0184 
0185 /* startup code */
0186 __asm__ (".section .text\n"
0187     ".weak _start\n"
0188     "_start:\n"
0189     ".option push\n"
0190     ".option norelax\n"
0191     "lla   gp, __global_pointer$\n"
0192     ".option pop\n"
0193     "ld    a0, 0(sp)\n"          // argc (a0) was in the stack
0194     "add   a1, sp, "SZREG"\n"    // argv (a1) = sp
0195     "slli  a2, a0, "PTRLOG"\n"   // envp (a2) = SZREG*argc ...
0196     "add   a2, a2, "SZREG"\n"    //             + SZREG (skip null)
0197     "add   a2,a2,a1\n"           //             + argv
0198     "andi  sp,a1,-16\n"          // sp must be 16-byte aligned
0199     "call  main\n"               // main() returns the status code, we'll exit with it.
0200     "li a7, 93\n"                // NR_exit == 93
0201     "ecall\n"
0202     "");
0203 
0204 #endif // _NOLIBC_ARCH_RISCV_H