/* * Copyright 1993,1994,1995 Emin Gun Sirer * MIPSI - Mips Instruction Set Simulator. */ #include "MIPS/syscall-ultrix.h" #include "config.h" #include "main.h" #include "syscalls.h" #include "mem.h" /* * decides which syscall it should do or simulate * returns non-zero to signal exit, zero for continue */ int dosyscall(void) { void *buf; switch(R[REG_V0]) { case SYS_syscall: traceout("SYSCALL syscall\n"); R[REG_V0] = R[REG_A0]; R[REG_A0] = R[REG_A1]; R[REG_A1] = R[REG_A2]; R[REG_A2] = R[REG_A3]; R[REG_A3] = rnr_mem_word(R[REG_SP]+16); dosyscall(); break; case SYS_write: /* A special case so we can use printf without implementing any I/O in mt-os. */ traceout("SYSCALL write(%d, 0x%x, %d)\n", R[REG_A0], R[REG_A1], R[REG_A2]); buf = galloc(R[REG_A2]); copy_to_buffer(buf, R[REG_A1], R[REG_A2]); R[REG_RES] = write(R[REG_A0], buf, R[REG_A2]); R[REG_ERR] = ((signed)R[REG_RES] < 0) ? -1 : 0; free(buf); break; case SYS_getpagesize: traceout("SYSCALL getpagesize() = 4096\n"); R[REG_RES] = 4096; R[REG_ERR] = 0; break; case SYS_sbrk: traceout("SYSCALL sbrk(%d) = ", R[REG_A0]); expand_data(R[REG_A0]); R[REG_RES] = pbreak; pbreak += R[REG_A0]; R[REG_ERR] = 0; traceout("0x%x\n", R[REG_RES]); break; case SYS_brk: { unsigned long datatop = 0x10000000 + datasize; traceout("SYSCALL brk(0x%x) = ", R[REG_A0]); /* Round up to PGSZ boundary */ if((R[REG_A0] - datatop) > 0) expand_data(ROUND(R[REG_A0], PGSZ) - datatop); /* * if we get here, expand data must have been successful */ R[REG_RES] = pbreak; pbreak = ROUND(R[REG_A0], PGSZ); R[REG_ERR] = 0; traceout("0x%x\n", R[REG_RES]); break; } case SYS_exit: { /* A special case so programs can stop. */ traceout("SYSCALL _exit(%d)\n", R[REG_A0]); return (R[REG_A0] & 0xff) + 256; } case SYS_MT_OS: R[REG_RES] = mt_syscall(R[REG_A0], R[REG_A1], R[REG_A2], R[REG_A3]); break; default: error(Fatal, "Unimplemented system call: %d\n",R[REG_V0]); break; } return 0; }