From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by sourceware.org (Postfix) with ESMTP id 5F7433857C65 for ; Wed, 16 Dec 2020 23:31:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5F7433857C65 Received: from mail-pg1-f198.google.com (mail-pg1-f198.google.com [209.85.215.198]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-358-Im0nX2p0MvizkHYGIqxsww-1; Wed, 16 Dec 2020 18:31:52 -0500 X-MC-Unique: Im0nX2p0MvizkHYGIqxsww-1 Received: by mail-pg1-f198.google.com with SMTP id 21so3360489pgq.18 for ; Wed, 16 Dec 2020 15:31:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=T0UP2LmztF6t64RcMq0RwTeUD1wxCBZdJtRBSjbVjEg=; b=bFREsZK4ZxfzAdmsckWwpSc5zcU2fpAfA08SpwHjWlxsErOZmacsIqnXXhYR4ZWGua u1TXZ7z87E97xvsHFoPvBYbLEzuWY2FVgBY0GEHTft2Ny5HvZSy/qMwk/jGVX4VYI/qx 9sCiNBjroNIaCXlHi3P8Hr5E6T7gclUi8BquOwyWC8CQveu6YMGpRRDWWf6x/nqR53XU AWApIl6zTfhLSd2aiT4V6yFwnJpcgW9CwDK9nuPIJzAMAP8kE3fELiVJy+Y+Aj39gxUa QiLNZUduCh+DNlCW7kQXBdF/z5KUC9PW5shNBWFy6NdCIxiyc38wnRnNG3tvz+dcpO++ 2P0A== X-Gm-Message-State: AOAM530WudlCBLzXlEzAyp/wsp/qiSvUSrZ1qO8aBtT4UMgt4O6Ur/hT /MVj5Qoaf0bN8F9otk+fU2vIs1xVudnu/21wWhQeVy9Mv9o6pzso9IN/CacelZkGAx4j9YA/pB5 AnM9kHn7dU9sKZe25cgAYyxdRoV3I/aA= X-Received: by 2002:a62:1615:0:b029:19d:c9f1:f450 with SMTP id 21-20020a6216150000b029019dc9f1f450mr34061060pfw.11.1608161510822; Wed, 16 Dec 2020 15:31:50 -0800 (PST) X-Google-Smtp-Source: ABdhPJzpgywrfX8tbtveo3uPOCeWDyrZQlBSzrJji5TBjaZNtOIQiWH6xsmsHapoMPIPhL7TH0wq3FakuQeP9PEZ1YI= X-Received: by 2002:a62:1615:0:b029:19d:c9f1:f450 with SMTP id 21-20020a6216150000b029019dc9f1f450mr34061046pfw.11.1608161510438; Wed, 16 Dec 2020 15:31:50 -0800 (PST) MIME-Version: 1.0 References: <694d497b-bc07-a3ba-2643-a7336927e9a7@embecosm.com> <3ef25bfd-65d7-e8a2-cdd6-0b0532b5c4f6@embecosm.com> In-Reply-To: <3ef25bfd-65d7-e8a2-cdd6-0b0532b5c4f6@embecosm.com> From: Jeff Johnston Date: Wed, 16 Dec 2020 18:31:38 -0500 Message-ID: Subject: Re: [PATCH] RISC-V: Add semihosting support To: Craig Blackmore Cc: Newlib X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Newlib mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Dec 2020 23:32:00 -0000 Patch merged to master with your license added to COPYING.LIBGLOSS. -- Jeff J. On Wed, Dec 16, 2020 at 3:33 AM Craig Blackmore < craig.blackmore@embecosm.com> wrote: > Hi Jeff, > On 15/12/2020 22:51, Jeff Johnston wrote: > > Hi Craig, > > Can you confirm that you have permission from your employer (embecosm) to > contribute the code? Other than that, I think we're good to merge before > the snapshot. > > Yes, I have permission from Embecosm to contribute this. > > Thanks, > > Craig > > > Thanks, > > -- Jeff J. > > On Tue, Dec 15, 2020 at 7:00 AM Craig Blackmore < > craig.blackmore@embecosm.com> wrote: > >> Hi Kito, >> >> Thanks for the test and review. >> >> On 09/12/2020 08:21, Kito Cheng wrote: >> >> > Hi Craig: >> > >> > I verified with GCC testsuite on qemu with Keith's semihosting patch, >> > And that's LGTM, only two minor review comment, see below: >> > >> >> +++ b/libgloss/riscv/semihost-sys_exit.c >> >> @@ -0,0 +1,19 @@ >> >> +#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); >> > Could you use SEMIHOST_exit_extended here, so that we could have >> > return value on rv32. >> >> I can use SEMIHOST_exit_extended, but I will also need to add a check for >> the >> SH_EXT_EXIT_EXTENDED feature. Can I follow up with this in a later patch? >> >> >> +/* Return the fdentry for file or NULL if not found. */ >> >> + >> >> +struct fdentry * >> >> +__get_fdentry (int file) >> >> +{ >> >> + if (file<0 || file>RISCV_MAX_OPEN_FILES || fdtable[file].handle == >> -1) >> > Should be >= RISCV_MAX_OPEN_FILES here? >> >> Please see updated patch below which fixes this condition and adds a >> license as >> requested by Jeff Johnston. >> >> Best wishes, >> Craig >> >> --- >> 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 +++++++++++++ >> 21 files changed, 692 insertions(+), 1 deletion(-) >> create mode 100644 libgloss/riscv/semihost-sys_close.c >> create mode 100644 libgloss/riscv/semihost-sys_exit.c >> create mode 100644 libgloss/riscv/semihost-sys_fdtable.c >> create mode 100644 libgloss/riscv/semihost-sys_fstat.c >> create mode 100644 libgloss/riscv/semihost-sys_ftime.c >> create mode 100644 libgloss/riscv/semihost-sys_isatty.c >> create mode 100644 libgloss/riscv/semihost-sys_link.c >> create mode 100644 libgloss/riscv/semihost-sys_lseek.c >> create mode 100644 libgloss/riscv/semihost-sys_open.c >> create mode 100644 libgloss/riscv/semihost-sys_read.c >> create mode 100644 libgloss/riscv/semihost-sys_sbrk.c >> create mode 100644 libgloss/riscv/semihost-sys_stat.c >> create mode 100644 libgloss/riscv/semihost-sys_stat_common.c >> create mode 100644 libgloss/riscv/semihost-sys_unlink.c >> create mode 100644 libgloss/riscv/semihost-sys_write.c >> create mode 100644 libgloss/riscv/semihost.specs >> create mode 100644 libgloss/riscv/semihost_fdtable.h >> create mode 100644 libgloss/riscv/semihost_stat.h >> create mode 100644 libgloss/riscv/semihost_syscall.h >> >> 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> + fdtable[i].handle = -1; >> + >> + /* Set up std streams. */ >> + /* stdin. */ >> + handle = _open (":tt", O_RDONLY); >> + fdtable[STDIN_FILENO].handle = handle; >> + fdtable[STDIN_FILENO].pos = 0; >> + >> + /* stdout. */ >> + handle = _open (":tt", O_WRONLY|O_CREAT|O_TRUNC); >> + fdtable[STDOUT_FILENO].handle = handle; >> + fdtable[STDOUT_FILENO].pos = 0; >> + >> + /* stderr. */ >> + handle = _open (":tt", O_WRONLY|O_CREAT|O_APPEND); >> + fdtable[STDERR_FILENO].handle = handle; >> + fdtable[STDERR_FILENO].pos = 0; >> +} >> + >> +/* Add entry to fdtable. */ >> + >> +int >> +__add_fdentry (int handle) >> +{ >> + for (int i=0; i> + if (fdtable[i].handle == -1) >> + { >> + fdtable[i].handle = handle; >> + fdtable[i].pos = 0; >> + return i; >> + } >> + /* Too many open files. */ >> + errno = ENFILE; >> + return -1; >> +} >> + >> +/* Return the fdentry for file or NULL if not found. */ >> + >> +struct fdentry * >> +__get_fdentry (int file) >> +{ >> + if (file<0 || file>=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 >> -- >> 2.17.1 >> >> >>