From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by sourceware.org (Postfix) with ESMTPS id B5BE9386F41D for ; Wed, 16 Dec 2020 08:33:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org B5BE9386F41D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=craig.blackmore@embecosm.com Received: by mail-wm1-x335.google.com with SMTP id a6so1514635wmc.2 for ; Wed, 16 Dec 2020 00:33:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=subject:to:cc:references:from:autocrypt:message-id:date:user-agent :mime-version:in-reply-to:content-language; bh=MIjT2zOiuFUaRdznJFtL/eHOkyN0764DTHGprfzwbEQ=; b=eva6atdHZR3oSamTvwrdmGQ0XoEm6KJTVsFZFEFNkjbVG5pJYAE7KPcshO2ZMkk9XN 8pnWyHn2KjsLBWh2JlGnll0LwcmFYM1cZxmA1Oh7rTlRiDB3CXtBKUksFsC4BrXAwrTX NQTqRuYi7YYjnFG1iEuG2xId1WPag9240hytwB/pOkU8OBU47fn1dPTqu4+dNCLkhr5c AETarlD51X6pfbvggiZsJqLtR4Sk911WwKg8Ol3E39mLzKGv7thuqgyKZ3BcqIerIijo vP25Utoir7oIRbLXvl3qqMtK2Cf8dvc4srI96838+w5TkkATaZcLYqlpCoA+0sKu+LHv 6eoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:autocrypt :message-id:date:user-agent:mime-version:in-reply-to :content-language; bh=MIjT2zOiuFUaRdznJFtL/eHOkyN0764DTHGprfzwbEQ=; b=cQh+frgQLsDQeVmY2ryz2Cd+gNm9vaefCxW9Kj7fgQAQUlW+PaMqaiZhWyElxnES/n kdysN+/+0+BrRjJhUc55/UWM7rSh69se0i8gtUxsBPj9hTqBKtqU0DGcdVyymZ0+rw4N s8ri3JRI+mPDGsvXRoyOBg50vzPjsOYIAxmxLHlHF9lYKI67qq4CbdHllC/ei+cWSCgN XYI1MY4gx7rmffY9sIAN1IlwZiGwoCbdEV3FguzEAt4M2EX6XtIrTO9uJLwU/l/THfDv r85NECQOMgqmI1gNP5eGusjE00QviWK3hUmhWQXdBK8MGVmc3EeGuo/PnAxv9a9ZZSXk rDqQ== X-Gm-Message-State: AOAM531X2bKAJwjNpl0k1ga43O1O5OclokEItKTvcjmjxPaDvsxeFfz8 iVvUVmi4C4fef75Bcv4Ueq+UWeH6CwhKPr8KJHs= X-Google-Smtp-Source: ABdhPJy0N8+0keppoFVKww4qojdDQl7iy7lVAXTjwkOv6qTaWMXeKlIP6oYsZIPmPWHUpDDGFstnOA== X-Received: by 2002:a05:600c:2116:: with SMTP id u22mr2123763wml.174.1608107585343; Wed, 16 Dec 2020 00:33:05 -0800 (PST) Received: from [192.168.0.27] ([80.0.65.139]) by smtp.gmail.com with ESMTPSA id v7sm1692363wma.26.2020.12.16.00.33.03 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 16 Dec 2020 00:33:04 -0800 (PST) Subject: Re: [PATCH] RISC-V: Add semihosting support To: Jeff Johnston Cc: Newlib References: <694d497b-bc07-a3ba-2643-a7336927e9a7@embecosm.com> From: Craig Blackmore Autocrypt: addr=craig.blackmore@embecosm.com; prefer-encrypt=mutual; keydata= xsBNBFdIF8oBCACwrsvc6YVfzJRT+ZoBfL9jEb8ITwNahDxCGSG6sIWrJ9UFeTwE8fnNhMpz RyFRm0OXruS5k/8YHJHrxKxFY9cgZ3CWNftXEjRqURUWGtN/ESiw0J7nVfhSGQTo3LBzpXZ1 0JHk4ZHKDJKYa+fhybCHOs19BfP3HydHoTlc5QTKMfom0X/xo7WDdwUYeZsjD9u8IzHk7gNw 05Abk1vqni+J7Fghjp4RI8W3IsjpKOfV3f02OyO/MTSraXNyejO4JRl0A8b3q1Lq+G6Z7o5n LVief5JpkRyzWQSawTIBKmRZa9EzAKZXd6IJdY/sZt7pTir5EP7MHq4a+AtKfKuDkrDDABEB AAHNLkNyYWlnIEJsYWNrbW9yZSA8Y3JhaWcuYmxhY2ttb3JlQGVtYmVjb3NtLmNvbT7CwHgE EwECACIFAldIF8oCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGEeRQLLl5WtydMH /1nYd9jmOBaF8w5gGgjF5eOO5b/cdUegmO///VYj/5R7iF/zbB6KgF0Obo5h2gG9AIfsZG+T ybuTx7oU1DZYEIndw+YP9c9Yi5de5UzEHwbJiV57W0n+MP0Widgw7p6XJmUQ1XbHxdcWp7nY EJa8ASKLuuIhO8JFUXbQ8BcUiWbsA/JxgCzeid8iixGrzPWj6iFzoK2mX4GqP+24pXSDUamM TXmSQd2taYEsyUdJNiEkUC51ncRcMuThjdtfn6Ok+7lHjh3Zz8q0keJz5pnIp4EXdkAgKSjq U42PMrd3v1HoIFINTtr5F23OdkxoQzysu4GMO4pkw5pwz95Uckr08ojOwE0EV0gXygEIAKv/ luYHmCG/qefgzdbnegwMdG5753NJ+zGxFltFX6aaOPZ8go9Omf6zwjybUKv6Qx6AlDanwCl3 ewVQs+h9iW8uaQBRgeDmwAGMG/doBiFqs7X0jBf23exMiJezXlKb2ZlKzMAbzJ87408AzRaV sZdwEpXHVi2mRPoXtMrqL5iQEyG5hdx2ySj5164DIgVOs/ypFiaiFaDPkIcAQTzJrxsbt6pf iI9kT93DO9nRKVV0pPWztV8P5gKM8HY2rS0wQcfrqAU6T89Aa0VFw92J+w5d2spF8MUNPsvR NLm9ooCF3YME9STYHXrNH1U9fJUWpIC+b49UoWSWRD9nwl2h2i8AEQEAAcLAXwQYAQIACQUC V0gXygIbDAAKCRBhHkUCy5eVreLbB/sHPs1xu78uNV8O4UPTX7D5zBBS3nsrbDr+8stmXRap xbvo6kqKzIMAXuO3bYB/NyJ/tFzuFr9Tjd/2g56D2186bp01/kgxJ9CEl/m2T3lG3DlxIoLg pCExzTLTb8zH/7/6mdeJ17cdnrK+2QAKYctReVPAC67cq5KmUyU3bv5e1JzhV4ezz/i/O+Jv el112ZEsa54ya9KZOUHbgAR6hLnRWIa+8yQTtXqYRc3LxLRfS80Wn0Err1YvqFYzJsQMC8ND xAeEuqQ1gfk1b0jmv7tYljNqsHqzGVbuWz6hyzyLv5GjcdSDKpbw/797gRKQSY8Gty5ynfUH O4kKyuZPrE8P Message-ID: <3ef25bfd-65d7-e8a2-cdd6-0b0532b5c4f6@embecosm.com> Date: Wed, 16 Dec 2020 08:33:02 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, HTML_MESSAGE, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, 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 Content-Transfer-Encoding: 8bit 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 08:33:12 -0000 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 > > > 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 > >