arch-riscv.h 9.7 KB

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