diff --git a/amach.awk b/amach.awk index f554170..c007251 100644 --- a/amach.awk +++ b/amach.awk @@ -10,11 +10,7 @@ # fatal error reporting function function trapout(msg, fd) { - for(fd in FD_PATH) { - if(FD_DIRTY[fd]) { - write_fd_to_file(fd) - } - } + for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd) cmd = "cat 1>&2" printf("Fatal: %s\n", msg) | cmd close(cmd) @@ -95,15 +91,15 @@ function qquote(str) { function hex_to_dec(hex, dec, i, len, c, val) { dec = 0 len = length(hex) - for (i = 1; i <= len; i++) { + for(i = 1; i <= len; i++) { c = tolower(substr(hex, i, 1)) - if (c ~ /[0-9]/) val = int(c) - else if (c == "a") val = 10 - else if (c == "b") val = 11 - else if (c == "c") val = 12 - else if (c == "d") val = 13 - else if (c == "e") val = 14 - else if (c == "f") val = 15 + if(c ~ /[0-9]/) val = int(c) + else if(c == "a") val = 10 + else if(c == "b") val = 11 + else if(c == "c") val = 12 + else if(c == "d") val = 13 + else if(c == "e") val = 14 + else if(c == "f") val = 15 else continue dec = dec * 16 + val } @@ -114,9 +110,7 @@ function hex_to_dec(hex, dec, i, len, c, val) { function read_str(addr, c, s) { s = "" addr = uint32(addr) - while ((c = MEM[addr++]) != 0) { - s = s sprintf("%c", c) - } + while((c = MEM[addr++]) != 0) s = s sprintf("%c", c) return s } @@ -126,21 +120,13 @@ function path_exists(path) { } # Checks if path is a directory using POSIX test -d -function is_dir(path) { - return (system("test -d " qquote(path)) == 0) -} +function is_dir(path) {return (system("test -d " qquote(path)) == 0)} # Resolves relative path against dfd directory function resolve_path(dfd, pathname, path) { - if (substr(pathname, 1, 1) == "/") { - return pathname - } - if (dfd == -100) { # AT_FDCWD - return pathname - } - if (dfd in FD_PATH) { - return FD_PATH[dfd] "/" pathname - } + if(substr(pathname, 1, 1) == "/") return pathname + if(dfd == -100) return pathname + if(dfd in FD_PATH) return FD_PATH[dfd] "/" pathname return pathname } @@ -148,8 +134,8 @@ function resolve_path(dfd, pathname, path) { # TV_SEC: 64-bit for clock_gettime64, 32-bit for clock_gettime function get_system_time(time_arr, cmd, line) { cmd = "date +%s%N" - if ((cmd | getline line) > 0) { - if (length(line) > 9 && line ~ /^[0-9]+$/) { + if((cmd | getline line) > 0) { + if(length(line) > 9 && line ~ /^[0-9]+$/) { time_arr["sec"] = int(substr(line, 1, length(line) - 9)) time_arr["nsec"] = int(substr(line, length(line) - 8)) close(cmd) @@ -160,16 +146,13 @@ function get_system_time(time_arr, cmd, line) { # Fallback if %N is not supported cmd = "date +%s" - if ((cmd | getline line) > 0) { + if((cmd | getline line) > 0) { time_arr["sec"] = int(line) - } else { - time_arr["sec"] = 0 - } + } else time_arr["sec"] = 0 close(cmd) - - if (time_arr["sec"] == LAST_SEC) { + if(time_arr["sec"] == LAST_SEC) { VIRT_NSEC += 500000 - if (VIRT_NSEC >= 1000000000) { + if(VIRT_NSEC >= 1000000000) { VIRT_NSEC = 999999999 } } else { @@ -183,7 +166,7 @@ function get_system_time(time_arr, cmd, line) { function fill_stat_struct(path, addr, follow, cmd, line, parts, opt, mode_hex, mode_dec, size, atime, mtime, ctime, i) { opt = follow ? "-L " : "" cmd = "stat " opt "-c \"%f %s %X %Y %Z\" " qquote(path) - if ((cmd | getline line) > 0) { + if((cmd | getline line) > 0) { split(line, parts) mode_hex = parts[1] mode_dec = hex_to_dec(mode_hex) @@ -191,12 +174,9 @@ function fill_stat_struct(path, addr, follow, cmd, line, parts, opt, mode_hex, atime = int(parts[3]) mtime = int(parts[4]) ctime = int(parts[5]) - close(cmd) - for (i = 0; i < 104; i++) { - MEM[addr + i] = 0 - } + for(i = 0; i < 104; i++) MEM[addr + i] = 0 write_mem(addr + 0, 1, 8) write_mem(addr + 8, 1, 8) @@ -226,96 +206,80 @@ function write_fd_to_file(fd, path, chunk, i, size) { printf("") > path close(path) chunk = "" - for (i = 0; i < size; i++) { + for(i = 0; i < size; i++) { chunk = chunk sprintf("%c", FD_DATA[fd, i]) - if (length(chunk) >= 1024) { + if(length(chunk) >= 1024) { printf("%s", chunk) >> path chunk = "" } } - if (length(chunk) > 0) { - printf("%s", chunk) >> path - } + if(length(chunk) > 0) printf("%s", chunk) >> path close(path) } function amach_exit(code, fd) { - for (fd in FD_PATH) { - if (FD_DIRTY[fd]) { - write_fd_to_file(fd) - } - } + for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd) exit(code) } # syscall emulation function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathname, flags, fd, count, now_time, dtype, full_path, reclen, bytes_written, idx, count_limit, buf_addr, name, status, follow, oldpath, newpath, access_mode, is_read, is_write, do_trunc, cmd, line, arr, size, buflen) { - if (callnum == 34) { # sys_mkdirat + if(callnum == 34) { # sys_mkdirat pathname = read_str(a1) path = resolve_path(a0, pathname) - if (path_exists(path)) { - setreg(10, -17) # -EEXIST - } else { + if(path_exists(path)) setreg(10, -17) # -EEXIST + else { status = system("mkdir " qquote(path)) setreg(10, (status == 0) ? 0 : -2) } - - } else if (callnum == 35) { # sys_unlinkat + } else if(callnum == 35) { # sys_unlinkat pathname = read_str(a1) path = resolve_path(a0, pathname) - if (!path_exists(path)) { + if(!path_exists(path)) { setreg(10, -2) # -ENOENT } else { - if (bw_and(a2, 512)) { # AT_REMOVEDIR (0x200) + if(bw_and(a2, 512)) # AT_REMOVEDIR (0x200) status = system("rmdir " qquote(path)) - } else { + else status = system("rm " qquote(path)) - } setreg(10, (status == 0) ? 0 : -1) - } - - } else if (callnum == 38 || callnum == 276) { # sys_renameat / sys_renameat2 + } + } else if(callnum == 38 || callnum == 276) { # sys_renameat / sys_renameat2 oldpath = resolve_path(a0, read_str(a1)) newpath = resolve_path(a2, read_str(a3)) status = system("mv " qquote(oldpath) " " qquote(newpath)) setreg(10, (status == 0) ? 0 : -1) - - } else if (callnum == 56) { # sys_openat + } else if(callnum == 56) { # sys_openat pathname = read_str(a1) path = resolve_path(a0, pathname) flags = a2 - if (bw_and(flags, 64)) { # O_CREAT (0x40) - if (bw_and(flags, 128) && path_exists(path)) { # O_EXCL (0x80) + if(bw_and(flags, 64)) { # O_CREAT (0x40) + if(bw_and(flags, 128) && path_exists(path)) { # O_EXCL (0x80) setreg(10, -17) # -EEXIST return } - if (!path_exists(path)) { + if(!path_exists(path)) { printf("") > path close(path) } } else { - if (!path_exists(path)) { + if(!path_exists(path)) { setreg(10, -2) # -ENOENT return } } - fd = NEXT_FD++ FD_PATH[fd] = path FD_FLAGS[fd] = flags FD_OFFSET[fd] = 0 FD_SIZE[fd] = 0 FD_DIRTY[fd] = 0 - - if (is_dir(path)) { + if(is_dir(path)) { cmd = "ls -a1 " qquote(path) count = 0 - while ((cmd | getline line) > 0) { - if (line != "") { - FD_DIRENTS[fd, count++] = line - } - } + while((cmd | getline line) > 0) + if(line != "") FD_DIRENTS[fd, count++] = line close(cmd) FD_DIRENT_COUNT[fd] = count } else { @@ -324,64 +288,51 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathnam is_write = (access_mode == 1 || access_mode == 2) do_trunc = (is_write && bw_and(flags, 512)) # O_TRUNC (0x200) - if (is_read && !do_trunc) { + if(is_read && !do_trunc) { cmd = "od -An -v -tu1 " qquote(path) size = 0 - while ((cmd | getline line) > 0) { + while((cmd | getline line) > 0) { split(line, arr) - for (i = 1; i in arr; i++) { + for(i = 1; i in arr; i++) FD_DATA[fd, size++] = arr[i] - } } close(cmd) FD_SIZE[fd] = size - } else if (do_trunc) { + } else if(do_trunc) { printf("") > path close(path) } } setreg(10, fd) - } else if (callnum == 57) { # sys_close + } else if(callnum == 57) { # sys_close fd = a0 - if (fd >= 3 && (fd in FD_PATH)) { - if (FD_DIRTY[fd]) { - write_fd_to_file(fd) - } + if(fd >= 3 && (fd in FD_PATH)) { + if(FD_DIRTY[fd]) write_fd_to_file(fd) delete FD_PATH[fd] delete FD_FLAGS[fd] delete FD_OFFSET[fd] delete FD_SIZE[fd] delete FD_DIRTY[fd] - if (fd in FD_DIRENT_COUNT) { - for (i = 0; i < FD_DIRENT_COUNT[fd]; i++) { - delete FD_DIRENTS[fd, i] - } + if(fd in FD_DIRENT_COUNT) { + for(i = 0; i < FD_DIRENT_COUNT[fd]; i++) delete FD_DIRENTS[fd, i] delete FD_DIRENT_COUNT[fd] - } else { - for (i = 0; i < FD_SIZE[fd]; i++) { - delete FD_DATA[fd, i] - } - } + } else for(i = 0; i < FD_SIZE[fd]; i++) delete FD_DATA[fd, i] setreg(10, 0) - } else { - setreg(10, -9) # -EBADF - } - - } else if (callnum == 61) { # sys_getdents64 + } else setreg(10, -9) # -EBADF + } else if(callnum == 61) { # sys_getdents64 fd = a0 - if (!(fd in FD_DIRENT_COUNT)) { - setreg(10, -9) # -EBADF - } else { + if(!(fd in FD_DIRENT_COUNT)) setreg(10, -9) # -EBADF + else { bytes_written = 0 idx = FD_OFFSET[fd] count_limit = a2 buf_addr = a1 - while (idx < FD_DIRENT_COUNT[fd]) { + while(idx < FD_DIRENT_COUNT[fd]) { name = FD_DIRENTS[fd, idx] reclen = int((20 + length(name) + 7) / 8) * 8 - if (bytes_written + reclen > count_limit) { - if (bytes_written == 0) { + if(bytes_written + reclen > count_limit) { + if(bytes_written == 0) { setreg(10, -22) # -EINVAL return } @@ -393,143 +344,116 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathnam full_path = FD_PATH[fd] "/" name dtype = is_dir(full_path) ? 4 : 8 write_mem(buf_addr + bytes_written + 18, dtype, 1) - for (i = 0; i < length(name); i++) { + for(i = 0; i < length(name); i++) MEM[buf_addr + bytes_written + 19 + i] = ord(substr(name, i + 1, 1)) - } MEM[buf_addr + bytes_written + 19 + length(name)] = 0 - for (i = 19 + length(name) + 1; i < reclen; i++) { + for(i = 19 + length(name) + 1; i < reclen; i++) MEM[buf_addr + bytes_written + i] = 0 - } bytes_written += reclen idx++ } FD_OFFSET[fd] = idx setreg(10, bytes_written) } - - } else if (callnum == 62) { # sys_lseek + } else if(callnum == 62) { # sys_lseek fd = a0 - if (fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) { + if(fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) { idx = FD_OFFSET[fd] size = FD_SIZE[fd] - if (a2 == 0) idx = a1 # SEEK_SET - else if (a2 == 1) idx = idx + a1 # SEEK_CUR - else if (a2 == 2) idx = size + a1 # SEEK_END + if(a2 == 0) idx = a1 # SEEK_SET + else if(a2 == 1) idx = idx + a1 # SEEK_CUR + else if(a2 == 2) idx = size + a1 # SEEK_END else { setreg(10, -22) # -EINVAL return } - if (idx < 0) { - setreg(10, -22) # -EINVAL - } else { + if(idx < 0) setreg(10, -22) # -EINVAL + else { FD_OFFSET[fd] = idx setreg(10, idx) } - } else { - setreg(10, -9) # -EBADF - } - - } else if (callnum == 63) { # sys_read + } else setreg(10, -9) # -EBADF + } else if(callnum == 63) { # sys_read fd = a0 - if (fd == 0) { + if(fd == 0) { getline buf < "/dev/tty" - l = length(buf); if (l > a2) l = a2 - for (i = 0; i < l; i++) MEM[uint32(a1 + i)] = ord(substr(buf, i + 1, 1)) + l = length(buf); if(l > a2) l = a2 + for(i = 0; i < l; i++) MEM[uint32(a1 + i)] = ord(substr(buf, i + 1, 1)) setreg(10, l) - } else if (fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) { + } else if(fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) { idx = FD_OFFSET[fd] size = FD_SIZE[fd] count = a2 - if (idx >= size) { - setreg(10, 0) - } else { - if (idx + count > size) count = size - idx - for (i = 0; i < count; i++) { + if(idx >= size) setreg(10, 0) + else { + if(idx + count > size) count = size - idx + for(i = 0; i < count; i++) MEM[uint32(a1 + i)] = FD_DATA[fd, idx + i] - } FD_OFFSET[fd] = idx + count setreg(10, count) } - } else { - setreg(10, -9) # -EBADF - } - - } else if (callnum == 64) { # sys_write + } else setreg(10, -9) # -EBADF + } else if(callnum == 64) { # sys_write fd = a0 - if (fd == 1 || fd == 2) { - for (i = 0; i < a2; i++) printf("%c", MEM[uint32(a1 + i)]) + if(fd == 1 || fd == 2) { + for(i = 0; i < a2; i++) printf("%c", MEM[uint32(a1 + i)]) setreg(10, a2) - } else if (fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) { + } else if(fd >= 3 && (fd in FD_PATH) && !(fd in FD_DIRENT_COUNT)) { idx = FD_OFFSET[fd] count = a2 - if (bw_and(FD_FLAGS[fd], 1024)) { # O_APPEND (0x400) - idx = FD_SIZE[fd] - } - for (i = 0; i < count; i++) { + if(bw_and(FD_FLAGS[fd], 1024)) idx = FD_SIZE[fd] # O_APPEND (0x400) + for(i = 0; i < count; i++) FD_DATA[fd, idx + i] = MEM[uint32(a1 + i)] - } FD_OFFSET[fd] = idx + count - if (FD_OFFSET[fd] > FD_SIZE[fd]) { - FD_SIZE[fd] = FD_OFFSET[fd] - } + if(FD_OFFSET[fd] > FD_SIZE[fd]) FD_SIZE[fd] = FD_OFFSET[fd] FD_DIRTY[fd] = 1 setreg(10, count) - } else { - setreg(10, -9) # -EBADF - } - - } else if (callnum == 78) { # sys_readlinkat + } else setreg(10, -9) # -EBADF + } else if(callnum == 78) { # sys_readlinkat path = resolve_path(a0, read_str(a1)) cmd = "readlink " qquote(path) - if ((cmd | getline line) > 0) { + if((cmd | getline line) > 0) { close(cmd) l = length(line) - if (l > a3) l = a3 - for (i = 0; i < l; i++) { + if(l > a3) l = a3 + for(i = 0; i < l; i++) MEM[uint32(a2 + i)] = ord(substr(line, i + 1, 1)) - } setreg(10, l) } else { close(cmd) setreg(10, -22) # -EINVAL } - - } else if (callnum == 79) { # sys_newfstatat + } else if(callnum == 79) { # sys_newfstatat pathname = read_str(a1) flags = a3 - if (pathname == "" && bw_and(flags, 4096)) { # AT_EMPTY_PATH - if (a0 == -100) path = "." - else if (a0 in FD_PATH) path = FD_PATH[a0] + if(pathname == "" && bw_and(flags, 4096)) { # AT_EMPTY_PATH + if(a0 == -100) path = "." + else if(a0 in FD_PATH) path = FD_PATH[a0] else { setreg(10, -9) # -EBADF return } - } else { - path = resolve_path(a0, pathname) - } + } else path = resolve_path(a0, pathname) follow = (bw_and(flags, 256) == 0) # follow link if AT_SYMLINK_NOFOLLOW (0x100) is NOT set status = fill_stat_struct(path, a2, follow) - setreg(10, status) - - } else if (callnum == 80) { # sys_fstat + setreg(10, status) + } else if(callnum == 80) { # sys_fstat fd = a0 - if (fd == 0) path = "/dev/stdin" - else if (fd == 1) path = "/dev/stdout" - else if (fd == 2) path = "/dev/stderr" - else if (fd >= 3 && (fd in FD_PATH)) path = FD_PATH[fd] + if(fd == 0) path = "/dev/stdin" + else if(fd == 1) path = "/dev/stdout" + else if(fd == 2) path = "/dev/stderr" + else if(fd >= 3 && (fd in FD_PATH)) path = FD_PATH[fd] else { setreg(10, -9) # -EBADF return } status = fill_stat_struct(path, a1, 1) setreg(10, status) - - } else if (callnum == 93 || callnum == 94) { # sys_exit / sys_exit_group + } else if(callnum == 93 || callnum == 94) { # sys_exit / sys_exit_group amach_exit(a0) - - } else if (callnum == 113 || callnum == 403) { # sys_clock_gettime / sys_clock_gettime64 + } else if(callnum == 113 || callnum == 403) { # sys_clock_gettime / sys_clock_gettime64 get_system_time(now_time) - if (callnum == 113) { + if(callnum == 113) { write_mem(a1, now_time["sec"], 4) write_mem(a1 + 4, now_time["nsec"], 4) } else { @@ -537,24 +461,18 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, l, buf, path, pathnam write_mem(a1 + 8, now_time["nsec"], 4) } setreg(10, 0) - - } else if (callnum == 169) { # sys_gettimeofday + } else if(callnum == 169) { # sys_gettimeofday get_system_time(now_time) write_mem(a0, now_time["sec"], 4) write_mem(a0 + 4, int(now_time["nsec"] / 1000), 4) setreg(10, 0) - - } else if (callnum == 278) { # sys_getrandom + } else if(callnum == 278) { # sys_getrandom buf_addr = a0 buflen = a1 - for (i = 0; i < buflen; i++) { + for(i = 0; i < buflen; i++) MEM[uint32(buf_addr + i)] = int(rand() * 256) - } setreg(10, buflen) - - } else { - trapout(sprintf("Unimplemented environment call %d at 0x%X", callnum, pc - 4)) - } + } else trapout(sprintf("Unimplemented environment call %d at 0x%X", callnum, pc - 4)) } # instruction type executors @@ -861,9 +779,5 @@ END { instr += 65536 * MEM[pc++] + 16777216 * MEM[pc++] amach_exec(instr) # decode and execute } - for(fd in FD_PATH) { - if(FD_DIRTY[fd]) { - write_fd_to_file(fd) - } - } + for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd) } diff --git a/rv32imac_syscall_tests.bin b/rv32imac_syscall_tests.bin deleted file mode 100755 index 2488bbb..0000000 Binary files a/rv32imac_syscall_tests.bin and /dev/null differ diff --git a/rv32imac_syscall_tests.s b/rv32imac_syscall_tests.s new file mode 100644 index 0000000..c770e69 --- /dev/null +++ b/rv32imac_syscall_tests.s @@ -0,0 +1,302 @@ +.section .text +.option norvc +.global _start + +# Helper macro to exit with code if condition fails +# Example: ASSERT_EQ a0, 0, 4 (if a0 != 0, exit with code 4) +.macro ASSERT_EQ reg, val, error_code + li t4, \val + beq \reg, t4, .L_ok_\@ + li a0, \error_code + li a7, 93 + ecall +.L_ok_\@: +.endm + +# Helper macro to exit with code if registers are not equal +.macro ASSERT_REG_EQ reg1, reg2, error_code + beq \reg1, \reg2, .L_ok_reg_\@ + li a0, \error_code + li a7, 93 + ecall +.L_ok_reg_\@: +.endm + +# Helper macro to exit with code if a register is negative +.macro ASSERT_GEZ reg, error_code + bgez \reg, .L_ok_gez_\@ + li a0, \error_code + li a7, 93 + ecall +.L_ok_gez_\@: +.endm + +_start: + # 1. Write welcome message to stdout + li a7, 64 # sys_write + li a0, 1 # stdout + la a1, msg_welcome + li a2, 29 # welcome message length + ecall + ASSERT_EQ a0, 29, 1 + + # 2. Test clock_gettime + li a7, 113 # sys_clock_gettime + li a0, 0 # CLOCK_REALTIME + la a1, timespec_buf + ecall + ASSERT_EQ a0, 0, 2 + # verify we wrote something non-zero to seconds + lw t0, timespec_buf + ASSERT_GEZ t0, 3 + + # 3. Test gettimeofday + li a7, 169 # sys_gettimeofday + la a0, timeval_buf + li a1, 0 # NULL timezone + ecall + ASSERT_EQ a0, 0, 4 + lw t0, timeval_buf + ASSERT_GEZ t0, 5 + + # 4. Test openat to create file + li a7, 56 # sys_openat + li a0, -100 # AT_FDCWD + la a1, file_name + li a2, 577 # O_CREAT | O_WRONLY | O_TRUNC (64 | 1 | 512 = 577) + li a3, 0644 # permissions + ecall + ASSERT_GEZ a0, 6 + mv s2, a0 # save fd in s2 + + # 5. Write to the new file + li a7, 64 # sys_write + mv a0, s2 # fd + la a1, msg_to_file + li a2, 29 # length + ecall + ASSERT_EQ a0, 29, 7 + + # 6. Close the file + li a7, 57 # sys_close + mv a0, s2 # fd + ecall + ASSERT_EQ a0, 0, 8 + + # 7. Open file O_RDONLY + li a7, 56 # sys_openat + li a0, -100 # AT_FDCWD + la a1, file_name + li a2, 0 # O_RDONLY + li a3, 0 + ecall + ASSERT_GEZ a0, 9 + mv s2, a0 # save fd in s2 + + # 7b. Test fstat + li a7, 80 # sys_fstat + mv a0, s2 # fd + la a1, stat_buf + ecall + ASSERT_EQ a0, 0, 20 + lw t0, stat_buf + 48 + ASSERT_EQ t0, 29, 21 + + # 7c. Test newfstatat + li a7, 79 # sys_newfstatat + li a0, -100 # AT_FDCWD + la a1, file_name + la a2, stat_buf + li a3, 0 # flags + ecall + ASSERT_EQ a0, 0, 22 + lw t0, stat_buf + 48 + ASSERT_EQ t0, 29, 23 + + + # 8. Read from the file + li a7, 63 # sys_read + mv a0, s2 # fd + la a1, read_buf + li a2, 50 # buffer size + ecall + ASSERT_EQ a0, 29, 10 # should read 29 bytes + + # verify read content matches + la t0, msg_to_file + la t1, read_buf + li t2, 0 # index +.L_loop: + add t3, t0, t2 + lb t3, 0(t3) + add t5, t1, t2 + lb t5, 0(t5) + ASSERT_REG_EQ t3, t5, 11 + addi t2, t2, 1 + li t6, 29 + blt t2, t6, .L_loop + + # 9. Close the file + li a7, 57 # sys_close + mv a0, s2 # fd + ecall + ASSERT_EQ a0, 0, 12 + + # 9b. Test renameat (rename test_output.txt to test_output_new.txt) + li a7, 38 # sys_renameat + li a0, -100 # AT_FDCWD + la a1, file_name + li a2, -100 # AT_FDCWD + la a3, file_name_new + ecall + ASSERT_EQ a0, 0, 24 + + # 9c. Verify renamed file can be opened O_RDONLY + li a7, 56 # sys_openat + li a0, -100 # AT_FDCWD + la a1, file_name_new + li a2, 0 # O_RDONLY + li a3, 0 + ecall + ASSERT_GEZ a0, 25 + mv s3, a0 + + # 9d. Close renamed file + li a7, 57 # sys_close + mv a0, s3 + ecall + ASSERT_EQ a0, 0, 26 + + + # 10. Test mkdirat + li a7, 34 # sys_mkdirat + li a0, -100 # AT_FDCWD + la a1, dir_name + li a2, 0755 + ecall + ASSERT_EQ a0, 0, 13 + + # 11. Open directory fd + li a7, 56 # sys_openat + li a0, -100 # AT_FDCWD + la a1, dir_name + li a2, 0 # O_RDONLY + li a3, 0 + ecall + ASSERT_GEZ a0, 14 + mv s2, a0 # save fd in s2 + + # 12. Test getdents64 + li a7, 61 # sys_getdents64 + mv a0, s2 # fd + la a1, dirents_buf + li a2, 512 # buffer size + ecall + ASSERT_GEZ a0, 15 + + # 13. Close directory fd + li a7, 57 # sys_close + mv a0, s2 # fd + ecall + ASSERT_EQ a0, 0, 16 + + # 13b. Test readlinkat + li a7, 78 # sys_readlinkat + li a0, -100 # AT_FDCWD + la a1, link_name + la a2, read_buf + li a3, 50 # buffer size + ecall + ASSERT_EQ a0, 19, 27 + + # verify symlink target string + la t0, file_name_new + la t1, read_buf + li t2, 0 +.L_loop_link: + add t3, t0, t2 + lb t3, 0(t3) + add t5, t1, t2 + lb t5, 0(t5) + ASSERT_REG_EQ t3, t5, 28 + addi t2, t2, 1 + li t6, 19 + blt t2, t6, .L_loop_link + + # 14. Test unlinkat for renamed file + li a7, 35 # sys_unlinkat + li a0, -100 # AT_FDCWD + la a1, file_name_new + li a2, 0 + ecall + ASSERT_EQ a0, 0, 17 + + # 14b. Test unlinkat for symlink + li a7, 35 # sys_unlinkat + li a0, -100 # AT_FDCWD + la a1, link_name + li a2, 0 + ecall + ASSERT_EQ a0, 0, 29 + + # 15. Test unlinkat with AT_REMOVEDIR for directory + li a7, 35 # sys_unlinkat + li a0, -100 # AT_FDCWD + la a1, dir_name + li a2, 512 # AT_REMOVEDIR + ecall + ASSERT_EQ a0, 0, 18 + + + # 15b. Test getrandom + li a7, 278 # sys_getrandom + la a0, random_buf + li a1, 16 # 16 bytes + li a2, 0 # no flags + ecall + ASSERT_EQ a0, 16, 185 + + # 16. Write success message + li a7, 64 # sys_write + li a0, 1 # stdout + la a1, msg_success + li a2, 33 # success message length + ecall + ASSERT_EQ a0, 33, 19 + + # 17. Exit with 0 + li a7, 93 # sys_exit + li a0, 0 # status 0 + ecall + +.section .rodata +msg_welcome: + .string "Running Syscall Verification\n" +msg_to_file: + .string "Hello from RISC-V A-Machine!\n" +msg_success: + .string "All Extended Syscall Tests PASS!\n" +file_name: + .string "test_output.txt" +file_name_new: + .string "test_output_new.txt" +link_name: + .string "test_link.txt" +dir_name: + .string "test_dir" + +.section .bss +.align 4 +timespec_buf: + .space 16 +timeval_buf: + .space 8 +read_buf: + .space 64 +dirents_buf: + .space 512 +random_buf: + .space 16 +stat_buf: + .space 104 + diff --git a/rv32imac_tests.bin b/rv32imac_tests.bin deleted file mode 100755 index 0ce71c1..0000000 Binary files a/rv32imac_tests.bin and /dev/null differ