From 3ff59ba45d7793b791cacba3d89ecdc8ccfe5fa4 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Wed, 10 Jan 2024 10:15:05 +0100 Subject: [PATCH] small refactor, adds baisc functionality --- src/iss/semihosting/semihosting.cpp | 690 +++------------------------- src/iss/semihosting/semihosting.h | 60 ++- 2 files changed, 99 insertions(+), 651 deletions(-) diff --git a/src/iss/semihosting/semihosting.cpp b/src/iss/semihosting/semihosting.cpp index 02f8d65..00124fb 100644 --- a/src/iss/semihosting/semihosting.cpp +++ b/src/iss/semihosting/semihosting.cpp @@ -1,621 +1,108 @@ #include "semihosting.h" +#include #include #include - +// explanation of syscalls can be found at https://github.com/SpinalHDL/openocd_riscv/blob/riscv_spinal/src/target/semihosting_common.h template void semihosting_callback(iss::arch_if* arch_if_ptr, T call_number, T parameter) { - switch(call_number) { - case SEMIHOSTING_ENTER_SVC: { - throw std::runtime_error("Semihosting Call not Implemented"); - } /* DEPRECATED */ - case SEMIHOSTING_SYS_CLOCK: { - /* - * Returns the number of centiseconds (hundredths of a second) - * since the execution started. - * - * Values returned can be of limited use for some benchmarking - * purposes because of communication overhead or other - * agent-specific factors. For example, with a debug hardware - * unit the request is passed back to the host for execution. - * This can lead to unpredictable delays in transmission and - * process scheduling. - * - * Use this function to calculate time intervals, by calculating - * differences between intervals with and without the code - * sequence to be timed. - * - * Entry - * The PARAMETER REGISTER must contain 0. There are no other - * parameters. - * - * Return - * On exit, the RETURN REGISTER contains: - * - The number of centiseconds since some arbitrary start - * point, if the call is successful. - * - –1 if the call is not successful. For example, because - * of a communications error. - */ + switch(static_cast(call_number)) { + case semihosting_syscalls::SYS_CLOCK: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_CLOSE: { - /* - * Closes a file on the host system. The handle must reference - * a file that was opened with SYS_OPEN. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * one-field argument block: - * - field 1 Contains a handle for an open file. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 0 if the call is successful - * - –1 if the call is not successful. - */ + case semihosting_syscalls::SYS_CLOSE: { + throw std::runtime_error("Semihosting Call not Implemented"); + break; + } + case semihosting_syscalls::SYS_ELAPSED: { + throw std::runtime_error("Semihosting Call not Implemented"); + break; + } + case semihosting_syscalls::SYS_ERRNO: { + throw std::runtime_error("Semihosting Call not Implemented"); + break; + } + case semihosting_syscalls::SYS_EXIT: { - throw std::runtime_error("Semihosting Call not Implemented"); + throw std::runtime_error("ISS terminated by Semihost: SYS_EXIT"); + break; } - case SEMIHOSTING_SYS_ELAPSED: { - /* - * Returns the number of elapsed target ticks since execution - * started. - * Use SYS_TICKFREQ to determine the tick frequency. - * - * Entry (32-bit) - * On entry, the PARAMETER REGISTER points to a two-field data - * block to be used for returning the number of elapsed ticks: - * - field 1 The least significant field and is at the low address. - * - field 2 The most significant field and is at the high address. - * - * Entry (64-bit) - * On entry the PARAMETER REGISTER points to a one-field data - * block to be used for returning the number of elapsed ticks: - * - field 1 The number of elapsed ticks as a 64-bit value. - * - * Return - * On exit: - * - On success, the RETURN REGISTER contains 0, the PARAMETER - * REGISTER is unchanged, and the data block pointed to by the - * PARAMETER REGISTER is filled in with the number of elapsed - * ticks. - * - On failure, the RETURN REGISTER contains -1, and the - * PARAMETER REGISTER contains -1. - * - * Note: Some semihosting implementations might not support this - * semihosting operation, and they always return -1 in the - * RETURN REGISTER. - */ - throw std::runtime_error("Semihosting Call not Implemented"); + case semihosting_syscalls::SYS_EXIT_EXTENDED: { + throw std::runtime_error("ISS terminated by Semihost: SYS_EXIT_EXTENDED"); + break; } - case SEMIHOSTING_SYS_ERRNO: { - /* - * Returns the value of the C library errno variable that is - * associated with the semihosting implementation. The errno - * variable can be set by a number of C library semihosted - * functions, including: - * - SYS_REMOVE - * - SYS_OPEN - * - SYS_CLOSE - * - SYS_READ - * - SYS_WRITE - * - SYS_SEEK. - * - * Whether errno is set or not, and to what value, is entirely - * host-specific, except where the ISO C standard defines the - * behavior. - * - * Entry - * There are no parameters. The PARAMETER REGISTER must be 0. - * - * Return - * On exit, the RETURN REGISTER contains the value of the C - * library errno variable. - */ + case semihosting_syscalls::SYS_FLEN: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_EXIT: { - /* - * Note: SYS_EXIT was called angel_SWIreason_ReportException in - * previous versions of the documentation. - * - * An application calls this operation to report an exception - * to the debugger directly. The most common use is to report - * that execution has completed, using ADP_Stopped_ApplicationExit. - * - * Note: This semihosting operation provides no means for 32-bit - * callers to indicate an application exit with a specified exit - * code. Semihosting callers may prefer to check for the presence - * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use - * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it - * is available. - * - * Entry (32-bit) - * On entry, the PARAMETER register is set to a reason code - * describing the cause of the trap. Not all semihosting client - * implementations will necessarily trap every corresponding - * event. Important reason codes are: - * - * - ADP_Stopped_ApplicationExit 0x20026 - * - ADP_Stopped_RunTimeErrorUnknown 0x20023 - * - * Entry (64-bit) - * On entry, the PARAMETER REGISTER contains a pointer to a - * two-field argument block: - * - field 1 The exception type, which is one of the set of - * reason codes in the above tables. - * - field 2 A subcode, whose meaning depends on the reason - * code in field 1. - * In particular, if field 1 is ADP_Stopped_ApplicationExit - * then field 2 is an exit status code, as passed to the C - * standard library exit() function. A simulator receiving - * this request must notify a connected debugger, if present, - * and then exit with the specified status. - * - * Return - * No return is expected from these calls. However, it is - * possible for the debugger to request that the application - * continues by performing an RDI_Execute request or equivalent. - * In this case, execution continues with the registers as they - * were on entry to the operation, or as subsequently modified - * by the debugger. - */ + case semihosting_syscalls::SYS_GET_CMDLINE: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_EXIT_EXTENDED: { - /* - * This operation is only supported if the semihosting extension - * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is - * reported using feature byte 0, bit 0. If this extension is - * supported, then the implementation provides a means to - * report a normal exit with a nonzero exit status in both 32-bit - * and 64-bit semihosting APIs. - * - * The implementation must provide the semihosting call - * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs. - * - * SYS_EXIT_EXTENDED is used by an application to report an - * exception or exit to the debugger directly. The most common - * use is to report that execution has completed, using - * ADP_Stopped_ApplicationExit. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * two-field argument block: - * - field 1 The exception type, which should be one of the set - * of reason codes that are documented for the SYS_EXIT - * (0x18) call. For example, ADP_Stopped_ApplicationExit. - * - field 2 A subcode, whose meaning depends on the reason - * code in field 1. In particular, if field 1 is - * ADP_Stopped_ApplicationExit then field 2 is an exit status - * code, as passed to the C standard library exit() function. - * A simulator receiving this request must notify a connected - * debugger, if present, and then exit with the specified status. - * - * Return - * No return is expected from these calls. - * - * For the A64 API, this call is identical to the behavior of - * the mandatory SYS_EXIT (0x18) call. If this extension is - * supported, then both calls must be implemented. - */ + case semihosting_syscalls::SYS_HEAPINFO: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_FLEN: { - /* - * Returns the length of a specified file. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * one-field argument block: - * - field 1 A handle for a previously opened, seekable file - * object. - * - * Return - * On exit, the RETURN REGISTER contains: - * - The current length of the file object, if the call is - * successful. - * - –1 if an error occurs. - */ + case semihosting_syscalls::SYS_ISERROR: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_GET_CMDLINE: { - /* - * Returns the command line that is used for the call to the - * executable, that is, argc and argv. - * - * Entry - * On entry, the PARAMETER REGISTER points to a two-field data - * block to be used for returning the command string and its length: - * - field 1 A pointer to a buffer of at least the size that is - * specified in field 2. - * - field 2 The length of the buffer in bytes. - * - * Return - * On exit: - * If the call is successful, then the RETURN REGISTER contains 0, - * the PARAMETER REGISTER is unchanged, and the data block is - * updated as follows: - * - field 1 A pointer to a null-terminated string of the command - * line. - * - field 2 The length of the string in bytes. - * If the call is not successful, then the RETURN REGISTER - * contains -1. - * - * Note: The semihosting implementation might impose limits on - * the maximum length of the string that can be transferred. - * However, the implementation must be able to support a - * command-line length of at least 80 bytes. - */ + case semihosting_syscalls::SYS_ISTTY: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_HEAPINFO: { - /* - * Returns the system stack and heap parameters. - * - * Entry - * On entry, the PARAMETER REGISTER contains the address of a - * pointer to a four-field data block. The contents of the data - * block are filled by the function. The following C-like - * pseudocode describes the layout of the block: - * struct block { - * void* heap_base; - * void* heap_limit; - * void* stack_base; - * void* stack_limit; - * }; - * - * Return - * On exit, the PARAMETER REGISTER is unchanged and the data - * block has been updated. - */ + case semihosting_syscalls::SYS_OPEN: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_ISERROR: { - /* - * Determines whether the return code from another semihosting - * call is an error status or not. - * - * This call is passed a parameter block containing the error - * code to examine. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * one-field data block: - * - field 1 The required status word to check. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 0 if the status field is not an error indication - * - A nonzero value if the status field is an error indication. - */ + case semihosting_syscalls::SYS_READ: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_ISTTY: { - /* - * Checks whether a file is connected to an interactive device. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * one-field argument block: - * field 1 A handle for a previously opened file object. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 1 if the handle identifies an interactive device. - * - 0 if the handle identifies a file. - * - A value other than 1 or 0 if an error occurs. - */ + case semihosting_syscalls::SYS_READC: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_OPEN: { - /* - * Opens a file on the host system. - * - * The file path is specified either as relative to the current - * directory of the host process, or absolute, using the path - * conventions of the host operating system. - * - * Semihosting implementations must support opening the special - * path name :semihosting-features as part of the semihosting - * extensions reporting mechanism. - * - * ARM targets interpret the special path name :tt as meaning - * the console input stream, for an open-read or the console - * output stream, for an open-write. Opening these streams is - * performed as part of the standard startup code for those - * applications that reference the C stdio streams. The - * semihosting extension SH_EXT_STDOUT_STDERR allows the - * semihosting caller to open separate output streams - * corresponding to stdout and stderr. This extension is - * reported using feature byte 0, bit 1. Use SYS_OPEN with - * the special path name :semihosting-features to access the - * feature bits. - * - * If this extension is supported, the implementation must - * support the following additional semantics to SYS_OPEN: - * - If the special path name :tt is opened with an fopen - * mode requesting write access (w, wb, w+, or w+b), then - * this is a request to open stdout. - * - If the special path name :tt is opened with a mode - * requesting append access (a, ab, a+, or a+b), then this is - * a request to open stderr. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * three-field argument block: - * - field 1 A pointer to a null-terminated string containing - * a file or device name. - * - field 2 An integer that specifies the file opening mode. - * - field 3 An integer that gives the length of the string - * pointed to by field 1. - * - * The length does not include the terminating null character - * that must be present. - * - * Return - * On exit, the RETURN REGISTER contains: - * - A nonzero handle if the call is successful. - * - –1 if the call is not successful. - */ + case semihosting_syscalls::SYS_REMOVE: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_READ: { - /* - * Reads the contents of a file into a buffer. The file position - * is specified either: - * - Explicitly by a SYS_SEEK. - * - Implicitly one byte beyond the previous SYS_READ or - * SYS_WRITE request. - * - * The file position is at the start of the file when it is - * opened, and is lost when the file is closed. Perform the - * file operation as a single action whenever possible. For - * example, do not split a read of 16KB into four 4KB chunks - * unless there is no alternative. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * three-field data block: - * - field 1 Contains a handle for a file previously opened - * with SYS_OPEN. - * - field 2 Points to a buffer. - * - field 3 Contains the number of bytes to read to the buffer - * from the file. - * - * Return - * On exit, the RETURN REGISTER contains the number of bytes not - * filled in the buffer (buffer_length - bytes_read) as follows: - * - If the RETURN REGISTER is 0, the entire buffer was - * successfully filled. - * - If the RETURN REGISTER is the same as field 3, no bytes - * were read (EOF can be assumed). - * - If the RETURN REGISTER contains a value smaller than - * field 3, the read succeeded but the buffer was only partly - * filled. For interactive devices, this is the most common - * return value. - */ + case semihosting_syscalls::SYS_RENAME: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_READC: { - /* - * Reads a byte from the console. - * - * Entry - * The PARAMETER REGISTER must contain 0. There are no other - * parameters or values possible. - * - * Return - * On exit, the RETURN REGISTER contains the byte read from - * the console. - */ + case semihosting_syscalls::SYS_SEEK: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_REMOVE: { - /* - * Deletes a specified file on the host filing system. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * two-field argument block: - * - field 1 Points to a null-terminated string that gives the - * path name of the file to be deleted. - * - field 2 The length of the string. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 0 if the delete is successful - * - A nonzero, host-specific error code if the delete fails. - */ + case semihosting_syscalls::SYS_SYSTEM: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_RENAME: { - /* - * Renames a specified file. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * four-field data block: - * - field 1 A pointer to the name of the old file. - * - field 2 The length of the old filename. - * - field 3 A pointer to the new filename. - * - field 4 The length of the new filename. Both strings are - * null-terminated. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 0 if the rename is successful. - * - A nonzero, host-specific error code if the rename fails. - */ + case semihosting_syscalls::SYS_TICKFREQ: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_SEEK: { - /* - * Seeks to a specified position in a file using an offset - * specified from the start of the file. The file is assumed - * to be a byte array and the offset is given in bytes. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * two-field data block: - * - field 1 A handle for a seekable file object. - * - field 2 The absolute byte position to seek to. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 0 if the request is successful. - * - A negative value if the request is not successful. - * Use SYS_ERRNO to read the value of the host errno variable - * describing the error. - * - * Note: The effect of seeking outside the current extent of - * the file object is undefined. - */ + case semihosting_syscalls::SYS_TIME: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_SYSTEM: { - /* - * Passes a command to the host command-line interpreter. - * This enables you to execute a system command such as dir, - * ls, or pwd. The terminal I/O is on the host, and is not - * visible to the target. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * two-field argument block: - * - field 1 Points to a string to be passed to the host - * command-line interpreter. - * - field 2 The length of the string. - * - * Return - * On exit, the RETURN REGISTER contains the return status. - */ - - /* Provide SYS_SYSTEM functionality. Uses the - * libc system command, there may be a reason *NOT* - * to use this, but as I can't think of one, I - * implemented it this way. - */ + case semihosting_syscalls::SYS_TMPNAM: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_TICKFREQ: { - /* - * Returns the tick frequency. - * - * Entry - * The PARAMETER REGISTER must contain 0 on entry to this routine. - * - * Return - * On exit, the RETURN REGISTER contains either: - * - The number of ticks per second. - * - –1 if the target does not know the value of one tick. - * - * Note: Some semihosting implementations might not support - * this semihosting operation, and they always return -1 in the - * RETURN REGISTER. - */ + case semihosting_syscalls::SYS_WRITE: { throw std::runtime_error("Semihosting Call not Implemented"); + break; } - case SEMIHOSTING_SYS_TIME: { - /* - * Returns the number of seconds since 00:00 January 1, 1970. - * This value is real-world time, regardless of any debug agent - * configuration. - * - * Entry - * There are no parameters. - * - * Return - * On exit, the RETURN REGISTER contains the number of seconds. - */ - throw std::runtime_error("Semihosting Call not Implemented"); + case semihosting_syscalls::SYS_WRITEC: { + uint8_t character; + auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, parameter, 1, &character); + if(res != iss::Ok) + return; + putchar(character); + break; } - case SEMIHOSTING_SYS_TMPNAM: { - /* - * Returns a temporary name for a file identified by a system - * file identifier. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * three-word argument block: - * - field 1 A pointer to a buffer. - * - field 2 A target identifier for this filename. Its value - * must be an integer in the range 0-255. - * - field 3 Contains the length of the buffer. The length must - * be at least the value of L_tmpnam on the host system. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 0 if the call is successful. - * - –1 if an error occurs. - * - * The buffer pointed to by the PARAMETER REGISTER contains - * the filename, prefixed with a suitable directory name. - * If you use the same target identifier again, the same - * filename is returned. - * - * Note: The returned string must be null-terminated. - */ - throw std::runtime_error("Semihosting Call not Implemented"); - } - case SEMIHOSTING_SYS_WRITE: { - /* - * Writes the contents of a buffer to a specified file at the - * current file position. The file position is specified either: - * - Explicitly, by a SYS_SEEK. - * - Implicitly as one byte beyond the previous SYS_READ or - * SYS_WRITE request. - * - * The file position is at the start of the file when the file - * is opened, and is lost when the file is closed. - * - * Perform the file operation as a single action whenever - * possible. For example, do not split a write of 16KB into - * four 4KB chunks unless there is no alternative. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * three-field data block: - * - field 1 Contains a handle for a file previously opened - * with SYS_OPEN. - * - field 2 Points to the memory containing the data to be written. - * - field 3 Contains the number of bytes to be written from - * the buffer to the file. - * - * Return - * On exit, the RETURN REGISTER contains: - * - 0 if the call is successful. - * - The number of bytes that are not written, if there is an error. - */ - throw std::runtime_error("Semihosting Call not Implemented"); - } - case SEMIHOSTING_SYS_WRITEC: { - /* - * Writes a character byte, pointed to by the PARAMETER REGISTER, - * to the debug channel. When executed under a semihosting - * debugger, the character appears on the host debugger console. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to the - * character. - * - * Return - * None. The RETURN REGISTER is corrupted. - */ - throw std::runtime_error("Semihosting Call not Implemented"); - } - case SEMIHOSTING_SYS_WRITE0: { - /* - * Writes a null-terminated string to the debug channel. - * When executed under a semihosting debugger, the characters - * appear on the host debugger console. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to the - * first byte of the string. - * - * Return - * None. The RETURN REGISTER is corrupted. - */ - + case semihosting_syscalls::SYS_WRITE0: { uint8_t character; while(1) { auto res = arch_if_ptr->read(iss::address_type::PHYSICAL, iss::access_type::DEBUG_READ, 0, parameter, 1, &character); @@ -626,54 +113,19 @@ template void semihosting_callback(iss::arch_if* arch_if_ptr, T cal putchar(character); parameter++; } + break; } - case SEMIHOSTING_USER_CMD_0x100: { - /** - * - * This is a user defined operation (while user cmds 0x100-0x1ff - * are possible, none are currently implemented). - * - * Reads the user operation parameters from target, then fires the - * corresponding target event. When the target callbacks returned, - * cleans up the command parameter buffer. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * two-field data block: - * - field 1 Contains a pointer to the bound command parameter - * string - * - field 2 Contains the command parameter string length - * - * Return - * On exit, the RETURN REGISTER contains the return status. - */ + case semihosting_syscalls::USER_CMD_0x100: { throw std::runtime_error("Semihosting Call not Implemented"); - } /* First user cmd op code */ - - case SEMIHOSTING_USER_CMD_0x1FF: { - /** - * - * This is a user defined operation (while user cmds 0x100-0x1ff - * are possible, none are currently implemented). - * - * Reads the user operation parameters from target, then fires the - * corresponding target event. When the target callbacks returned, - * cleans up the command parameter buffer. - * - * Entry - * On entry, the PARAMETER REGISTER contains a pointer to a - * two-field data block: - * - field 1 Contains a pointer to the bound command parameter - * string - * - field 2 Contains the command parameter string length - * - * Return - * On exit, the RETURN REGISTER contains the return status. - */ + break; + } + case semihosting_syscalls::USER_CMD_0x1FF: { throw std::runtime_error("Semihosting Call not Implemented"); - } /* Last user cmd op code */ + break; + } default: throw std::runtime_error("Semihosting Call not Implemented"); + break; } } template void semihosting_callback(iss::arch_if* arch_if_ptr, uint32_t call_number, uint32_t parameter); diff --git a/src/iss/semihosting/semihosting.h b/src/iss/semihosting/semihosting.h index ea6a5c6..e551f78 100644 --- a/src/iss/semihosting/semihosting.h +++ b/src/iss/semihosting/semihosting.h @@ -7,7 +7,7 @@ * https://static.docs.arm.com/100863/0200/semihosting.pdf * from ARM Ltd. * - * The available semihosting operation numbers passed in R0 are allocated + * The available semihosting operation numbers passed in A0 are allocated * as follows: * - 0x00-0x31 Used by ARM. * - 0x32-0xFF Reserved for future use by ARM. @@ -18,38 +18,34 @@ * - 0x200-0xFFFFFFFF Undefined and currently unused. It is recommended * that you do not use these. */ -enum semihosting_operation_numbers { - /* - * ARM semihosting operations, in lexicographic order. - */ - SEMIHOSTING_ENTER_SVC = 0x17, /* DEPRECATED */ +enum class semihosting_syscalls { - SEMIHOSTING_SYS_CLOCK = 0x10, - SEMIHOSTING_SYS_CLOSE = 0x02, - SEMIHOSTING_SYS_ELAPSED = 0x30, - SEMIHOSTING_SYS_ERRNO = 0x13, - SEMIHOSTING_SYS_EXIT = 0x18, - SEMIHOSTING_SYS_EXIT_EXTENDED = 0x20, - SEMIHOSTING_SYS_FLEN = 0x0C, - SEMIHOSTING_SYS_GET_CMDLINE = 0x15, - SEMIHOSTING_SYS_HEAPINFO = 0x16, - SEMIHOSTING_SYS_ISERROR = 0x08, - SEMIHOSTING_SYS_ISTTY = 0x09, - SEMIHOSTING_SYS_OPEN = 0x01, - SEMIHOSTING_SYS_READ = 0x06, - SEMIHOSTING_SYS_READC = 0x07, - SEMIHOSTING_SYS_REMOVE = 0x0E, - SEMIHOSTING_SYS_RENAME = 0x0F, - SEMIHOSTING_SYS_SEEK = 0x0A, - SEMIHOSTING_SYS_SYSTEM = 0x12, - SEMIHOSTING_SYS_TICKFREQ = 0x31, - SEMIHOSTING_SYS_TIME = 0x11, - SEMIHOSTING_SYS_TMPNAM = 0x0D, - SEMIHOSTING_SYS_WRITE = 0x05, - SEMIHOSTING_SYS_WRITEC = 0x03, - SEMIHOSTING_SYS_WRITE0 = 0x04, - SEMIHOSTING_USER_CMD_0x100 = 0x100, /* First user cmd op code */ - SEMIHOSTING_USER_CMD_0x1FF = 0x1FF, /* Last user cmd op code */ + SYS_OPEN = 0x01, + SYS_CLOSE = 0x02, + SYS_WRITEC = 0x03, + SYS_WRITE0 = 0x04, + SYS_WRITE = 0x05, + SYS_READ = 0x06, + SYS_READC = 0x07, + SYS_ISERROR = 0x08, + SYS_ISTTY = 0x09, + SYS_SEEK = 0x0A, + SYS_FLEN = 0x0C, + SYS_TMPNAM = 0x0D, + SYS_REMOVE = 0x0E, + SYS_RENAME = 0x0F, + SYS_CLOCK = 0x10, + SYS_TIME = 0x11, + SYS_SYSTEM = 0x12, + SYS_ERRNO = 0x13, + SYS_GET_CMDLINE = 0x15, + SYS_HEAPINFO = 0x16, + SYS_EXIT = 0x18, + SYS_EXIT_EXTENDED = 0x20, + SYS_ELAPSED = 0x30, + SYS_TICKFREQ = 0x31, + USER_CMD_0x100 = 0x100, + USER_CMD_0x1FF = 0x1FF, }; template void semihosting_callback(iss::arch_if* arch_if_ptr, T call_number, T parameter);