- In
a0= Integer to print- From C
void sim_print_int(int value)
RISC-V Syscalls
Making a syscall
Files and folders
Sound
Program arguments
Print integer
a7 = 1Print float
a7 = 2- In
fa0= Float to print- From C
void sim_print_float(float value)
Print double
a7 = 3- In
fa0= Double to print- From C
void sim_print_double(double value)
Print string
a7 = 4- In
a0= Address of NUL-terminated UTF-8 string to print- From C
void sim_print_string(const char *text)
Read integer
a7 = 5- Out
a0= Contains the integer parsed from the input line- Note
- Waits for a line typed at the keyboard in the Terminal and Enter, or reads scripted input in a Testcase. Trims surrounding whitespace and parses it as an integer. Invalid input stops the program with an input error.
- From C
int sim_read_int(void)
Read float
a7 = 6- Out
fa0= Contains the floating-point value parsed from the input line- Note
- Waits for a line typed at the keyboard in the Terminal and Enter, or reads scripted input in a Testcase. Trims surrounding whitespace and parses it as a floating-point value. Invalid input stops the program with an input error.
- From C
float sim_read_float(void)
Read double
a7 = 7- Out
fa0= Contains the double-precision value parsed from the input line- Note
- Waits for a line typed at the keyboard in the Terminal and Enter, or reads scripted input in a Testcase. Trims surrounding whitespace and parses it as a double-precision value. Invalid input stops the program with an input error.
- From C
double sim_read_double(void)
Read string
a7 = 8- In
a0= Address of input buffer;a1= Size of input buffer in bytes- Out
- Writes memory at the address in
a0. - Note
- Waits for a line typed at the keyboard in the Terminal and Enter, or reads scripted input in a Testcase. Stores UTF-8 with fgets-style limits: for buffer size n, writes at most n-1 bytes, adds a newline if there is room, then a NUL byte. Truncation can split a multibyte character. If n = 1, ignores input and writes only NUL; if n < 1, ignores input and writes nothing.
- From C
void sim_read_string(char *buffer, int size)
Sbrk (allocate heap memory)
a7 = 9- In
a0= Number of bytes to allocate- Out
a0= Contains address of allocated memory- Note
- The heap ends at 0x14000000, 64 MB from the data segment, where RARS stops at 0x10400000; asking for more stops execution with a runtime error.
- From C
void *sim_sbrk(int bytes)
Exit (terminate execution)
a7 = 10- Note
- Ends the program successfully with exit code 0.
- From C
void sim_exit(void)
Print character
a7 = 11- In
a0= Character to print- Note
- Prints the ASCII character whose code is in the low-order byte.
- From C
void sim_print_char(int character)
Read character
a7 = 12- Out
a0= Contains the input character code- Note
- Waits for one key in the Terminal and completes immediately; Enter returns 10. A Testcase supplies scripted input.
- From C
int sim_read_char(void)
Get cwd
a7 = 17- In
a0= Address of the buffer to write the path into;a1= Length of the buffer- Out
a0= Contains -1 if the path and its terminating null do not fit in the buffer, and is left unchanged otherwise; Writes memory at the address ina0.- Note
- Writes /, the top folder, followed by a null byte: the current folder is always the top folder. The minimum buffer size is 2.
- From C
int sim_get_cwd(char *buffer, int size)
Time (program time)
a7 = 30- Out
a0= Low order 32 bits of the program time;a1= High order 32 bits of the program time- Note
- Returns milliseconds since 1970-01-01 UTC. In a Testcase, calendar time starts at 2000-01-01 UTC and advances through waits of service 32. The time CSR (and timeh in RV32) reads this same clock. Undo restores recorded register and CSR readings.
- From C
long long sim_time(void)
MIDI out
a7 = 31- In
a0= Pitch, 0 to 127: 60 is middle C, 62 is D, 64 is E; each step is one semitone;a1= Duration in milliseconds;a2= Instrument sound from the General MIDI list, numbered from 0 to 127: 0 piano, 40 violin, 56 trumpet, 73 flute;a3= Volume, 0 (silent) to 127 (loudest)- Note
- Plays a note and continues immediately, allowing notes to overlap. Values outside 0 to 127 use these defaults: invalid pitch becomes 60 (middle C), invalid instrument becomes 0 (piano), and invalid volume becomes 100. A negative duration becomes 1000 milliseconds, as in RARS. The first note or MIDI-file request after opening or reloading the editor page waits while the browser loads the sound bank, the collection of instrument sounds; later runs share it. At most 64 notes sound at once, where RARS has no limit: starting another stops the oldest. Notes finish their duration after the program exits. Testcases are silent.
- From C
void sim_midi_out(int pitch, int duration, int instrument, int volume)
Sleep
a7 = 32- In
a0= The length of time to sleep in milliseconds- Note
- Service 32 - Lets that much program time pass before the next instruction. The editor stays responsive while it waits and the wait costs no instructions, so a program idling on the keyboard never reaches the execution limit; in a testcase it completes at once and advances the virtual clock read by service 30 and the time CSR (timeh in RV32) instead.
- From C
void sim_sleep(int milliseconds)
MIDI out synchronous
a7 = 33- In
a0= Pitch, 0 to 127: 60 is middle C, 62 is D, 64 is E; each step is one semitone;a1= Duration in milliseconds;a2= Instrument sound from the General MIDI list, numbered from 0 to 127: 0 piano, 40 violin, 56 trumpet, 73 flute;a3= Volume, 0 (silent) to 127 (loudest)- Note
- Plays a note with the same argument defaults as service 31, then waits for the requested duration before the next instruction. A sequence of these calls can play a melody. Muting or stopping the audible note does not shorten the wait. Testcases are silent; the wait completes immediately and advances the virtual clock by the duration.
- From C
void sim_midi_out_sync(int pitch, int duration, int instrument, int volume)
Print integer in hexadecimal
a7 = 34- In
a0= Integer to print- Note
- Displayed value is 8 hexadecimal digits, left-padding with zeroes if necessary.
- From C
void sim_print_hex(int value)
Print integer in binary
a7 = 35- In
a0= Integer to print- Note
- Displayed value is 32 bits, left-padding with zeroes if necessary.
- From C
void sim_print_binary(int value)
Print integer as unsigned
a7 = 36- In
a0= Integer to print- Note
- Displayed as unsigned decimal value.
- From C
void sim_print_unsigned(unsigned value)
Set seed
a7 = 40- In
a0= Generator ID: any integer selects an independent pseudorandom sequence;a1= Seed for corresponding pseudorandom number generator- Note
- Seeds the generator selected by a0. Each generator ID has an independent sequence. An unseeded ID starts from host randomness in an interactive run and a fixed per-ID seed in a testcase, making testcase runs repeatable. Values follow Java’s
Randomsequence for the same seed. Undo restores the state before a draw or reseed. - From C
void sim_random_seed(int generator, int seed)
Random int
a7 = 41- In
a0= Generator ID: any integer selects an independent pseudorandom sequence- Out
a0= Contains the next pseudorandom, uniformly distributed int value from this random number generator's sequence- Note
- Each generator ID has an independent sequence. An unseeded ID starts from host randomness in an interactive run and a fixed per-ID seed in a testcase, making testcase runs repeatable. Service 40 sets an explicit seed. Values follow Java’s
Randomsequence for the same seed. Undo restores the state before a draw or reseed. - From C
int sim_random_int(int generator)
Random int range
a7 = 42- In
a0= Generator ID: any integer selects an independent pseudorandom sequence;a1= Upper bound of range of returned values- Out
a0= Contains pseudorandom, uniformly distributed int value in the range 0 <= [int] < [upper bound], drawn from this random number generator's sequence- Note
- Each generator ID has an independent sequence. An unseeded ID starts from host randomness in an interactive run and a fixed per-ID seed in a testcase, making testcase runs repeatable. Service 40 sets an explicit seed. Values follow Java’s
Randomsequence for the same seed. Undo restores the state before a draw or reseed. - From C
int sim_random_int_range(int generator, int bound)
Random float
a7 = 43- In
a0= Generator ID: any integer selects an independent pseudorandom sequence- Out
fa0= Contains the next pseudorandom, uniformly distributed float value in the range 0.0 <= f < 1.0 from this random number generator's sequence- Note
- Each generator ID has an independent sequence. An unseeded ID starts from host randomness in an interactive run and a fixed per-ID seed in a testcase, making testcase runs repeatable. Service 40 sets an explicit seed. Values follow Java’s
Randomsequence for the same seed. Undo restores the state before a draw or reseed. - From C
float sim_random_float(int generator)
Random double
a7 = 44- In
a0= Generator ID: any integer selects an independent pseudorandom sequence- Out
fa0= Contains the next pseudorandom, uniformly distributed double value in the range 0.0 <= f < 1.0 from this random number generator's sequence- Note
- Each generator ID has an independent sequence. An unseeded ID starts from host randomness in an interactive run and a fixed per-ID seed in a testcase, making testcase runs repeatable. Service 40 sets an explicit seed. Values follow Java’s
Randomsequence for the same seed. Undo restores the state before a draw or reseed. - From C
double sim_random_double(int generator)
ConfirmDialog
a7 = 50- In
a0= Address of NUL-terminated UTF-8 string that is the message to user- Out
a0= Contains value of user-chosen option 0: Yes 1: No 2: Cancel- From C
int sim_confirm_dialog(const char *message)
InputDialogInt
a7 = 51- In
a0= Address of NUL-terminated UTF-8 string that is the message to user- Out
a0= Contains int read;a1= Contains status value 0: OK status -1: input data cannot be correctly parsed -2: Cancel was chosen -3: OK was chosen but no data had been input into field- From C
int sim_input_dialog_int(const char *message, int *status)
InputDialogFloat
a7 = 52- In
a0= Address of NUL-terminated UTF-8 string that is the message to user- Out
f0= Contains the floating-point value parsed from the input line;a1= Contains status value 0: OK status -1: input data cannot be correctly parsed -2: Cancel was chosen -3: OK was chosen but no data had been input into field- From C
float sim_input_dialog_float(const char *message, int *status)
InputDialogDouble
a7 = 53- In
a0= Address of NUL-terminated UTF-8 string that is the message to user- Out
fa0= Contains the double-precision value parsed from the input line;a1= Contains status value 0: OK status -1: input data cannot be correctly parsed -2: Cancel was chosen -3: OK was chosen but no data had been input into field- From C
double sim_input_dialog_double(const char *message, int *status)
InputDialogString
a7 = 54- In
a0= Address of NUL-terminated UTF-8 string that is the message to user;a1= Address of input buffer;a2= Size of input buffer in bytes- Out
a1= Contains status value 0: OK status. Buffer contains the input string. -2: Cancel was chosen. No change to buffer. -3: OK was chosen but no data had been input into field. No change to buffer. -4: length of the input string exceeded the specified maximum. Buffer contains the maximum allowable input string plus a terminating null.; Writes memory at the address ina1.- Note
- Stores the entered string as UTF-8 in the buffer: at most n-1 bytes for buffer size n, followed by a newline if there is room and a terminating NUL. Truncation can split a multibyte character.
- From C
int sim_input_dialog_string(const char *message, char *buffer, int size)
MessageDialog
a7 = 55- In
a0= Address of NUL-terminated UTF-8 string that is the message to user;a1= The type of message to be displayed: 0: error message, indicated by Error icon 1: information message, indicated by Information icon 2: warning message, indicated by Warning icon 3: question message, indicated by Question icon other: plain message (no icon displayed)- From C
void sim_message_dialog(const char *message, int type)
MessageDialogInt
a7 = 56- In
a0= Address of NUL-terminated UTF-8 string that is an information-type message to user;a1= Int value to display in string form after the first string- From C
void sim_message_dialog_int(const char *message, int value)
Close file
a7 = 57- In
a0= File or folder descriptor to close- From C
void sim_close(int fd)
MessageDialogDouble
a7 = 58- In
a0= Address of NUL-terminated UTF-8 string that is an information-type message to user;fa0= Double value to display in string form after the first string- From C
void sim_message_dialog_double(const char *message, double value)
MessageDialogString
a7 = 59- In
a0= Address of NUL-terminated UTF-8 string that is an information-type message to user;a1= Address of NUL-terminated UTF-8 string to display after the first string- From C
void sim_message_dialog_string(const char *message, const char *text)
MessageDialogFloat
a7 = 60- In
a0= Address of NUL-terminated UTF-8 string that is an information-type message to user;fa1= Float value to display in string form after the first string- From C
void sim_message_dialog_float(const char *message, float value)
Lseek (move file position)
a7 = 62- In
a0= File descriptor;a1= Offset in bytes;a2= Where the offset counts from: 0 the start of the file, 1 the current position, 2 the end of the file- Out
a0= Contains the new position, counted from the beginning of the file (-1 if error)- Note
- Descriptors 0, 1, and 2 (standard input, output, and error) cannot be repositioned.
- From C
int sim_lseek(int fd, int offset, int whence)
Read from file
a7 = 63- In
a0= File descriptor;a1= Address of the buffer to fill;a2= Maximum number of bytes to read- Out
a0= Number of bytes read, 0 at end of file or input, or -1 on failure; Writes memory at the address ina1.- Note
- Reads up to the requested number of bytes into the buffer, without adding a string terminator. Returns the byte count, 0 at the end of the file or input, or -1 on failure. Descriptor 0 reads standard input from the Terminal. Enter a line and press Enter. Ctrl+D or End of input on an empty line ends standard input. In a Testcase, input ends when the scripted answers run out. See Files and folders for Undo and Testcase behavior.
- From C
int sim_read(int fd, void *buffer, int length)
Write to file
a7 = 64- In
a0= File descriptor;a1= Address of the bytes to write;a2= Number of bytes to write- Out
a0= Number of bytes written, or -1 on failure- Note
- Writes the requested bytes to an open file. Descriptors 1 and 2 write to the Terminal as standard output and standard error. Returns the number of bytes written or -1 on failure. See Files and folders for Undo and Testcase behavior.
- From C
int sim_write(int fd, const void *buffer, int length)
Exit2 (terminate with value)
a7 = 93- In
a0= Termination result- Note
- Ends the program with the signed exit code in a0. The editor shows this code in the Log.
- From C
void sim_exit2(int code)
Open file
a7 = 1024- In
a0= Address of NUL-terminated UTF-8 path;a1= Flags;a2= Mode (ignored, pass 0)- Out
a0= File or folder descriptor, or -1 on failure- Note
- Opens a file and returns its descriptor, the number used by later read, write and close calls. | Flag | Access | Effect on the file | | ---- | ------ | ------------------ | | 0 | Read | Requires an existing file. | | 1 | Write | Creates a file or empties an existing one. | | 9 | Write, append | Creates a file if needed. Writes go to its end. | | 2 | Read and write | Requires an existing file. | | 3 | Read and write | Creates a file or empties an existing one. | | 10 | Read and write, append | Creates a file if needed. Writes go to its end. | Flags 2, 3 and 10 are editor extensions. Reads and writes on the same descriptor share one file position. Flag 0 can also open a folder for listing with service 1065; folders cannot be opened for writing. The mode argument is ignored. Descriptors 0, 1 and 2 are reserved for standard input, standard output and standard error. Opened files and folders receive descriptors starting at 3. Failure returns -1. See Files and folders for paths, persistence, Undo and Testcase behavior.
- From C
int sim_open(const char *path, int flags, int mode)
Unlink (delete a file)
a7 = 1026- In
a0= Address of NUL-terminated UTF-8 path of the file to delete- Out
a0= 0 on success, or a negative error number- Note
- Deletes the file at the path. Returns -2 if the path does not exist or -21 if it names a folder. To delete an empty folder, use rmdir. The shared file rules describe errors, Undo and Testcases.
- From C
int sim_unlink(const char *path)
Mkdir (make a folder)
a7 = 1030- In
a0= Address of NUL-terminated UTF-8 path of the new folder- Out
a0= 0 on success, or a negative error number- Note
- Creates an empty folder. Its parent must already exist: -2 means a missing parent and -20 means a file was used as a folder. Returns -17 if a file or folder already occupies the requested path. Before treating -17 as success, use stat to confirm that the existing path is a folder.
The new folder lasts for the current run. It remains afterward only if a file still exists inside it, directly or in a subfolder. An empty
.keepfile is enough. See Files and folders for the full lifetime, Undo and Testcase rules. - From C
int sim_mkdir(const char *path)
Rmdir (delete an empty folder)
a7 = 1031- In
a0= Address of NUL-terminated UTF-8 path of the folder to delete- Out
a0= 0 on success, or a negative error number- Note
- Deletes an empty folder. Returns -39 if it contains a file or subfolder, -20 if the path names a file, or -2 if it does not exist. The top folder cannot be deleted (-16). See the shared file rules for folder lifetime, Undo and Testcases.
- From C
int sim_rmdir(const char *path)
Rename (rename or move a file)
a7 = 1034- In
a0= Address of NUL-terminated UTF-8 path of the file;a1= Address of the NUL-terminated UTF-8 destination path- Out
a0= 0 on success, or a negative error number- Note
- Renames a file or moves it into another folder. The destination folder must exist (-2 if missing, -20 if a file is used as a folder). An existing destination file is replaced. Renaming a file to its own path does nothing. Folders cannot be moved: a folder as the source or destination returns -21, except that a folder onto an existing file returns -20. Renaming a folder to itself does nothing. The top folder cannot be renamed. See the shared file rules for Undo and Testcases.
- From C
int sim_rename(const char *from, const char *to)
Stat (describe a path)
a7 = 1038- In
a0= Address of NUL-terminated UTF-8 path;a1= Address of a buffer of 104 bytes in RV32 and 128 in RV64, which the service fills- Out
a0= 0 on success, or a negative error number; Writes memory at the address ina1.- Note
- Reports the type and size of the path in the Linux
struct statlayout for this target. The buffer must hold 104 bytes in RV32 or 128 in RV64. Fields are little-endian: | Field | Byte offset in RV32 and RV64 | Size in bytes | | ----- | --------------------------- | ------------- | | Inode number | 8 | 8 | | Mode | 16 | 4 | | Link count | 20 | 4 | | File size | 48 | 8 | The type bitsmode & 0xF000are0x4000for a folder or0x8000for a file. File size counts bytes. A folder has size 0. The inode number identifies the entry throughout the run. Link count is 1, and all other fields, including times and owners, are 0. Returns -2 for a missing path or -20 if the path uses a file as a folder. From C,stat()in<sys/stat.h>accesses these fields by name. - From C
int sim_stat(const char *path, void *buffer)
Getdents (list a folder)
a7 = 1065- In
a0= File descriptor of a folder, opened with service 1024 and flag 0;a1= Address of the buffer to fill;a2= Size of the buffer in bytes- Out
a0= Number of bytes stored, 0 at the end of the listing, or a negative error number; Writes memory at the address ina1.- Note
- Lists the entries present when the folder was opened:
.and..first, then files and subfolders in name order. It fills the buffer with complete records and returns their total byte count. Call again to continue. A return value of 0 means every entry has been listed. Each record has this little-endian layout: | Field | RV32 byte offset | RV64 byte offset | Size in bytes | | ----- | ---------------- | ---------------- | ------------- | | Inode number | 0 | 0 | 4 in RV32, 8 in RV64 | | Position of next entry | 4 | 8 | 4 in RV32, 8 in RV64 | | Record length | 8 | 16 | 2 | | NUL-terminated UTF-8 name | 10 | 18 | Variable | The record length includes padding and a final type byte: 4 for a folder, 8 for a file. Add that length to the record address to find the next record. The next-entry position counts entries, not bytes. Returns -22 if the buffer cannot hold the next record, -9 if the descriptor is not open, or -20 if it belongs to a file. Reading a folder with service 63 returns -1. Close it with service 57. From C,opendir()andreaddir()in<dirent.h>handle these records for you. - From C
int sim_getdents(int fd, void *buffer, int length)