Re: [PATCH 1/1] Only pass the minimum number of syscall arguments

Kito Cheng <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <CA+yXCZApK06gq7Waa-=KCnWjt9LhFWTYGaxTjr9vRvYfgC4v+w@mail.gmail.com>
Hi Georg:

LGTM, great job, it reduce the code size for libgloss.

Tested rv32gc/rv64gc on qemu.

Thanks :)

On Tue, Feb 11, 2020 at 4:20 AM Georg Sauthoff <[email protected]> wrote:
>
> Previously, __internal_syscall() compiled into asm-code that unconditionally
> sets the syscall argument registers a0 to a5.
>
> For example, the instruction sequence for a exit syscall looked like
> this:
>
>     li    a0, 1   # in ther caller of exit()
>     # ...         # in newlib:
>     li    a1, 0   # unused arguments
>     li    a2, 0
>     li    a3, 0
>     li    a4, 0
>     li    a5, 0
>     li    a7, 93  # exit syscall number
>
> (i.e. the binary contains then 5 superfluous instructions for this
> one argument syscall)
>
> This commit changes the RISC-V syscall code such that only the required
> syscall argument registers are set.
>
> GCC detects that argc is known at compile time and thus evaluates all the
> if-statements where argc is used at compile time (tested with -O2 and -Os).
> ---
>  libgloss/riscv/internal_syscall.h | 41 ++++++++++++++++++++++---------
>  libgloss/riscv/sys_access.c       |  2 +-
>  libgloss/riscv/sys_close.c        |  2 +-
>  libgloss/riscv/sys_exit.c         |  2 +-
>  libgloss/riscv/sys_faccessat.c    |  2 +-
>  libgloss/riscv/sys_fstat.c        |  2 +-
>  libgloss/riscv/sys_fstatat.c      |  2 +-
>  libgloss/riscv/sys_gettimeofday.c |  2 +-
>  libgloss/riscv/sys_link.c         |  2 +-
>  libgloss/riscv/sys_lseek.c        |  2 +-
>  libgloss/riscv/sys_lstat.c        |  2 +-
>  libgloss/riscv/sys_open.c         |  2 +-
>  libgloss/riscv/sys_openat.c       |  2 +-
>  libgloss/riscv/sys_read.c         |  2 +-
>  libgloss/riscv/sys_sbrk.c         |  4 +--
>  libgloss/riscv/sys_stat.c         |  2 +-
>  libgloss/riscv/sys_unlink.c       |  2 +-
>  libgloss/riscv/sys_write.c        |  2 +-
>  18 files changed, 48 insertions(+), 29 deletions(-)
>
> diff --git a/libgloss/riscv/internal_syscall.h b/libgloss/riscv/internal_syscall.h
> index e5d5594..1f1f42f 100644
> --- a/libgloss/riscv/internal_syscall.h
> +++ b/libgloss/riscv/internal_syscall.h
> @@ -22,31 +22,50 @@ __syscall_error(long a0)
>  }
>
>  static inline long
> -__internal_syscall(long n, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5)
> +__internal_syscall(long n, int argc, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5)
>  {
> +#ifdef __riscv_32e
> +  register long syscall_id asm("t0") = n;
> +#else
> +  register long syscall_id asm("a7") = n;
> +#endif
> +
>    register long a0 asm("a0") = _a0;
> +  if (argc < 2) {
> +      asm volatile ("ecall" : "+r"(a0) : "r"(syscall_id));
> +      return a0;
> +  }
>    register long a1 asm("a1") = _a1;
> +  if (argc == 2) {
> +      asm volatile ("ecall" : "+r"(a0) : "r"(a1), "r"(syscall_id));
> +      return a0;
> +  }
>    register long a2 asm("a2") = _a2;
> +  if (argc == 3) {
> +      asm volatile ("ecall" : "+r"(a0) : "r"(a1), "r"(a2), "r"(syscall_id));
> +      return a0;
> +  }
>    register long a3 asm("a3") = _a3;
> +  if (argc == 4) {
> +      asm volatile ("ecall" : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(syscall_id));
> +      return a0;
> +  }
>    register long a4 asm("a4") = _a4;
> +  if (argc == 5) {
> +      asm volatile ("ecall" : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(syscall_id));
> +      return a0;
> +  }
>    register long a5 asm("a5") = _a5;
>
> -#ifdef __riscv_32e
> -  register long syscall_id asm("t0") = n;
> -#else
> -  register long syscall_id asm("a7") = n;
> -#endif
> -
> -  asm volatile ("scall"
> -               : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(syscall_id));
> +  asm volatile ("ecall" : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(syscall_id));
>
>    return a0;
>  }
>
>  static inline long
> -syscall_errno(long n, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5)
> +syscall_errno(long n, int argc, long _a0, long _a1, long _a2, long _a3, long _a4, long _a5)
>  {
> -  long a0 = __internal_syscall (n, _a0, _a1, _a2, _a3, _a4, _a5);
> +  long a0 = __internal_syscall (n, argc, _a0, _a1, _a2, _a3, _a4, _a5);
>
>    if (a0 < 0)
>      return __syscall_error (a0);
> diff --git a/libgloss/riscv/sys_access.c b/libgloss/riscv/sys_access.c
> index ef446d2..45bedb3 100644
> --- a/libgloss/riscv/sys_access.c
> +++ b/libgloss/riscv/sys_access.c
> @@ -5,5 +5,5 @@
>  int
>  _access(const char *file, int mode)
>  {
> -  return syscall_errno (SYS_access, file, mode, 0, 0, 0, 0);
> +  return syscall_errno (SYS_access, 2, file, mode, 0, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_close.c b/libgloss/riscv/sys_close.c
> index 80b10c6..c1691d8 100644
> --- a/libgloss/riscv/sys_close.c
> +++ b/libgloss/riscv/sys_close.c
> @@ -5,5 +5,5 @@
>  int
>  _close(int file)
>  {
> -  return syscall_errno (SYS_close, file, 0, 0, 0, 0, 0);
> +  return syscall_errno (SYS_close, 1, file, 0, 0, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_exit.c b/libgloss/riscv/sys_exit.c
> index 03e1c34..995dd65 100644
> --- a/libgloss/riscv/sys_exit.c
> +++ b/libgloss/riscv/sys_exit.c
> @@ -5,6 +5,6 @@
>  void
>  _exit(int exit_status)
>  {
> -  syscall_errno (SYS_exit, exit_status, 0, 0, 0, 0, 0);
> +  syscall_errno (SYS_exit, 1, exit_status, 0, 0, 0, 0, 0);
>    while (1);
>  }
> diff --git a/libgloss/riscv/sys_faccessat.c b/libgloss/riscv/sys_faccessat.c
> index e966a4a..6418ef4 100644
> --- a/libgloss/riscv/sys_faccessat.c
> +++ b/libgloss/riscv/sys_faccessat.c
> @@ -4,5 +4,5 @@
>  /* Permissions of a file (by name) in a given directory.  */
>  int _faccessat(int dirfd, const char *file, int mode, int flags)
>  {
> -  return syscall_errno (SYS_faccessat, dirfd, file, mode, flags, 0, 0);
> +  return syscall_errno (SYS_faccessat, 4, dirfd, file, mode, flags, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_fstat.c b/libgloss/riscv/sys_fstat.c
> index 13a0bca..d97ba44 100644
> --- a/libgloss/riscv/sys_fstat.c
> +++ b/libgloss/riscv/sys_fstat.c
> @@ -9,7 +9,7 @@ int
>  _fstat(int file, struct stat *st)
>  {
>    struct kernel_stat kst;
> -  int rv = syscall_errno (SYS_fstat, file, &kst, 0, 0, 0, 0);
> +  int rv = syscall_errno (SYS_fstat, 2, file, &kst, 0, 0, 0, 0);
>    _conv_stat (st, &kst);
>    return rv;
>  }
> diff --git a/libgloss/riscv/sys_fstatat.c b/libgloss/riscv/sys_fstatat.c
> index 0e4ea42..bf03355 100644
> --- a/libgloss/riscv/sys_fstatat.c
> +++ b/libgloss/riscv/sys_fstatat.c
> @@ -8,7 +8,7 @@ int
>  _fstatat(int dirfd, const char *file, struct stat *st, int flags)
>  {
>    struct kernel_stat kst;
> -  int rv = syscall_errno (SYS_fstatat, dirfd, file, &kst, flags, 0, 0);
> +  int rv = syscall_errno (SYS_fstatat, 4, dirfd, file, &kst, flags, 0, 0);
>    _conv_stat (st, &kst);
>    return rv;
>  }
> diff --git a/libgloss/riscv/sys_gettimeofday.c b/libgloss/riscv/sys_gettimeofday.c
> index 457dcbc..daa14e4 100644
> --- a/libgloss/riscv/sys_gettimeofday.c
> +++ b/libgloss/riscv/sys_gettimeofday.c
> @@ -6,5 +6,5 @@
>  int
>  _gettimeofday(struct timeval *tp, void *tzp)
>  {
> -  return syscall_errno (SYS_gettimeofday, tp, 0, 0, 0, 0, 0);
> +  return syscall_errno (SYS_gettimeofday, 1, tp, 0, 0, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_link.c b/libgloss/riscv/sys_link.c
> index eaeb22b..83cd1b2 100644
> --- a/libgloss/riscv/sys_link.c
> +++ b/libgloss/riscv/sys_link.c
> @@ -4,5 +4,5 @@
>  /* Establish a new name for an existing file.  */
>  int _link(const char *old_name, const char *new_name)
>  {
> -  return syscall_errno (SYS_link, old_name, new_name, 0, 0, 0, 0);
> +  return syscall_errno (SYS_link, 2, old_name, new_name, 0, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_lseek.c b/libgloss/riscv/sys_lseek.c
> index 7486a3a..8eb8b81 100644
> --- a/libgloss/riscv/sys_lseek.c
> +++ b/libgloss/riscv/sys_lseek.c
> @@ -6,5 +6,5 @@
>  off_t
>  _lseek(int file, off_t ptr, int dir)
>  {
> -  return syscall_errno (SYS_lseek, file, ptr, dir, 0, 0, 0);
> +  return syscall_errno (SYS_lseek, 3, file, ptr, dir, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_lstat.c b/libgloss/riscv/sys_lstat.c
> index 2eeabcc..dd5dc52 100644
> --- a/libgloss/riscv/sys_lstat.c
> +++ b/libgloss/riscv/sys_lstat.c
> @@ -7,7 +7,7 @@
>  int _lstat(const char *file, struct stat *st)
>  {
>    struct kernel_stat kst;
> -  int rv = syscall_errno (SYS_lstat, file, &kst, 0, 0, 0, 0);
> +  int rv = syscall_errno (SYS_lstat, 2, file, &kst, 0, 0, 0, 0);
>    _conv_stat (st, &kst);
>    return rv;
>  }
> diff --git a/libgloss/riscv/sys_open.c b/libgloss/riscv/sys_open.c
> index 4fd5d67..eb1a99b 100644
> --- a/libgloss/riscv/sys_open.c
> +++ b/libgloss/riscv/sys_open.c
> @@ -5,5 +5,5 @@
>  int
>  _open(const char *name, int flags, int mode)
>  {
> -  return syscall_errno (SYS_open, name, flags, mode, 0, 0, 0);
> +  return syscall_errno (SYS_open, 3, name, flags, mode, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_openat.c b/libgloss/riscv/sys_openat.c
> index cf429b7..652ab2e 100644
> --- a/libgloss/riscv/sys_openat.c
> +++ b/libgloss/riscv/sys_openat.c
> @@ -4,5 +4,5 @@
>  /* Open file relative to given directory.  */
>  int _openat(int dirfd, const char *name, int flags, int mode)
>  {
> -  return syscall_errno (SYS_openat, dirfd, name, flags, mode, 0, 0);
> +  return syscall_errno (SYS_openat, 4, dirfd, name, flags, mode, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_read.c b/libgloss/riscv/sys_read.c
> index 7367e26..dd3bc33 100644
> --- a/libgloss/riscv/sys_read.c
> +++ b/libgloss/riscv/sys_read.c
> @@ -5,5 +5,5 @@
>  /* Read from a file.  */
>  ssize_t _read(int file, void *ptr, size_t len)
>  {
> -  return syscall_errno (SYS_read, file, ptr, len, 0, 0, 0);
> +  return syscall_errno (SYS_read, 3, file, ptr, len, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_sbrk.c b/libgloss/riscv/sys_sbrk.c
> index f91c2c5..086509e 100644
> --- a/libgloss/riscv/sys_sbrk.c
> +++ b/libgloss/riscv/sys_sbrk.c
> @@ -41,13 +41,13 @@ _sbrk(ptrdiff_t incr)
>
>    if (heap_end == 0)
>      {
> -      long brk = __internal_syscall (SYS_brk, 0, 0, 0, 0, 0, 0);
> +      long brk = __internal_syscall (SYS_brk, 1, 0, 0, 0, 0, 0, 0);
>        if (brk == -1)
>          return (void *)__syscall_error (-ENOMEM);
>        heap_end = brk;
>      }
>
> -  if (__internal_syscall (SYS_brk, heap_end + incr, 0, 0, 0, 0, 0) != heap_end + incr)
> +  if (__internal_syscall (SYS_brk, 1, heap_end + incr, 0, 0, 0, 0, 0) != heap_end + incr)
>      return (void *)__syscall_error (-ENOMEM);
>
>    heap_end += incr;
> diff --git a/libgloss/riscv/sys_stat.c b/libgloss/riscv/sys_stat.c
> index a193b10..1e03700 100644
> --- a/libgloss/riscv/sys_stat.c
> +++ b/libgloss/riscv/sys_stat.c
> @@ -8,7 +8,7 @@ int
>  _stat(const char *file, struct stat *st)
>  {
>    struct kernel_stat kst;
> -  int rv = syscall_errno (SYS_stat, file, &kst, 0, 0, 0, 0);
> +  int rv = syscall_errno (SYS_stat, 2, file, &kst, 0, 0, 0, 0);
>    _conv_stat (st, &kst);
>    return rv;
>  }
> diff --git a/libgloss/riscv/sys_unlink.c b/libgloss/riscv/sys_unlink.c
> index b55fe1e..1cf6bbe 100644
> --- a/libgloss/riscv/sys_unlink.c
> +++ b/libgloss/riscv/sys_unlink.c
> @@ -5,5 +5,5 @@
>  int
>  _unlink(const char *name)
>  {
> -  return syscall_errno (SYS_unlink, name, 0, 0, 0, 0, 0);
> +  return syscall_errno (SYS_unlink, 1, name, 0, 0, 0, 0, 0);
>  }
> diff --git a/libgloss/riscv/sys_write.c b/libgloss/riscv/sys_write.c
> index b972734..ce2edd3 100644
> --- a/libgloss/riscv/sys_write.c
> +++ b/libgloss/riscv/sys_write.c
> @@ -6,5 +6,5 @@
>  ssize_t
>  _write(int file, const void *ptr, size_t len)
>  {
> -  return syscall_errno (SYS_write, file, ptr, len, 0, 0, 0);
> +  return syscall_errno (SYS_write, 3, file, ptr, len, 0, 0, 0);
>  }
> --
> 2.24.1
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.