📄 mips-syscall.c
字号:
{SYS_cacheflush, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "cacheflush"}, {SYS_cachectl, SPC_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "cachectl"}, {154, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, ""}, {SYS_atomic_op, BAD_SYSCALL, NO_ARG, NO_ARG, NO_ARG, NO_ARG, NO_ARG, "atomic_op"},#else {0}#endif};#define MAX_SYSCALL (sizeof(syscall_table)/ sizeof(syscall_table[0]))static int syscall_usage[MAX_SYSCALL]; /* Track system calls */#define SYSCALL_ARG(REGOFF, ARG, REG) \ ((syscall_table[R[REGOFF]].ARG == ADDR_ARG) ? \ (R[REG] == 0 ? (void*)NULL : MEM_ADDRESS(R[REG])) : \ (syscall_table[R[REGOFF]].ARG == STR_ARG) ? MEM_ADDRESS(R[REG]) : \ (((syscall_table[R[REGOFF]].ARG == FD_ARG) \ && (R[REG] < OPEN_MAX) && (R[REG] >= 0))) ? (void*)prog_fds[R[REG]] : (void*)R[REG])#define SYSCALL_COUNT(SYSCALL) \ if (SYSCALL < MAX_SYSCALL && SYSCALL >= 0) syscall_usage[SYSCALL]++;/* Decides which syscall to execute or simulate. Returns zero upon exit syscall and non-zero to continue execution. */#ifdef __STDC__intdo_syscall (void)#elseintdo_syscall ()#endif{ SYSCALL_COUNT(R[REG_V0]); if (source_file) { /* Syscalls for the source-language version of SPIM. These are easier to use than the real syscall and are portable to non-MIPS (non-Unix?) operating systems. */ switch (R[REG_V0]) { case PRINT_INT_SYSCALL: write_output (console_out, "%d", R[REG_A0]); break; case PRINT_FLOAT_SYSCALL: { float val = FPR_S (REG_FA0); write_output (console_out, "%.18f", val); break; } case PRINT_DOUBLE_SYSCALL: write_output (console_out, "%.18g", FPR[REG_FA0/2]); break; case PRINT_STRING_SYSCALL: write_output (console_out, "%s", MEM_ADDRESS (R[REG_A0])); break; case READ_INT_SYSCALL: { static char str [256]; read_input (str, 256); R[REG_RES] = atol (str); break; } case READ_FLOAT_SYSCALL: { static char str [256]; read_input (str, 256); FGR [REG_FRES] = (float) atof (str); break; } case READ_DOUBLE_SYSCALL: { static char str [256]; read_input (str, 256); FPR [REG_FRES] = atof (str); break; } case READ_STRING_SYSCALL: { read_input ( (char *) MEM_ADDRESS (R[REG_A0]), R[REG_A1]); data_modified = 1; break; } case SBRK_SYSCALL: { mem_addr x = data_top; expand_data (R[REG_A0]); R[REG_RES] = x; data_modified = 1; break; } case PRINT_CHARACTER_SYSCALL: write_output (console_out, "%c", R[REG_A0]); break; case READ_CHARACTER_SYSCALL: { static char str [2]; read_input (str, 2); if (*str == '\0') *str = '\n'; /* makes xspim = spim */ R[REG_RES] = (long) str[0]; break; } case EXIT_SYSCALL: return (0); case OPEN_SYSCALL: {#ifdef WIN32 R[REG_RES] = _open(MEM_ADDRESS(R[REG_A0]), R[REG_A1], R[REG_A2]);#else R[REG_RES] = open(MEM_ADDRESS(R[REG_A0]), R[REG_A1], R[REG_A2]);#endif break; } case READ_SYSCALL: { /* Test if address is valid */ MEM_ADDRESS(R[REG_A1] + R[REG_A2] - 1);#ifdef WIN32 R[REG_RES] = _read(R[REG_A0], MEM_ADDRESS(R[REG_A1]), R[REG_A2]);#else R[REG_RES] = read(R[REG_A0], MEM_ADDRESS(R[REG_A1]), R[REG_A2]);#endif data_modified = 1; break; } case WRITE_SYSCALL: { /* Test if address is valid */ MEM_ADDRESS(R[REG_A1] + R[REG_A2] - 1);#ifdef WIN32 R[REG_RES] = _write(R[REG_A0], MEM_ADDRESS(R[REG_A1]), R[REG_A2]);#else R[REG_RES] = write(R[REG_A0], MEM_ADDRESS(R[REG_A1]), R[REG_A2]);#endif break; } case CLOSE_SYSCALL: {#ifdef WIN32 R[REG_RES] = _close(R[REG_A0]);#else R[REG_RES] = close(R[REG_A0]);#endif break; } default: run_error ("Unknown system call: %d\n", R[REG_V0]); break; } } else#if (mips && dec) { if (!fds_initialized) { initialize_prog_fds (); fds_initialized = 1; } /* Use actual MIPS system calls. First translate arguments from simulated memory to actual memory and correct file descriptors. */ if (R[REG_V0] < 0 || R[REG_V0] > MAX_SYSCALL) { run_error ("Illegal system call: %d\n", R[REG_V0]); } switch (syscall_table[R[REG_V0]].syscall_type) { case BAD_SYSCALL: run_error ("Unknown system call: %d\n", R[REG_V0]); break; case UNIX_SYSCALL: unixsyscall (); break; case SPC_SYSCALL: /* These syscalls need to be simulated specially: */ switch (R[REG_V0]) { case SYS_syscall: R[REG_V0] = R[REG_A0]; R[REG_A0] = R[REG_A1]; R[REG_A1] = R[REG_A2]; R[REG_A2] = R[REG_A3]; READ_MEM_WORD (R[REG_A3], R[REG_SP] + 16); do_syscall (); break; case SYS_sysmips: { /* The table smipst maps from the sysmips arguments to syscall numbers */ int callno; static int smipst[] = {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, SYS_getrusage, SYS_wait3, SYS_cacheflush, SYS_cachectl}; callno= R[REG_A0]; callno= ( (callno >0x100) ? smipst[callno - 0x100 + 10] : smipst[callno]); R[REG_V0] = callno; R[REG_A0] = R[REG_A1]; R[REG_A1] = R[REG_A2]; R[REG_A2] = R[REG_A3]; READ_MEM_WORD (R[REG_A3], R[REG_SP] + 16); do_syscall (); break; } case SYS_exit: { kill_prog_fds (); return (0); } case SYS_close: if (unixsyscall () >= 0) prog_fds[R[REG_A0]] = -1; /* Mark file descriptor closed */ break; case SYS_open: case SYS_creat: case SYS_dup: { int ret = unixsyscall (); if (ret >= 0) prog_fds[ret] = ret; /* Update fd translation table */ break; } case SYS_pipe: { /* This isn't too useful unless we implement fork () or other fd passing mechanisms */ int fd1, fd2; if (unixsyscall () >= 0) { READ_MEM_WORD (fd1, MEM_ADDRESS (R[REG_A0])); READ_MEM_WORD (fd2, MEM_ADDRESS (R[REG_A0])); prog_fds[fd1] = fd1; prog_fds[fd2] = fd2; } break; } case SYS_select: { int fd; /* * We have to use this kludge to circumvent typechecking * because the memory read macros take the lefthand side * as an argument instead of simply returnign the value * at the address */ mem_addr kludge; fd_set a, b, c; fd_set *readfds = &a, *writefds = &b, *exceptfds = &c; struct timeval *timeout; FD_ZERO (readfds); FD_ZERO (writefds); FD_ZERO (exceptfds); READ_MEM_WORD (kludge, R[REG_SP] + 16); if (kludge == NULL) timeout = NULL; else timeout = (struct timeval *) MEM_ADDRESS (kludge); if (R[REG_A1] == NULL) readfds = NULL; else for (fd = 0; fd < R[REG_A0]; fd++) if (FD_ISSET (fd, (fd_set *) MEM_ADDRESS (R[REG_A1]))) FD_SET (prog_fds[fd], readfds); if (R[REG_A2] == NULL) writefds = NULL; else for (fd = 0; fd < R[REG_A0]; fd++) if (FD_ISSET (fd, (fd_set *) MEM_ADDRESS (R[REG_A2]))) FD_SET (prog_fds[fd], writefds); if (R[REG_A3] == NULL) exceptfds = NULL; else for (fd = 0; fd < R[REG_A0]; fd++) if (FD_ISSET (fd, (fd_set *) MEM_ADDRESS (R[REG_A3]))) FD_SET (prog_fds[fd], exceptfds); R[REG_RES] = select (R[REG_A0], readfds, writefds, exceptfds, timeout); if (readfds == NULL) R[REG_A1] = NULL; else for (fd = 0; fd < R[REG_A0]; fd++) if (FD_ISSET (fd, readfds)) FD_SET (reverse_fds (fd), (fd_set *) MEM_ADDRESS (R[REG_A1])); if (writefds == NULL) R[REG_A2] = NULL; else for (fd = 0; fd < R[REG_A0]; fd++) if (FD_ISSET (fd, writefds)) FD_SET (reverse_fds (fd), (fd_set *) MEM_ADDRESS (R[REG_A2])); if (exceptfds == NULL) R[REG_A3] = NULL; else for (fd = 0; fd < R[REG_A0]; fd++) if (FD_ISSET (fd, exceptfds)) FD_SET (reverse_fds (fd), (fd_set *) MEM_ADDRESS (R[REG_A3])); if (R[REG_RES] < 0) { R[REG_ERR] = -1; R[REG_RES] = errno; return (-1); } else { R[REG_ERR] = 0; return (R[REG_RES]); } } case SYS_sbrk:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -