From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2134) id AB9703857C7F; Wed, 16 Dec 2020 21:41:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AB9703857C7F Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Jeff Johnston To: cygwin-cvs@sourceware.org, newlib-cvs@sourceware.org Subject: [newlib-cygwin] RISC-V: Add semihosting support X-Act-Checkin: newlib-cygwin X-Git-Author: Craig Blackmore X-Git-Refname: refs/heads/master X-Git-Oldrev: d634f26653d4a673fed92d882107f165503e2e60 X-Git-Newrev: 865cd30dcc2f00c81c8b3624a9f3464138cd24a5 Message-Id: <20201216214102.AB9703857C7F@sourceware.org> Date: Wed, 16 Dec 2020 21:41:02 +0000 (GMT) X-BeenThere: newlib-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Newlib GIT logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Dec 2020 21:41:02 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=865cd30dcc2f00c81c8b3624a9f3464138cd24a5 commit 865cd30dcc2f00c81c8b3624a9f3464138cd24a5 Author: Craig Blackmore Date: Tue Dec 15 12:00:27 2020 +0000 RISC-V: Add semihosting support Diff: --- COPYING.LIBGLOSS | 5 ++ libgloss/riscv/Makefile.in | 66 +++++++++++++++++++++++- libgloss/riscv/machine/syscall.h | 25 +++++++++ libgloss/riscv/semihost-sys_close.c | 28 ++++++++++ libgloss/riscv/semihost-sys_exit.c | 23 +++++++++ libgloss/riscv/semihost-sys_fdtable.c | 85 +++++++++++++++++++++++++++++++ libgloss/riscv/semihost-sys_fstat.c | 19 +++++++ libgloss/riscv/semihost-sys_ftime.c | 16 ++++++ libgloss/riscv/semihost-sys_isatty.c | 21 ++++++++ libgloss/riscv/semihost-sys_link.c | 9 ++++ libgloss/riscv/semihost-sys_lseek.c | 70 +++++++++++++++++++++++++ libgloss/riscv/semihost-sys_open.c | 62 ++++++++++++++++++++++ libgloss/riscv/semihost-sys_read.c | 32 ++++++++++++ libgloss/riscv/semihost-sys_sbrk.c | 26 ++++++++++ libgloss/riscv/semihost-sys_stat.c | 36 +++++++++++++ libgloss/riscv/semihost-sys_stat_common.c | 36 +++++++++++++ libgloss/riscv/semihost-sys_unlink.c | 15 ++++++ libgloss/riscv/semihost-sys_write.c | 32 ++++++++++++ libgloss/riscv/semihost.specs | 10 ++++ libgloss/riscv/semihost_fdtable.h | 21 ++++++++ libgloss/riscv/semihost_stat.h | 14 +++++ libgloss/riscv/semihost_syscall.h | 47 +++++++++++++++++ 22 files changed, 697 insertions(+), 1 deletion(-) diff --git a/COPYING.LIBGLOSS b/COPYING.LIBGLOSS index 2c64ed2b2..7ae0cd9a4 100644 --- a/COPYING.LIBGLOSS +++ b/COPYING.LIBGLOSS @@ -478,3 +478,8 @@ including the implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. A copy of this license is available at http://www.opensource.org/licenses. +(24) - RISC-V Semihosting (riscv-* targets) + +Copyright (C) 2020 Embecosm Limited +SPDX-License-Identifier: BSD-2-Clause + diff --git a/libgloss/riscv/Makefile.in b/libgloss/riscv/Makefile.in index 579dd9554..185b6e6d2 100644 --- a/libgloss/riscv/Makefile.in +++ b/libgloss/riscv/Makefile.in @@ -40,8 +40,38 @@ gloss_srcs = \ sys_wait.c \ sys_write.c +# libsemihost reuses some of the libgloss minimal implementations + +semihost_srcs = \ + nanosleep.c \ + sys_chdir.c \ + sys_chmod.c \ + sys_chown.c \ + sys_execve.c \ + sys_fork.c \ + sys_getcwd.c \ + sys_getpid.c \ + sys_kill.c \ + sys_utime.c \ + sys_wait.c \ + semihost-sys_close.c \ + semihost-sys_exit.c \ + semihost-sys_fdtable.c \ + semihost-sys_fstat.c \ + semihost-sys_ftime.c \ + semihost-sys_isatty.c \ + semihost-sys_link.c \ + semihost-sys_lseek.c \ + semihost-sys_open.c \ + semihost-sys_read.c \ + semihost-sys_sbrk.c \ + semihost-sys_stat.c \ + semihost-sys_stat_common.c \ + semihost-sys_unlink.c \ + semihost-sys_write.c + gloss_specs = \ - nano.specs sim.specs + nano.specs sim.specs semihost.specs # Extra files @@ -134,6 +164,17 @@ sim_objs += $(sim_c_objs) deps += $(sim_c_deps) junk += $(sim_c_deps) $(sim_c_objs) +semihost_c_srcs = $(filter %.c, $(semihost_srcs)) +semihost_c_objs = $(patsubst %.c, semihost-%.o, $(notdir $(semihost_c_srcs))) +semihost_c_deps = $(patsubst %.c, semihost-%.d, $(notdir $(semihost_c_srcs))) + +$(semihost_c_objs): semihost-%.o : %.c + $(COMPILE) -c -o $@ $< + +semihost_objs += $(semihost_c_objs) +deps += $(semihost_c_deps) +junk += $(semihost_c_deps) $(semihost_c_objs) + #------------------------------------------------------------------------- # Build Object Files from Assembly Source #------------------------------------------------------------------------- @@ -159,6 +200,16 @@ sim_objs += $(sim_asm_objs) deps += $(sim_asm_deps) junk += $(sim_asm_deps) $(sim_asm_objs) +semihost_asm_objs = $(patsubst %.S, semihost-%.o, $(notdir $(gloss_asm_srcs))) +semihost_asm_deps = $(patsubst %.S, semihost-%.d, $(notdir $(gloss_asm_srcs))) + +$(semihost_asm_objs) : semihost-%.o : %.S + $(COMPILE) -c -DUSING_SEMIHOST_SPECS -o $@ $< + +semihost_objs += $(semihost_asm_objs) +deps += $(semihost_asm_deps) +junk += $(semihost_asm_deps) $(semihost_asm_objs) + #------------------------------------------------------------------------- # Build libgloss.a #------------------------------------------------------------------------- @@ -187,6 +238,19 @@ junk += $(sim_lib) install_libs += $(sim_lib) +#------------------------------------------------------------------------- +# Build libsemihost.a +#------------------------------------------------------------------------- + +semihost_lib = libsemihost.a +$(semihost_lib) : $(semihost_objs) + $(AR) rcv $@ $^ + $(RANLIB) $@ + +junk += $(semihost_lib) + +install_libs += $(semihost_lib) + #------------------------------------------------------------------------- # Build crt0.o #------------------------------------------------------------------------- diff --git a/libgloss/riscv/machine/syscall.h b/libgloss/riscv/machine/syscall.h index 5cd15b848..88b9fdfda 100644 --- a/libgloss/riscv/machine/syscall.h +++ b/libgloss/riscv/machine/syscall.h @@ -54,4 +54,29 @@ #define SYS_time 1062 #define SYS_getmainvars 2011 +/* Semihosting operations. */ +#define SEMIHOST_clock 0x10 +#define SEMIHOST_close 0x02 +#define SEMIHOST_elapsed 0x30 +#define SEMIHOST_errno 0x13 +#define SEMIHOST_exit 0x18 +#define SEMIHOST_exit_extended 0x20 +#define SEMIHOST_flen 0x0C +#define SEMIHOST_get_cmdline 0x15 +#define SEMIHOST_heapinfo 0x16 +#define SEMIHOST_iserror 0x08 +#define SEMIHOST_istty 0x09 +#define SEMIHOST_open 0x01 +#define SEMIHOST_read 0x06 +#define SEMIHOST_readc 0x07 +#define SEMIHOST_remove 0x0E +#define SEMIHOST_rename 0x0F +#define SEMIHOST_seek 0x0A +#define SEMIHOST_system 0x12 +#define SEMIHOST_tickfreq 0x31 +#define SEMIHOST_time 0x11 +#define SEMIHOST_tmpnam 0x0D +#define SEMIHOST_write 0x05 +#define SEMIHOST_writec 0x03 +#define SEMIHOST_write0 0x04 #endif diff --git a/libgloss/riscv/semihost-sys_close.c b/libgloss/riscv/semihost-sys_close.c new file mode 100644 index 000000000..47402340c --- /dev/null +++ b/libgloss/riscv/semihost-sys_close.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +/* Close a file. */ +int +_close (int file) +{ + long res; + struct fdentry *fd =__get_fdentry (file); + long data_block[1]; + + if (fd == NULL) + return -1; + + data_block[0] = fd->handle; + res = syscall_errno (SEMIHOST_close, data_block); + + if (res != 0) + return res; + + __remove_fdentry (file); + return 0; +} diff --git a/libgloss/riscv/semihost-sys_exit.c b/libgloss/riscv/semihost-sys_exit.c new file mode 100644 index 000000000..626fb6aeb --- /dev/null +++ b/libgloss/riscv/semihost-sys_exit.c @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" + +#define ADP_Stopped_ApplicationExit 0x20026 + +/* Exit a program without cleaning up files. */ +void +_exit (int exit_status) +{ +#if __riscv_xlen == 32 + syscall_errno (SEMIHOST_exit, (long *) ADP_Stopped_ApplicationExit); +#else + /* The semihosting exit operation only allows 64-bit targets to report the + exit code. */ + long data_block[] = {ADP_Stopped_ApplicationExit, exit_status}; + syscall_errno (SEMIHOST_exit, data_block); +#endif + while (1); +} diff --git a/libgloss/riscv/semihost-sys_fdtable.c b/libgloss/riscv/semihost-sys_fdtable.c new file mode 100644 index 000000000..152c92d15 --- /dev/null +++ b/libgloss/riscv/semihost-sys_fdtable.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include "semihost_fdtable.h" +#include +#include +#include + +#ifndef RISCV_MAX_OPEN_FILES +#define RISCV_MAX_OPEN_FILES 16 +#endif + +extern int errno; +extern int _open (const char *, int, ...); + +/* fdtable keeps track of the position of each file and is used to map stdin, + stdout and stderr to STDIN_FILENO, STDOUT_FILENO and STDERR_FILENO. */ + +static struct fdentry fdtable[RISCV_MAX_OPEN_FILES]; + +/* Initialize fdtable. A handle of -1 denotes an empty entry. */ + +void __attribute__ ((constructor)) +init_semihosting () +{ + int handle; + + for (int i=0; i=RISCV_MAX_OPEN_FILES || fdtable[file].handle == -1) + { + errno = EBADF; + return NULL; + } + return &fdtable[file]; +} + +/* Remove entry from fdtable. */ + +void +__remove_fdentry (int file) +{ + fdtable[file].handle = -1; +} diff --git a/libgloss/riscv/semihost-sys_fstat.c b/libgloss/riscv/semihost-sys_fstat.c new file mode 100644 index 000000000..f57f0c07f --- /dev/null +++ b/libgloss/riscv/semihost-sys_fstat.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_stat.h" + +/* Status of an open file. The sys/stat.h header file required is + distributed in the include subdirectory for this C library. */ + +int +_fstat (int file, struct stat *st) +{ + /* Initialize st as not all fields will be set. */ + memset (st, 0, sizeof (*st)); + + return __stat_common (file, st); +} diff --git a/libgloss/riscv/semihost-sys_ftime.c b/libgloss/riscv/semihost-sys_ftime.c new file mode 100644 index 000000000..aeafc6ca2 --- /dev/null +++ b/libgloss/riscv/semihost-sys_ftime.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_syscall.h" + +/* Get the current time. */ +int +_ftime (struct timeb *tp) +{ + tp->time = syscall_errno (SEMIHOST_time, 0); + tp->millitm = 0; + return 0; +} diff --git a/libgloss/riscv/semihost-sys_isatty.c b/libgloss/riscv/semihost-sys_isatty.c new file mode 100644 index 000000000..02d8e39cb --- /dev/null +++ b/libgloss/riscv/semihost-sys_isatty.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +int +_isatty (int file) +{ + struct fdentry *fd =__get_fdentry (file); + long data_block[1]; + + if (fd == NULL) + return -1; + + data_block[0] = fd->handle; + return syscall_errno (SEMIHOST_istty, data_block); +} diff --git a/libgloss/riscv/semihost-sys_link.c b/libgloss/riscv/semihost-sys_link.c new file mode 100644 index 000000000..717c5c81c --- /dev/null +++ b/libgloss/riscv/semihost-sys_link.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +/* Establish a new name for an existing file. */ +int _link (const char *old_name, const char *new_name) +{ + return -1; +} diff --git a/libgloss/riscv/semihost-sys_lseek.c b/libgloss/riscv/semihost-sys_lseek.c new file mode 100644 index 000000000..68fccf2ff --- /dev/null +++ b/libgloss/riscv/semihost-sys_lseek.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +extern int errno; + +/* Set position in a file. */ +off_t +_lseek (int file, off_t offset, int dir) +{ + long data_block[2]; + long flen; + long res; + struct fdentry *fd; + off_t abs_pos; + + fd =__get_fdentry (file); + if (fd == NULL) + { + errno = EBADF; + return -1; + } + + if (dir == SEEK_CUR && offset == 0) + return fd->pos; + + data_block[0] = fd->handle; + + switch (dir) + { + case SEEK_SET: + abs_pos = offset; + break; + case SEEK_CUR: + abs_pos = fd->pos + offset; + break; + case SEEK_END: + data_block[1] = 0; + flen = syscall_errno (SEMIHOST_flen, data_block); + if (flen == -1) + return -1; + abs_pos = flen + offset; + break; + default: + errno = EINVAL; + return -1; + } + + if (abs_pos < 0) + { + errno = EINVAL; + return -1; + } + + data_block[1] = abs_pos; + res = syscall_errno (SEMIHOST_seek, data_block); + if (res == 0) + { + fd->pos = abs_pos; + return abs_pos; + } + return res; +} diff --git a/libgloss/riscv/semihost-sys_open.c b/libgloss/riscv/semihost-sys_open.c new file mode 100644 index 000000000..22f1d8206 --- /dev/null +++ b/libgloss/riscv/semihost-sys_open.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" +#include +#include +#include + +extern int errno; + +#define SEMIHOST_MODE_R 0 +#define SEMIHOST_MODE_RPLUS 2 +#define SEMIHOST_MODE_W 4 +#define SEMIHOST_MODE_WPLUS 6 +#define SEMIHOST_MODE_A 8 +#define SEMIHOST_MODE_APLUS 10 + +/* Open a file. */ +int +_open (const char *name, int flags, ...) +{ + int fh; + int mode; + long data_block[3]; + + /* Work out mode from flags. */ + if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) + mode = SEMIHOST_MODE_R; + else if ((flags & (O_WRONLY | O_CREAT | O_TRUNC)) + == (O_WRONLY | O_CREAT | O_TRUNC)) + mode = SEMIHOST_MODE_W; + else if ((flags & (O_WRONLY | O_CREAT | O_APPEND)) + == (O_WRONLY | O_CREAT | O_APPEND)) + mode = SEMIHOST_MODE_A; + else if ((flags & (O_RDWR | O_CREAT | O_TRUNC)) + == (O_RDWR | O_CREAT | O_TRUNC)) + mode = SEMIHOST_MODE_WPLUS; + else if ((flags & (O_RDWR | O_CREAT | O_APPEND)) + == (O_RDWR | O_CREAT | O_APPEND)) + mode = SEMIHOST_MODE_APLUS; + else if (flags & O_RDWR) + mode = SEMIHOST_MODE_RPLUS; + else + { + errno = EINVAL; + return -1; + } + + data_block[0] = (long) name; + data_block[1] = mode; + data_block[2] = strlen (name); + fh = syscall_errno (SEMIHOST_open, data_block); + /* Failed to open file. */ + if (fh == -1) + return -1; + + /* Register the file in the fdtable. */ + return __add_fdentry (fh); +} diff --git a/libgloss/riscv/semihost-sys_read.c b/libgloss/riscv/semihost-sys_read.c new file mode 100644 index 000000000..3164eed56 --- /dev/null +++ b/libgloss/riscv/semihost-sys_read.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +/* Read from a file. */ +ssize_t _read (int file, void *ptr, size_t len) +{ + struct fdentry *fd =__get_fdentry (file); + long data_block[3]; + long res; + + if (fd == NULL) + return -1; + + data_block[0] = fd->handle; + data_block[1] = (long) ptr; + data_block[2] = len; + res = syscall_errno (SEMIHOST_read, data_block); + if (res >= 0) + { + ssize_t bytes_read = len - res; + fd->pos += bytes_read; + return bytes_read; + } + return -1; +} diff --git a/libgloss/riscv/semihost-sys_sbrk.c b/libgloss/riscv/semihost-sys_sbrk.c new file mode 100644 index 000000000..cbd035832 --- /dev/null +++ b/libgloss/riscv/semihost-sys_sbrk.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +/* Semihosting requires that sbrk be implemented without a syscall. */ +extern char _end[]; /* _end is set in the linker command file. */ +char *heap_ptr; + +/* + * sbrk -- changes heap size size. Get nbytes more + * RAM. We just increment a pointer in what's + * left of memory on the board. + */ +char * +_sbrk (nbytes) + int nbytes; +{ + char *base; + + if (!heap_ptr) + heap_ptr = (char *)&_end; + base = heap_ptr; + heap_ptr += nbytes; + + return base; +} diff --git a/libgloss/riscv/semihost-sys_stat.c b/libgloss/riscv/semihost-sys_stat.c new file mode 100644 index 000000000..4015801b9 --- /dev/null +++ b/libgloss/riscv/semihost-sys_stat.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include "semihost_stat.h" + +/* Status of a file (by name). */ + +int +_stat (const char *name, struct stat *st) +{ + int file; + int res; + + /* Initialize st as not all fields will be set. */ + memset (st, 0, sizeof (*st)); + + /* Try to open file. */ + file = _open (name, O_RDONLY); + if (file == -1) + /* _open should have already set errno. */ + return -1; + + /* File opened successfully, infer read permission for owner and assume it is + a regular file. */ + st->st_mode |= S_IREAD | S_IFREG; + + /* Fill in more info. */ + res = __stat_common (file, st); + + _close (file); + return res; +} diff --git a/libgloss/riscv/semihost-sys_stat_common.c b/libgloss/riscv/semihost-sys_stat_common.c new file mode 100644 index 000000000..b38eb0863 --- /dev/null +++ b/libgloss/riscv/semihost-sys_stat_common.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include +#include "semihost_fdtable.h" + +/* Used by _fstat and _stat to fill in some common details. */ + +int +__stat_common (int file, struct stat *st) +{ + int flen; + struct fdentry *fd =__get_fdentry (file); + long data_block[1]; + + if (fd == NULL) + return -1; + + data_block[0] = fd->handle; + + /* Assume character device and default block size of 4096. */ + st->st_mode |= S_IFCHR; + st->st_blksize = 4096; + + /* Attempt to get length of file. */ + flen = syscall_errno (SEMIHOST_flen, data_block); + if (flen == -1) + return -1; + + st->st_size = flen; + + return 0; +} diff --git a/libgloss/riscv/semihost-sys_unlink.c b/libgloss/riscv/semihost-sys_unlink.c new file mode 100644 index 000000000..1d2a6a0f9 --- /dev/null +++ b/libgloss/riscv/semihost-sys_unlink.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include "semihost_syscall.h" +#include + +/* Remove a file's directory entry. */ +int +_unlink (const char *name) +{ + long data_block[] = {(long) name, strlen (name)}; + return syscall_errno (SEMIHOST_remove, data_block); +} diff --git a/libgloss/riscv/semihost-sys_write.c b/libgloss/riscv/semihost-sys_write.c new file mode 100644 index 000000000..9aee6d30b --- /dev/null +++ b/libgloss/riscv/semihost-sys_write.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include "semihost_syscall.h" +#include "semihost_fdtable.h" + +/* Write to a file. */ +ssize_t +_write (int file, const void *ptr, size_t len) +{ + struct fdentry *fd =__get_fdentry (file); + long data_block[3]; + long res; + + if (fd == NULL) + return -1; + + data_block[0] = fd->handle; + data_block[1] = (long) ptr; + data_block[2] = len; + res = syscall_errno (SEMIHOST_write, data_block); + if (res >= 0) + { + ssize_t bytes_written = len - res; + fd->pos += bytes_written; + return bytes_written; + } + return -1; +} diff --git a/libgloss/riscv/semihost.specs b/libgloss/riscv/semihost.specs new file mode 100644 index 000000000..1c86c67e4 --- /dev/null +++ b/libgloss/riscv/semihost.specs @@ -0,0 +1,10 @@ +# Spec file for semihosting syscalls. + +%rename lib semihost_lib +%rename link semihost_link + +*lib: +--start-group -lc -lsemihost --end-group + +*link: +%(semihost_link) %:replace-outfile(-lgloss -lsemihost) diff --git a/libgloss/riscv/semihost_fdtable.h b/libgloss/riscv/semihost_fdtable.h new file mode 100644 index 000000000..f596a409a --- /dev/null +++ b/libgloss/riscv/semihost_fdtable.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include + +#ifndef RISCV_SEMIHOST_FDTABLE_H +#define RISCV_SEMIHOST_FDTABLE_H + +extern void __attribute__ ((constructor)) init_semihosting (); +extern int __add_fdentry (int); +extern struct fdentry * __get_fdentry (int); +extern void __remove_fdentry (int); + +struct fdentry +{ + int handle; + off_t pos; +}; + +#endif diff --git a/libgloss/riscv/semihost_stat.h b/libgloss/riscv/semihost_stat.h new file mode 100644 index 000000000..c040fe8e7 --- /dev/null +++ b/libgloss/riscv/semihost_stat.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#include + +#ifndef RISCV_SEMIHOST_STAT_H +#define RISCV_SEMIHOST_STAT_H + +extern int __stat_common (int, struct stat *); +extern int _open (const char *, int, ...); +extern int _close (int); + +#endif diff --git a/libgloss/riscv/semihost_syscall.h b/libgloss/riscv/semihost_syscall.h new file mode 100644 index 000000000..50e731b40 --- /dev/null +++ b/libgloss/riscv/semihost_syscall.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 Embecosm Limited + * SPDX-License-Identifier: BSD-2-Clause + */ +#ifndef _INTERNAL_SYSCALL_H +#define _INTERNAL_SYSCALL_H + +extern int errno; + +static inline long +__semihost_syscall (long id, long *data_block) +{ + register long a0 asm ("a0") = id; + register long a1 asm ("a1") = (long) data_block; + + /* RISC-V semihosting trap sequence. Must be uncompressed and must not + cross page boundary. */ + asm volatile ( + ".balign 16 \n" + ".option push \n" + ".option norvc \n" + "slli zero, zero, 0x1f \n" + "ebreak \n" + "srai zero, zero, 0x7 \n" + ".option pop \n" + : "+r"(a0) : "r"(a1) : "memory"); + + return a0; +} + +static inline long +__syscall_error () +{ + errno = __semihost_syscall (SEMIHOST_errno, 0); + return -1; +} + +static inline long +syscall_errno (long id, long *data_block) +{ + long res = __semihost_syscall (id, data_block); + if (res < 0) + return __syscall_error (); + return res; +} + +#endif