2003/09/18 08:10:36
[org.ibex.core.git] / src / org / xwt / mips / syscalls.c
diff --git a/src/org/xwt/mips/syscalls.c b/src/org/xwt/mips/syscalls.c
new file mode 100644 (file)
index 0000000..ca35ddf
--- /dev/null
@@ -0,0 +1,78 @@
+#include <errno.h>
+#undef errno
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// NOTE: This must match up with the Syscalls interface in MIPSInterpreter.java
+// (in my tree the Syscalls interface is autogenerated from a syscalls.h. We should
+// do the same)
+#define SYS_null 0
+#define SYS_exit 1
+#define SYS_pause 2
+#define SYS_open 3
+#define SYS_close 4
+#define SYS_read 5
+#define SYS_write 6
+#define SYS_sbrk 7
+#define SYS_fstat 8
+#define SYS_isatty 9
+#define SYS_seek 10
+#define SYS_kill 11
+#define SYS_getpid 12
+
+static inline int syscall4(int n, int a, int b, int c, int d) {
+    int ret;
+    __asm__ __volatile__ (
+        ".set noreorder\n\t"
+        "move $2,%1\n\t"
+        "move $4,%2\n\t"
+        "move $5,%3\n\t"
+        "move $6,%4\n\t"
+        "move $7,%5\n\t"
+        "syscall\n\t"
+        "move %0,$2\n\t"
+        ".set reorder\n\t"
+        : "=r"(ret)
+        : "0"(n),"r"(a),"r"(b),"r"(c),"r"(d)
+        : "$2","$4","$5","$6","$7","memory"
+    );
+    return ret;
+}
+static inline int syscall0(int n) { return syscall4(n,0,0,0,0); }
+static inline int syscall1(int n, int a) { return syscall4(n,a,0,0,0); }
+static inline int syscall2(int n, int a, int b) { return syscall4(n,a,b,0,0); }
+static inline int syscall3(int n, int a, int b, int c) { return syscall4(n,a,b,c,0); }
+
+static inline int errnoize(struct _reent *ptr,int n) {
+    if(n < 0) {
+        ptr->_errno = -n;
+        n = -1;
+    }
+    return n;
+}
+
+/* These return errno values and must be reentrant */
+caddr_t _sbrk_r(struct _reent *ptr,int incr) {
+    int n = syscall1(SYS_sbrk,incr);
+    if(n == -ENOMEM) { ptr->_errno = ENOMEM; return (caddr_t)-1; }
+    return (caddr_t) n;
+}
+
+int _write_r(struct _reent *ptr,int fd, char *p, int len) { return errnoize(ptr,syscall3(SYS_write,fd,(int)p,len)); }
+int _read_r(struct _reent *ptr,int fd, char *p, int len) { return errnoize(ptr,syscall3(SYS_read,fd,(int)p,len)); }
+int _close_r(struct _reent *ptr,int fd) { return errnoize(ptr,syscall1(SYS_close,fd)); }
+int _fstat_r(struct _reent *ptr,int fd, struct stat *st) { return errnoize(ptr,syscall2(SYS_fstat,fd,(int)st)); }
+int _lseek_r(struct _reent *ptr,int fd, int off, int whence) { return errnoize(ptr,syscall3(SYS_seek,fd,off,whence)); }
+int _open_r(struct _reent *ptr,char *name, int flags, int mode) { return errnoize(ptr,syscall3(SYS_open,(int)name,flags,mode)); }
+int _kill_r(struct _reent *ptr,pid_t pid, int sig) { return errnoize(ptr,syscall2(SYS_kill,(int)pid,sig)); }
+int _getpid_r(struct _reent *ptr) { return errnoize(ptr,syscall0(SYS_getpid)); }
+
+/* No errno values */
+void _exit(int status) {
+    syscall1(SYS_exit,status);
+    for(;;); /* shut up gcc */
+}
+int isatty(int fd) { return syscall1(SYS_isatty,fd); }
+
+void emu_pause() { syscall0(SYS_pause); }