From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx07-00376f01.pphosted.com (mx07-00376f01.pphosted.com [185.132.180.163]) by sourceware.org (Postfix) with ESMTPS id 1D03238582B7 for ; Mon, 30 Oct 2023 13:01:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1D03238582B7 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=imgtec.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=imgtec.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1D03238582B7 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=185.132.180.163 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698670878; cv=none; b=xmGQY4wl3r4h1OV70aI7jwLfghw7qKk5W5/r4QjRIzLtdG3xaUVBJFb7kLcKgE4UnsZwxxDUUVhDHID3vLcyItmpQ8jlym2/k3UcilqeHfxQiMrPh8FPfM6KVDsrua8uolXFw/a5Eaadu/Okeu2EVBP4y4VNcIU9ECLhCVujoNs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698670878; c=relaxed/simple; bh=1np2O+PRXC6E5I22OOWta9m+Ebe2/OtC/uhv7iMwlww=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=wFXbPh013H/GNc+5ytECX6nMdYtGQ1wKK8HGX5BqblQ+W0neO834eZadICzWRXi7x3ZIoTp84RUNFPK513amQjxqz9vUuPCQqlhGrptTUsp2KhjTMYaf+H6GNVXM37XExf65PBdch3UgWxtZIKpq8p7I4Sv3r8r3G9PDoDUwGzU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from pps.filterd (m0168889.ppops.net [127.0.0.1]) by mx07-00376f01.pphosted.com (8.17.1.22/8.17.1.22) with ESMTP id 39U6hUSk026687; Mon, 30 Oct 2023 13:00:58 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=imgtec.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= dk201812; bh=E3SwLI2+ooMhF6jK+Fz/E5NtSQHK6NqzfCJ06HvdR/4=; b=vRw VcICNSEK1sj7nzB7kZPk9p2VOtldAJf2/BO9huZATFY2i6CS2y9Ud8LIn0FhNLH3 dKgoERdAVdoNJfVCqxbgqiSrH9/di2SDfcwKAfZnDNi5YjTSZ3r5vAO289nPKQp4 SVVMWNAQ9Nz/chg9I/6MUxoMSfFKLq4Y5rQtELjdtAMaVqKyOUhfbunf2dBosJ37 KpAilVRBhz8zqR3uKQn852U7Kj39nfPaBYLxY0Sces9ThlvtSP60xtfrTbcXG/MD o76UjPCFWdFUTFOyTouuhBJIGDaIGoWBo+t7LHf52qXHoHEM3h6JuxKQA7iJpTuc KmcxIb6znQIZY/A/Sug== Received: from hhmail04.hh.imgtec.org ([217.156.249.195]) by mx07-00376f01.pphosted.com (PPS) with ESMTPS id 3u0tcrhh37-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Mon, 30 Oct 2023 13:00:57 +0000 (GMT) Received: from hhjpatil.hh.imgtec.org (10.100.136.70) by HHMAIL04.hh.imgtec.org (10.100.10.119) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Mon, 30 Oct 2023 13:00:54 +0000 From: To: CC: , , , , Subject: [PATCH v2 3/3] [sim/riscv] Add semi-hosting support Date: Mon, 30 Oct 2023 13:00:42 +0000 Message-ID: <20231030130042.1472535-4-jaydeep.patil@imgtec.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231030130042.1472535-1-jaydeep.patil@imgtec.com> References: <20231030130042.1472535-1-jaydeep.patil@imgtec.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [10.100.136.70] X-ClientProxiedBy: HHMAIL04.hh.imgtec.org (10.100.10.119) To HHMAIL04.hh.imgtec.org (10.100.10.119) X-EXCLAIMER-MD-CONFIG: 15a78312-3e47-46eb-9010-2e54d84a9631 X-Proofpoint-GUID: 7ZMYz7I0xaDMD21Vy7dfPXFdx9QtIh0t X-Proofpoint-ORIG-GUID: 7ZMYz7I0xaDMD21Vy7dfPXFdx9QtIh0t X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Jaydeep Patil Added support for all semi-hosting calls. Enable prints in gdb.arch/riscv-insn-simulation.c. --- .../gdb.arch/riscv-insn-simulation.c | 2 - .../gdb.arch/riscv-insn-simulation.exp | 3 +- sim/riscv/riscv-sim.h | 21 + sim/riscv/sim-main.c | 494 ++++++++++++++++++ 4 files changed, 517 insertions(+), 3 deletions(-) diff --git a/gdb/testsuite/gdb.arch/riscv-insn-simulation.c b/gdb/testsuite/gdb.arch/riscv-insn-simulation.c index db2b8b4f3d8..12334bdd89e 100755 --- a/gdb/testsuite/gdb.arch/riscv-insn-simulation.c +++ b/gdb/testsuite/gdb.arch/riscv-insn-simulation.c @@ -51,8 +51,6 @@ #define SKIP_c_fsdsp #endif -#define DISABLE_PRINTS - #if defined (DISABLE_PRINTS) #define print(...) ; #else diff --git a/gdb/testsuite/gdb.arch/riscv-insn-simulation.exp b/gdb/testsuite/gdb.arch/riscv-insn-simulation.exp index f94a31cc236..9ffa526b318 100755 --- a/gdb/testsuite/gdb.arch/riscv-insn-simulation.exp +++ b/gdb/testsuite/gdb.arch/riscv-insn-simulation.exp @@ -28,4 +28,5 @@ if { ![runto_main] } { return -1 } -gdb_continue_to_end ".*All.*tests pass.*Inferior.*process.*exited normally.*" +gdb_continue_to_end "continue parent to end" "continue" 1 + diff --git a/sim/riscv/riscv-sim.h b/sim/riscv/riscv-sim.h index 6d9a719eadf..8e80a4f7374 100644 --- a/sim/riscv/riscv-sim.h +++ b/sim/riscv/riscv-sim.h @@ -78,8 +78,29 @@ extern void initialize_env (SIM_DESC, const char * const *argv, #define APPLICATION_EXIT 0x20026 #define SYS_OPEN 0x01 +#define SYS_CLOSE 0x02 +#define SYS_WRITEC 0x03 +#define SYS_WRITE0 0x04 +#define SYS_WRITE 0x05 +#define SYS_READ 0x06 +#define SYS_READC 0x07 +#define SYS_ISERROR 0x08 +#define SYS_ISTTY 0x09 +#define SYS_SEEK 0x0A +#define SYS_FLEN 0x0C +#define SYS_TMPNAM 0x0D +#define SYS_REMOVE 0x0E +#define SYS_RENAME 0x0F +#define SYS_CLOCK 0x10 +#define SYS_TIME 0x11 +#define SYS_SYSTEM 0x12 +#define SYS_ERRNO 0x13 #define SYS_GET_CMDLINE 0x15 +#define SYS_HEAPINFO 0x16 #define SYS_EXIT 0x18 +#define SYS_EXIT_EXTENDED 0x20 +#define SYS_ELAPSED 0x30 +#define SYS_TICKFREQ 0x31 #define GDB_O_RDONLY 0x000 #define GDB_O_WRONLY 0x001 diff --git a/sim/riscv/sim-main.c b/sim/riscv/sim-main.c index da9a1aa4cdf..8362d85522a 100644 --- a/sim/riscv/sim-main.c +++ b/sim/riscv/sim-main.c @@ -26,7 +26,11 @@ #include #include +#include +#include +#include +#include "bfd.h" #include "sim-main.h" #include "sim-signal.h" #include "sim-syscall.h" @@ -66,6 +70,8 @@ static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1]; } \ } while (0) +static clock_t clock_start = 0; + static INLINE void store_rd (SIM_CPU *cpu, int rd, unsigned_word val) { @@ -187,6 +193,430 @@ get_core_string_with_len (SIM_CPU *cpu, unsigned_word addr, return str; } +/* Write VALUE at specified address. ADDR and (INDEX * XLEN) + form the base address. */ +static void +set_core_data (SIM_CPU *cpu, unsigned_word addr, unsigned_word index, + uintptr_t value) +{ + int xlen = RISCV_XLEN (cpu); + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + if (xlen == 64) + sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, read_map, + addr + (index * 8), value); + else + sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, read_map, + addr + (index * 4), (uint32_t) value); +} + +/* Read data of length SLEN and address ADDR. */ +static char * +get_core_string (SIM_CPU *cpu, unsigned_word addr, int *slen) +{ + int len = 0; + char * str; + const int chunk_size = 128; /* allocate buffer in chunks. */ + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + str = (char *) malloc (chunk_size); + + while (1) + { + uint8_t ch = sim_core_read_unaligned_1 (cpu, riscv_cpu->pc, read_map, + addr + len); + str[len] = ch; + if (ch == 0) + break; + len++; + if ((len % chunk_size) == 0) + str = (char *) realloc (str, len + chunk_size); + } + + *slen = len; + return str; +} + +/* Find address of the symbol in SYMNAME. */ +static uintptr_t +get_symbol_value (SIM_CPU *cpu, const char *symname) +{ + struct bfd *abfd = STATE_PROG_BFD (CPU_STATE (cpu)); + static asymbol **symbol_table = NULL; + static long number_of_symbols = 0; + + if (symbol_table == NULL) + { + long storage_needed; + storage_needed = bfd_get_symtab_upper_bound (abfd); + if (storage_needed <= 0) + return 0; + symbol_table = (asymbol **) malloc (storage_needed); + if (symbol_table == NULL) + return 0; + number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); + if (number_of_symbols <= 0) + return 0; + } + + for (long i = 0; i < number_of_symbols; i++) + { + asymbol *sym = symbol_table[i]; + if (!strcmp (sym->name, symname)) + return bfd_asymbol_value (sym); + } + + return 0; +} + +/* SYS_FLEN + Register a1 points to a buffer containing: + Index 0: Integer: File handle. + The file size in bytes is returned through register a0. */ +static void +semihosting_flen (SIM_CPU *cpu) +{ + int fd; + struct stat sb; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + fd = (int) get_core_data (cpu, riscv_cpu->a1, 0); + + if (fd > STDERR_FILENO) + { + fstat (fd, &sb); + riscv_cpu->a0 = sb.st_size; + } + else + riscv_cpu->a0 = 0; +} + +/* SYS_WRITE + Write data to a file. Register a1 points to a buffer containing: + Index 0: Integer: File handle. + Index 1: Pointer: Pointer to buffer. + Index 2: Integer: Number of bytes to write. + Number of bytes written is returned through register a0. */ +static void +semihosting_write (SIM_CPU *cpu) +{ + int i, fd; + uintptr_t buf; + uintptr_t count; + char *str; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + fd = (int) get_core_data (cpu, riscv_cpu->a1, 0); + buf = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 1); + count = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 2); + + if (count <= 0) + { + riscv_cpu->a0 = -1; + return; + } + + str = get_core_string_with_len (cpu, buf, count); + riscv_cpu->a0 = sim_io_write (CPU_STATE (cpu), fd, str, count); + free (str); +} + +/* SYS_WRITEC + Register a1 points to a buffer containing: + Index 0: Integer: Character to write to console. + Number of bytes written is returned through register a0. */ +static void +semihosting_writec (SIM_CPU *cpu) +{ + char ch; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + ch = (char) get_core_data (cpu, riscv_cpu->a1, 0); + riscv_cpu->a0 = sim_io_write_stdout (CPU_STATE (cpu), &ch, 1); +} + +/* SYS_WRITE0 + Register a1 points to a buffer containing: + Index 0: Integer: Null terminated string. + Number of bytes written is returned through register a0. */ +static void +semihosting_write0 (SIM_CPU *cpu) +{ + int len; + char *str; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + str = get_core_string (cpu, riscv_cpu->a1, &len); + riscv_cpu->a0 = sim_io_write_stdout (CPU_STATE (cpu), str, len); +} + +/* SYS_READ + Read data from a file. Register a1 points to a buffer containing: + Index 0: Integer: File handle. + Index 1: Pointer: Pointer to destination buffer. + Index 2: Integer: Number of bytes to read. + Number of bytes read is returned through register a0. */ +static void +semihosting_read (SIM_CPU *cpu) +{ + int i, fd, read_len; + uintptr_t dst_buf; + uintptr_t count; + char *host_buf; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + fd = (int) get_core_data (cpu, riscv_cpu->a1, 0); + dst_buf = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 1); + count = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 2); + + if (count <= 0) + { + riscv_cpu->a0 = 0; + return; + } + + host_buf = (char *) malloc (count); + read_len = sim_io_read (CPU_STATE (cpu), fd, host_buf, count); + if (read_len > 0) + set_core_string (cpu, dst_buf, host_buf, read_len); + riscv_cpu->a0 = read_len; + free (host_buf); +} + +/* SYS_READC + Read a char from console and return it through register a0. */ +static void +semihosting_readc (SIM_CPU *cpu) +{ + char ch; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + sim_io_read_stdin (CPU_STATE (cpu), &ch, 1); + riscv_cpu->a0 = ch; +} + +/* SYS_CLOSE + Close a file. Register a1 points to a buffer containing: + Index 0: Integer: File handle. + Return status in register a0. */ +static void +semihosting_close (SIM_CPU *cpu) +{ + int fd; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + fd = (int) get_core_data (cpu, riscv_cpu->a1, 0); + riscv_cpu->a0 = sim_io_close (CPU_STATE (cpu), fd); +} + +/* SYS_SEEK + Seek in a file. Register a1 points to a buffer containing: + Index 0: Integer: File handle. + Index 1: Integer: Number of bytes to seek in the file. + Return status in register a0. */ +static void +semihosting_seek (SIM_CPU *cpu) +{ + int fd; + uintptr_t pos; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + fd = (int) get_core_data (cpu, riscv_cpu->a1, 0); + pos = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 1); + riscv_cpu->a0 = sim_io_lseek (CPU_STATE (cpu), fd, pos, 0); +} + +/* SYS_EXIT_EXTENDED + Register a1 points to a buffer containing: + Index 0: Integer: Application code. + Index 1: Integer: Exit code. */ +static void +semihosting_exit_extended (SIM_CPU *cpu) +{ + int ret; + uintptr_t app_code, exit_status; + SIM_DESC sd = CPU_STATE (cpu); + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + app_code = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 0); + exit_status = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 1); + if (app_code == APPLICATION_EXIT) + ret = exit_status; + else + ret = 1; + riscv_cpu->a0 = ret; + sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_exited, ret); +} + +/* SYS_ISERROR + Register a1 points to a buffer containing: + Index 0: Integer: Status code. */ +static void +semihosting_iserror (SIM_CPU *cpu) +{ + intptr_t status; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + status = (intptr_t) get_core_data (cpu, riscv_cpu->a1, 0); + riscv_cpu->a0 = (status < 0); +} + +/* SYS_ISTTY + Register a1 points to a buffer containing: + Index 0: Integer: File handle. */ +static void +semihosting_istty (SIM_CPU *cpu) +{ + int fd; + SIM_DESC sd = CPU_STATE (cpu); + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + fd = (int) get_core_data (cpu, riscv_cpu->a1, 0); + riscv_cpu->a0 = sim_io_isatty (sd, fd); +} + +/* SYS_TMPNAM + Register a1 points to a buffer containing: + Index 0: Pointer: Destination buffer address. + Index 1: Integer: ID (ignored). + Index 2: Integer: Maximum length of the buffer. + Pointer to temporary name is returned through a0. */ +static void +semihosting_tmpnam (SIM_CPU *cpu) +{ + uintptr_t t_pname; + int len, id, maxpath; + char *pname; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + t_pname = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 0); + id = (int) get_core_data (cpu, riscv_cpu->a1, 1); + maxpath = (int) get_core_data (cpu, riscv_cpu->a1, 2); + + pname = tmpnam (NULL); + + if (pname == NULL) + { + riscv_cpu->a0 = 0; + return; + } + + len = strlen (pname); + if (maxpath > len) + { + riscv_cpu->a0 = 0; + return; + } + + set_core_string (cpu, t_pname, pname, len + 1); + riscv_cpu->a0 = t_pname; +} + +/* SYS_REMOVE + Register a1 points to a buffer containing: + Index 0: Pointer: Name of the file to remove. + Index 1: Integer: Length of the file name. */ +static void +semihosting_remove (SIM_CPU *cpu) +{ + uintptr_t t_pname; + int len; + char *pname; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + t_pname = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 0); + len = (int) get_core_data (cpu, riscv_cpu->a1, 1); + pname = get_core_string_with_len (cpu, t_pname, len); + riscv_cpu->a0 = sim_io_unlink (CPU_STATE (cpu), pname); + free (pname); +} + +/* SYS_RENAME + Register a1 points to a buffer containing: + Index 0: Pointer: Old file path. + Index 1: Integer: Length of the old file name. + Index 2: Pointer: New file name. + Index 3: Integer: Length of the new file name. */ +static void +semihosting_rename (SIM_CPU *cpu) +{ + uintptr_t old_name_addr, new_name_addr; + uintptr_t old_len, new_len; + char *old_host_name, *new_host_name; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + old_name_addr = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 0); + old_len = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 1); + new_name_addr = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 2); + new_len = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 3); + old_host_name = get_core_string_with_len (cpu, old_name_addr, old_len); + new_host_name = get_core_string_with_len (cpu, new_name_addr, new_len); + riscv_cpu->a0 = sim_io_rename (CPU_STATE (cpu), old_host_name, + new_host_name); + free (old_host_name); + free (new_host_name); +} + +/* SYS_SYSTEM + Register a1 points to a buffer containing: + Index 0: Pointer: Command string. + Index 1: Integer: Length of the command string. + Status of the command is returned through a0. */ +static void +semihosting_system (SIM_CPU *cpu) +{ + uintptr_t cmd_addr; + uintptr_t cmd_len; + char *cmd_host; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + cmd_addr = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 0); + cmd_len = (uintptr_t) get_core_data (cpu, riscv_cpu->a1, 1); + cmd_host = get_core_string_with_len (cpu, cmd_addr, cmd_len); + riscv_cpu->a0 = sim_io_system (CPU_STATE (cpu), cmd_host); + free (cmd_host); +} + +/* SYS_ELAPSED + Return the elapsed seconds in a buffer pointed by register a1. */ +static void +semihosting_elapsed (SIM_CPU *cpu) +{ + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + clock_t elapsed = clock () - clock_start; + if (RISCV_XLEN (cpu) == 32) + { + sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map, + riscv_cpu->a1, (uint32_t) elapsed); + sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map, + riscv_cpu->a1 + 4, (uint32_t) (elapsed >> 32)); + } + else + sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map, riscv_cpu->a1, + elapsed); +} + +/* SYS_HEAPINFO + Return the heap start, heap end, stack start and stack end + in a buffer pointed by register a1. */ +static void +semihosting_heapinfo (SIM_CPU *cpu) +{ + static uintptr_t heap_base = 0, heap_limit = 0, + stack_base = 0, stack_limit = 0, stack_size = 0; + static bool have_heap = false, have_stack = false; + struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu); + + if (have_heap == false) + { + heap_base = get_symbol_value (cpu, "__heap_start"); + heap_limit = get_symbol_value (cpu, "__heap_end"); + have_heap = true; + } + + if (have_stack == false) + { + stack_base = get_symbol_value (cpu, "__stack"); + stack_size = get_symbol_value (cpu, "__stack_size"); + stack_limit = stack_base + stack_size; + have_stack = true; + } + + set_core_data (cpu, riscv_cpu->a1, 0, heap_base); + set_core_data (cpu, riscv_cpu->a1, 1, heap_limit); + set_core_data (cpu, riscv_cpu->a1, 2, stack_base); + set_core_data (cpu, riscv_cpu->a1, 3, stack_limit); +} + /* SYS_OPEN Register a1 points to a buffer containing: Index 0: Pointer: Address of the file name string. @@ -299,6 +729,69 @@ do_semihosting (SIM_CPU *cpu) case SYS_EXIT: semihosting_exit (cpu); break; + case SYS_CLOSE: + semihosting_close (cpu); + break; + case SYS_WRITEC: + semihosting_writec (cpu); + break; + case SYS_WRITE0: + semihosting_write0 (cpu); + break; + case SYS_WRITE: + semihosting_write (cpu); + break; + case SYS_READ: + semihosting_read (cpu); + break; + case SYS_READC: + semihosting_readc (cpu); + break; + case SYS_ISERROR: + semihosting_iserror (cpu); + break; + case SYS_ISTTY: + semihosting_istty (cpu); + break; + case SYS_SEEK: + semihosting_seek (cpu); + break; + case SYS_FLEN: + semihosting_flen (cpu); + break; + case SYS_TMPNAM: + semihosting_tmpnam (cpu); + break; + case SYS_REMOVE: + semihosting_remove (cpu); + break; + case SYS_RENAME: + semihosting_rename (cpu); + break; + case SYS_CLOCK: + riscv_cpu->a0 = (clock () / (CLOCKS_PER_SEC / 100)); + break; + case SYS_TIME: + riscv_cpu->a0 = sim_io_time (CPU_STATE (cpu)); + break; + case SYS_SYSTEM: + semihosting_system (cpu); + break; + case SYS_ERRNO: + riscv_cpu->a0 = sim_io_get_errno (CPU_STATE (cpu)); + break; + case SYS_HEAPINFO: + semihosting_heapinfo (cpu); + break; + case SYS_EXIT_EXTENDED: + semihosting_exit_extended (cpu); + break; + case SYS_ELAPSED: + semihosting_elapsed (cpu); + break; + case SYS_TICKFREQ: + riscv_cpu->a0 = 1000000000; + break; default: return -1; /* Semi-hosting call not supported. */ } @@ -1727,6 +2220,7 @@ initialize_cpu (SIM_DESC sd, SIM_CPU *cpu, int mhartid) riscv_cpu->csr.mimpid = 0x8000; riscv_cpu->csr.mhartid = mhartid; + clock_start = clock (); } /* Some utils don't like having a NULL environ. */ -- 2.25.1