Restructuring of LiveProcess etc. to support multiple emulated OS syscall
authorSteve Reinhardt <stever@eecs.umich.edu>
Tue, 2 Dec 2003 03:34:38 +0000 (19:34 -0800)
committerSteve Reinhardt <stever@eecs.umich.edu>
Tue, 2 Dec 2003 03:34:38 +0000 (19:34 -0800)
interfaces, and specific support for Alpha Linux.  Split syscall emulation
functions into several groups, based on whether they depend on the specific
OS and/or architecture (and all combinations of above), including the use of
template functions to support syscalls with slightly different constants
or interface structs.

arch/alpha/alpha_tru64_process.cc:
    Incorporate full Tru64 object definition here, including structure and constant definitions.
    This way we can wrap all of the functions inside the object, and not worry about namespace
    conflicts because no one outside this file will ever see it.
base/loader/aout_object.cc:
base/loader/aout_object.hh:
base/loader/ecoff_object.cc:
base/loader/ecoff_object.hh:
base/loader/elf_object.cc:
base/loader/elf_object.hh:
base/loader/object_file.cc:
base/loader/object_file.hh:
    Add enums to ObjectFile to indicate the object's architecture and operating system.
cpu/exec_context.cc:
    prog.hh is now process.hh
cpu/exec_context.hh:
    prog.hh is now process.hh
    move architecture-specific syscall arg accessors into ExecContext
cpu/simple_cpu/simple_cpu.cc:
    No need to include prog.hh (which has been renamed)
sim/process.cc:
sim/process.hh:
    LiveProcess is now effectively an abstract base class.
    New LiveProcess::create() function takes an object file and dynamically picks the
    appropriate subclass of LiveProcess to handle the syscall interface that file expects
    (currently Tru64 or Linux).

--HG--
rename : arch/alpha/fake_syscall.cc => arch/alpha/alpha_tru64_process.cc
rename : sim/prog.cc => sim/process.cc
rename : sim/prog.hh => sim/process.hh
extra : convert_revision : 4a03ca7d94a34177cb672931f8aae83a6bad179a

22 files changed:
arch/alpha/alpha_linux_process.cc [new file with mode: 0644]
arch/alpha/alpha_linux_process.hh [new file with mode: 0644]
arch/alpha/alpha_tru64_process.cc [new file with mode: 0644]
arch/alpha/alpha_tru64_process.hh [new file with mode: 0644]
arch/alpha/fake_syscall.cc [deleted file]
base/loader/aout_object.cc
base/loader/aout_object.hh
base/loader/ecoff_object.cc
base/loader/ecoff_object.hh
base/loader/elf_object.cc
base/loader/elf_object.hh
base/loader/object_file.cc
base/loader/object_file.hh
cpu/exec_context.cc
cpu/exec_context.hh
cpu/simple_cpu/simple_cpu.cc
sim/process.cc [new file with mode: 0644]
sim/process.hh [new file with mode: 0644]
sim/prog.cc [deleted file]
sim/prog.hh [deleted file]
sim/syscall_emul.cc [new file with mode: 0644]
sim/syscall_emul.hh [new file with mode: 0644]

diff --git a/arch/alpha/alpha_linux_process.cc b/arch/alpha/alpha_linux_process.cc
new file mode 100644 (file)
index 0000000..13d1f53
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>     // for host open() flags
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>    // for memset()
+#include <dirent.h>
+
+#include "sim/host.hh"
+#include "cpu/base_cpu.hh"
+#include "mem/functional_mem/functional_memory.hh"
+#include "sim/process.hh"
+#include "cpu/exec_context.hh"
+#include "sim/fake_syscall.hh"
+#include "sim/sim_events.hh"
+
+#include "sim/syscall_emul.hh"
+#include "arch/alpha/alpha_common_syscall_emul.hh"
+#include "sim/universe.hh"     // for curTick & ticksPerSecond
+
+#include "arch/alpha/alpha_linux_process.hh"
+
+#include "base/trace.hh"
+
+using namespace std;
+
+class Linux {
+
+public:
+
+//
+// basic Linux types
+//
+
+typedef uint64_t size_t;
+typedef uint64_t off_t;
+typedef int64_t time_t;
+typedef uint32_t uid_t;
+typedef uint32_t gid_t;
+
+// open(2) flags
+static const int TGT_O_RDONLY   = 00000000;
+static const int TGT_O_WRONLY   = 00000001;
+static const int TGT_O_RDWR     = 00000002;
+static const int TGT_O_NONBLOCK  = 00000004;
+static const int TGT_O_APPEND   = 00000010;
+static const int TGT_O_CREAT    = 00001000;
+static const int TGT_O_TRUNC    = 00002000;
+static const int TGT_O_EXCL     = 00004000;
+static const int TGT_O_NOCTTY   = 00010000;
+static const int TGT_O_SYNC     = 00040000;
+static const int TGT_O_DRD      = 00100000;
+static const int TGT_O_DIRECTIO  = 00200000;
+static const int TGT_O_CACHE    = 00400000;
+static const int TGT_O_DSYNC    = 02000000;
+static const int TGT_O_RSYNC    = 04000000;
+
+static OpenFlagTransTable openFlagTable[];
+static const int NUM_OPEN_FLAGS;
+
+//
+// Stat buffer.
+//
+
+struct tgt_stat {
+    uint32_t   st_dev;
+    uint32_t   st_ino;
+    uint32_t   st_mode;
+    uint32_t   st_nlink;
+    uint32_t   st_uid;
+    uint32_t   st_gid;
+    uint32_t   st_rdev;
+    int64_t    st_size;
+    uint64_t   st_atimeX;
+    uint64_t   st_mtimeX;
+    uint64_t   st_ctimeX;
+    uint32_t   st_blksize;
+    int32_t    st_blocks;
+    uint32_t   st_flags;
+    uint32_t   st_gen;
+};
+
+
+//
+// for uname()
+//
+
+static const int _SYS_NMLN = 65;
+
+struct utsname {
+    char sysname[_SYS_NMLN];
+    char nodename[_SYS_NMLN];
+    char release[_SYS_NMLN];
+    char version[_SYS_NMLN];
+    char machine[_SYS_NMLN];
+};
+
+
+//
+// for ioctl()
+//
+
+static const unsigned TIOCGETP   = 0x40067408;
+static const unsigned TIOCSETP   = 0x80067409;
+static const unsigned TIOCSETN   = 0x8006740a;
+static const unsigned TIOCSETC   = 0x80067411;
+static const unsigned TIOCGETC   = 0x40067412;
+static const unsigned FIONREAD   = 0x4004667f;
+static const unsigned TIOCISATTY = 0x2000745e;
+
+//
+// for getrlimit()
+//
+
+enum rlimit_resources {
+    RLIMIT_CPU = 0,
+    RLIMIT_FSIZE = 1,
+    RLIMIT_DATA = 2,
+    RLIMIT_STACK = 3,
+    RLIMIT_CORE = 4,
+    RLIMIT_RSS = 5,
+    RLIMIT_NOFILE = 6,
+    RLIMIT_AS = 7,
+    RLIMIT_VMEM = 7,
+    RLIMIT_NPROC = 8,
+    RLIMIT_MEMLOCK = 9,
+    RLIMIT_LOCKS = 10
+};
+
+struct rlimit {
+    uint64_t  rlim_cur;        // soft limit
+    uint64_t  rlim_max;        // hard limit
+};
+
+
+//
+// for mmap()
+//
+    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+
+//
+// for gettimeofday
+//
+
+struct timeval {
+    int64_t tv_sec;
+    int64_t tv_usec;
+};
+
+//
+// for getrusage
+//
+
+
+static const int RUSAGE_SELF = 0;
+static const int RUSAGE_CHILDREN = -1;
+static const int RUSAGE_BOTH = -2;
+
+struct rusage {
+     struct timeval ru_utime;  // user time used
+     struct timeval ru_stime;  // system time used
+     int64_t ru_maxrss;
+     int64_t ru_ixrss;         // integral shared memory size
+     int64_t ru_idrss;         // integral unshared data "
+     int64_t ru_isrss;         // integral unshared stack "
+     int64_t ru_minflt;                // page reclaims - total vmfaults
+     int64_t ru_majflt;                // page faults
+     int64_t ru_nswap;         // swaps
+     int64_t ru_inblock;       // block input operations
+     int64_t ru_oublock;       // block output operations
+     int64_t ru_msgsnd;                // messages sent
+     int64_t ru_msgrcv;                // messages received
+     int64_t ru_nsignals;      // signals received
+     int64_t ru_nvcsw;         // voluntary context switches
+     int64_t ru_nivcsw;                // involuntary "
+};
+
+static
+void
+copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
+{
+    TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+    tgt->st_dev = host->st_dev;
+    tgt->st_ino = host->st_ino;
+    tgt->st_mode = host->st_mode;
+    tgt->st_nlink = host->st_nlink;
+    tgt->st_uid = host->st_uid;
+    tgt->st_gid = host->st_gid;
+    tgt->st_rdev = host->st_rdev;
+    tgt->st_size = host->st_size;
+    tgt->st_atimeX = host->st_atime;
+    tgt->st_mtimeX = host->st_mtime;
+    tgt->st_ctimeX = host->st_ctime;
+    tgt->st_blksize = host->st_blksize;
+    tgt->st_blocks = host->st_blocks;
+
+    tgt.copyOut(mem);
+}
+
+
+static const char *hostname;
+
+static
+int
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
+
+    strcpy(name->sysname, "Linux");
+    strcpy(name->nodename, hostname);
+    strcpy(name->release, "2.4.20");
+    strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+    strcpy(name->machine, "alpha");
+
+    name.copyOut(xc->mem);
+    return 0;
+}
+
+
+static
+int
+osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+                   ExecContext *xc)
+{
+    unsigned op = xc->getSyscallArg(0);
+    // unsigned nbytes = xc->getSyscallArg(2);
+
+    switch (op) {
+
+      case 45: { // GSI_IEEE_FP_CONTROL
+          TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+          // I don't think this exactly matches the HW FPCR
+          *fpcr = 0;
+          fpcr.copyOut(xc->mem);
+          return 1;
+      }
+
+      default:
+        cerr << "osf_getsysinfo: unknown op " << op << endl;
+        abort();
+        break;
+    }
+
+    return 0;
+}
+
+
+static
+int
+osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+                   ExecContext *xc)
+{
+    unsigned op = xc->getSyscallArg(0);
+    // unsigned nbytes = xc->getSyscallArg(2);
+
+    switch (op) {
+
+      case 14: { // SSI_IEEE_FP_CONTROL
+          TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
+          // I don't think this exactly matches the HW FPCR
+          fpcr.copyIn(xc->mem);
+          DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
+                   " setting FPCR to 0x%x\n", *(uint64_t*)fpcr);
+          return 1;
+      }
+
+      default:
+        cerr << "osf_getsysinfo: unknown op " << op << endl;
+        abort();
+        break;
+    }
+
+    return 0;
+}
+
+
+static
+int
+fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
+           ExecContext *xc)
+{
+    int fd = xc->getSyscallArg(0);
+
+    if (fd < 0 || process->sim_fd(fd) < 0)
+        return -EBADF;
+
+    int cmd = xc->getSyscallArg(1);
+    switch (cmd) {
+      case 0: // F_DUPFD
+        // if we really wanted to support this, we'd need to do it
+        // in the target fd space.
+        warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
+        return -EMFILE;
+
+      case 1: // F_GETFD (get close-on-exec flag)
+      case 2: // F_SETFD (set close-on-exec flag)
+        return 0;
+
+      case 3: // F_GETFL (get file flags)
+      case 4: // F_SETFL (set file flags)
+        // not sure if this is totally valid, but we'll pass it through
+        // to the underlying OS
+        warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
+        return fcntl(process->sim_fd(fd), cmd);
+        // return 0;
+
+      case 7: // F_GETLK  (get lock)
+      case 8: // F_SETLK  (set lock)
+      case 9: // F_SETLKW (set lock and wait)
+        // don't mess with file locking... just act like it's OK
+        warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
+        return 0;
+
+      default:
+        warn("Unknown fcntl command %d\n", cmd);
+        return 0;
+    }
+}
+
+static SyscallDesc syscallDescs[];
+
+static const int Num_Syscall_Descs;
+
+static const int Max_Syscall_Desc;
+
+static
+void
+doSyscall(int callnum, Process *process, ExecContext *xc)
+{
+    if (callnum < 0 || callnum > Max_Syscall_Desc) {
+        fatal("Syscall %d out of range", callnum);
+    }
+
+    SyscallDesc *desc = &syscallDescs[callnum];
+
+    desc->doSyscall(callnum, process, xc);
+}
+
+
+};  // class Linux
+
+
+// open(2) flags translation table
+OpenFlagTransTable Linux::openFlagTable[] = {
+  /* target flag */    /* host flag */
+#ifdef _MSC_VER
+  { Linux::TGT_O_RDONLY,       _O_RDONLY },
+  { Linux::TGT_O_WRONLY,       _O_WRONLY },
+  { Linux::TGT_O_RDWR,         _O_RDWR },
+  { Linux::TGT_O_APPEND,       _O_APPEND },
+  { Linux::TGT_O_CREAT,                _O_CREAT },
+  { Linux::TGT_O_TRUNC,                _O_TRUNC },
+  { Linux::TGT_O_EXCL,         _O_EXCL },
+#ifdef _O_NONBLOCK
+  { Linux::TGT_O_NONBLOCK,     _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+  { Linux::TGT_O_NOCTTY,       _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+  { Linux::TGT_O_SYNC,         _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+  { Linux::TGT_O_RDONLY,       O_RDONLY },
+  { Linux::TGT_O_WRONLY,       O_WRONLY },
+  { Linux::TGT_O_RDWR,         O_RDWR },
+  { Linux::TGT_O_APPEND,       O_APPEND },
+  { Linux::TGT_O_CREAT,                O_CREAT },
+  { Linux::TGT_O_TRUNC,                O_TRUNC },
+  { Linux::TGT_O_EXCL,         O_EXCL },
+  { Linux::TGT_O_NONBLOCK,     O_NONBLOCK },
+  { Linux::TGT_O_NOCTTY,       O_NOCTTY },
+#ifdef O_SYNC
+  { Linux::TGT_O_SYNC,         O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int Linux::NUM_OPEN_FLAGS = (sizeof(Linux::openFlagTable)/sizeof(Linux::openFlagTable[0]));
+
+const char *Linux::hostname = "m5.eecs.umich.edu";
+
+SyscallDesc Linux::syscallDescs[] = {
+    /*  0 */ SyscallDesc("osf_syscall", unimplementedFunc),
+    /*  1 */ SyscallDesc("exit", exitFunc),
+    /*  2 */ SyscallDesc("fork", unimplementedFunc),
+    /*  3 */ SyscallDesc("read", readFunc),
+    /*  4 */ SyscallDesc("write", writeFunc),
+    /*  5 */ SyscallDesc("osf_old_open", unimplementedFunc),
+    /*  6 */ SyscallDesc("close", closeFunc),
+    /*  7 */ SyscallDesc("osf_wait4", unimplementedFunc),
+    /*  8 */ SyscallDesc("osf_old_creat", unimplementedFunc),
+    /*  9 */ SyscallDesc("link", unimplementedFunc),
+    /* 10 */ SyscallDesc("unlink", unimplementedFunc),
+    /* 11 */ SyscallDesc("osf_execve", unimplementedFunc),
+    /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+    /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
+    /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+    /* 15 */ SyscallDesc("chmod", unimplementedFunc),
+    /* 16 */ SyscallDesc("chown", unimplementedFunc),
+    /* 17 */ SyscallDesc("brk", obreakFunc),
+    /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
+    /* 19 */ SyscallDesc("lseek", lseekFunc),
+    /* 20 */ SyscallDesc("getxpid", getpidFunc),
+    /* 21 */ SyscallDesc("osf_mount", unimplementedFunc),
+    /* 22 */ SyscallDesc("umount", unimplementedFunc),
+    /* 23 */ SyscallDesc("setuid", setuidFunc),
+    /* 24 */ SyscallDesc("getxuid", getuidFunc),
+    /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
+    /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc),
+    /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc),
+    /* 28 */ SyscallDesc("osf_nsendmsg", unimplementedFunc),
+    /* 29 */ SyscallDesc("osf_nrecvfrom", unimplementedFunc),
+    /* 30 */ SyscallDesc("osf_naccept", unimplementedFunc),
+    /* 31 */ SyscallDesc("osf_ngetpeername", unimplementedFunc),
+    /* 32 */ SyscallDesc("osf_ngetsockname", unimplementedFunc),
+    /* 33 */ SyscallDesc("access", unimplementedFunc),
+    /* 34 */ SyscallDesc("osf_chflags", unimplementedFunc),
+    /* 35 */ SyscallDesc("osf_fchflags", unimplementedFunc),
+    /* 36 */ SyscallDesc("sync", unimplementedFunc),
+    /* 37 */ SyscallDesc("kill", unimplementedFunc),
+    /* 38 */ SyscallDesc("osf_old_stat", unimplementedFunc),
+    /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
+    /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc),
+    /* 41 */ SyscallDesc("dup", unimplementedFunc),
+    /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+    /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc),
+    /* 44 */ SyscallDesc("osf_profil", unimplementedFunc),
+    /* 45 */ SyscallDesc("open", openFunc<Linux>),
+    /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc),
+    /* 47 */ SyscallDesc("getxgid", getgidFunc),
+    /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc),
+    /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc),
+    /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc),
+    /* 51 */ SyscallDesc("acct", unimplementedFunc),
+    /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
+    /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc),
+    /* 54 */ SyscallDesc("ioctl", ioctlFunc<Linux>),
+    /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc),
+    /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc),
+    /* 57 */ SyscallDesc("symlink", unimplementedFunc),
+    /* 58 */ SyscallDesc("readlink", unimplementedFunc),
+    /* 59 */ SyscallDesc("execve", unimplementedFunc),
+    /* 60 */ SyscallDesc("umask", unimplementedFunc),
+    /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+    /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc),
+    /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
+    /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
+    /* 65 */ SyscallDesc("osf_mremap", unimplementedFunc),
+    /* 66 */ SyscallDesc("vfork", unimplementedFunc),
+    /* 67 */ SyscallDesc("stat", statFunc<Linux>),
+    /* 68 */ SyscallDesc("lstat", lstatFunc<Linux>),
+    /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc),
+    /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc),
+    /* 71 */ SyscallDesc("mmap", mmapFunc<Linux>),
+    /* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc),
+    /* 73 */ SyscallDesc("munmap", munmapFunc),
+    /* 74 */ SyscallDesc("mprotect", ignoreFunc),
+    /* 75 */ SyscallDesc("madvise", unimplementedFunc),
+    /* 76 */ SyscallDesc("vhangup", unimplementedFunc),
+    /* 77 */ SyscallDesc("osf_kmodcall", unimplementedFunc),
+    /* 78 */ SyscallDesc("osf_mincore", unimplementedFunc),
+    /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
+    /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
+    /* 81 */ SyscallDesc("osf_old_getpgrp", unimplementedFunc),
+    /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
+    /* 83 */ SyscallDesc("osf_setitimer", unimplementedFunc),
+    /* 84 */ SyscallDesc("osf_old_wait", unimplementedFunc),
+    /* 85 */ SyscallDesc("osf_table", unimplementedFunc),
+    /* 86 */ SyscallDesc("osf_getitimer", unimplementedFunc),
+    /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
+    /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
+    /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
+    /* 90 */ SyscallDesc("dup2", unimplementedFunc),
+    /* 91 */ SyscallDesc("fstat", fstatFunc<Linux>),
+    /* 92 */ SyscallDesc("fcntl", fcntlFunc),
+    /* 93 */ SyscallDesc("osf_select", unimplementedFunc),
+    /* 94 */ SyscallDesc("poll", unimplementedFunc),
+    /* 95 */ SyscallDesc("fsync", unimplementedFunc),
+    /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
+    /* 97 */ SyscallDesc("socket", unimplementedFunc),
+    /* 98 */ SyscallDesc("connect", unimplementedFunc),
+    /* 99 */ SyscallDesc("accept", unimplementedFunc),
+    /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
+    /* 101 */ SyscallDesc("send", unimplementedFunc),
+    /* 102 */ SyscallDesc("recv", unimplementedFunc),
+    /* 103 */ SyscallDesc("sigreturn", unimplementedFunc),
+    /* 104 */ SyscallDesc("bind", unimplementedFunc),
+    /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
+    /* 106 */ SyscallDesc("listen", unimplementedFunc),
+    /* 107 */ SyscallDesc("osf_plock", unimplementedFunc),
+    /* 108 */ SyscallDesc("osf_old_sigvec", unimplementedFunc),
+    /* 109 */ SyscallDesc("osf_old_sigblock", unimplementedFunc),
+    /* 110 */ SyscallDesc("osf_old_sigsetmask", unimplementedFunc),
+    /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
+    /* 112 */ SyscallDesc("osf_sigstack", ignoreFunc),
+    /* 113 */ SyscallDesc("recvmsg", unimplementedFunc),
+    /* 114 */ SyscallDesc("sendmsg", unimplementedFunc),
+    /* 115 */ SyscallDesc("osf_old_vtrace", unimplementedFunc),
+    /* 116 */ SyscallDesc("osf_gettimeofday", unimplementedFunc),
+    /* 117 */ SyscallDesc("osf_getrusage", unimplementedFunc),
+    /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
+    /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
+    /* 120 */ SyscallDesc("readv", unimplementedFunc),
+    /* 121 */ SyscallDesc("writev", unimplementedFunc),
+    /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc),
+    /* 123 */ SyscallDesc("fchown", unimplementedFunc),
+    /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
+    /* 125 */ SyscallDesc("recvfrom", unimplementedFunc),
+    /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
+    /* 127 */ SyscallDesc("setregid", unimplementedFunc),
+    /* 128 */ SyscallDesc("rename", unimplementedFunc),
+    /* 129 */ SyscallDesc("truncate", unimplementedFunc),
+    /* 130 */ SyscallDesc("ftruncate", unimplementedFunc),
+    /* 131 */ SyscallDesc("flock", unimplementedFunc),
+    /* 132 */ SyscallDesc("setgid", unimplementedFunc),
+    /* 133 */ SyscallDesc("sendto", unimplementedFunc),
+    /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
+    /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
+    /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
+    /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
+    /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc),
+    /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc),
+    /* 140 */ SyscallDesc("osf_adjtime", unimplementedFunc),
+    /* 141 */ SyscallDesc("getpeername", unimplementedFunc),
+    /* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc),
+    /* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc),
+    /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Linux>),
+    /* 145 */ SyscallDesc("setrlimit", unimplementedFunc),
+    /* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc),
+    /* 147 */ SyscallDesc("setsid", unimplementedFunc),
+    /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
+    /* 149 */ SyscallDesc("osf_oldquota", unimplementedFunc),
+    /* 150 */ SyscallDesc("getsockname", unimplementedFunc),
+    /* 151 */ SyscallDesc("osf_pread", unimplementedFunc),
+    /* 152 */ SyscallDesc("osf_pwrite", unimplementedFunc),
+    /* 153 */ SyscallDesc("osf_pid_block", unimplementedFunc),
+    /* 154 */ SyscallDesc("osf_pid_unblock", unimplementedFunc),
+    /* 155 */ SyscallDesc("osf_signal_urti", unimplementedFunc),
+    /* 156 */ SyscallDesc("sigaction", ignoreFunc),
+    /* 157 */ SyscallDesc("osf_sigwaitprim", unimplementedFunc),
+    /* 158 */ SyscallDesc("osf_nfssvc", unimplementedFunc),
+    /* 159 */ SyscallDesc("osf_getdirentries", unimplementedFunc),
+    /* 160 */ SyscallDesc("osf_statfs", unimplementedFunc),
+    /* 161 */ SyscallDesc("osf_fstatfs", unimplementedFunc),
+    /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
+    /* 163 */ SyscallDesc("osf_async_daemon", unimplementedFunc),
+    /* 164 */ SyscallDesc("osf_getfh", unimplementedFunc),
+    /* 165 */ SyscallDesc("osf_getdomainname", unimplementedFunc),
+    /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
+    /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
+    /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
+    /* 169 */ SyscallDesc("osf_exportfs", unimplementedFunc),
+    /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
+    /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
+    /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
+    /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
+    /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
+    /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
+    /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
+    /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
+    /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
+    /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
+    /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
+    /* 181 */ SyscallDesc("osf_alt_plock", unimplementedFunc),
+    /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
+    /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
+    /* 184 */ SyscallDesc("osf_getmnt", unimplementedFunc),
+    /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
+    /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
+    /* 187 */ SyscallDesc("osf_alt_sigpending", unimplementedFunc),
+    /* 188 */ SyscallDesc("osf_alt_setsid", unimplementedFunc),
+    /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
+    /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
+    /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
+    /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
+    /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
+    /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
+    /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
+    /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
+    /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
+    /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
+    /* 199 */ SyscallDesc("osf_swapon", unimplementedFunc),
+    /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
+    /* 201 */ SyscallDesc("msgget", unimplementedFunc),
+    /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
+    /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
+    /* 204 */ SyscallDesc("semctl", unimplementedFunc),
+    /* 205 */ SyscallDesc("semget", unimplementedFunc),
+    /* 206 */ SyscallDesc("semop", unimplementedFunc),
+    /* 207 */ SyscallDesc("osf_utsname", unimplementedFunc),
+    /* 208 */ SyscallDesc("lchown", unimplementedFunc),
+    /* 209 */ SyscallDesc("osf_shmat", unimplementedFunc),
+    /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
+    /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
+    /* 212 */ SyscallDesc("shmget", unimplementedFunc),
+    /* 213 */ SyscallDesc("osf_mvalid", unimplementedFunc),
+    /* 214 */ SyscallDesc("osf_getaddressconf", unimplementedFunc),
+    /* 215 */ SyscallDesc("osf_msleep", unimplementedFunc),
+    /* 216 */ SyscallDesc("osf_mwakeup", unimplementedFunc),
+    /* 217 */ SyscallDesc("msync", unimplementedFunc),
+    /* 218 */ SyscallDesc("osf_signal", unimplementedFunc),
+    /* 219 */ SyscallDesc("osf_utc_gettime", unimplementedFunc),
+    /* 220 */ SyscallDesc("osf_utc_adjtime", unimplementedFunc),
+    /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
+    /* 222 */ SyscallDesc("osf_security", unimplementedFunc),
+    /* 223 */ SyscallDesc("osf_kloadcall", unimplementedFunc),
+    /* 224 */ SyscallDesc("unknown #224", unimplementedFunc),
+    /* 225 */ SyscallDesc("unknown #225", unimplementedFunc),
+    /* 226 */ SyscallDesc("unknown #226", unimplementedFunc),
+    /* 227 */ SyscallDesc("unknown #227", unimplementedFunc),
+    /* 228 */ SyscallDesc("unknown #228", unimplementedFunc),
+    /* 229 */ SyscallDesc("unknown #229", unimplementedFunc),
+    /* 230 */ SyscallDesc("unknown #230", unimplementedFunc),
+    /* 231 */ SyscallDesc("unknown #231", unimplementedFunc),
+    /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
+    /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
+    /* 234 */ SyscallDesc("getsid", unimplementedFunc),
+    /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
+    /* 236 */ SyscallDesc("osf_waitid", unimplementedFunc),
+    /* 237 */ SyscallDesc("osf_priocntlset", unimplementedFunc),
+    /* 238 */ SyscallDesc("osf_sigsendset", unimplementedFunc),
+    /* 239 */ SyscallDesc("osf_set_speculative", unimplementedFunc),
+    /* 240 */ SyscallDesc("osf_msfs_syscall", unimplementedFunc),
+    /* 241 */ SyscallDesc("osf_sysinfo", unimplementedFunc),
+    /* 242 */ SyscallDesc("osf_uadmin", unimplementedFunc),
+    /* 243 */ SyscallDesc("osf_fuser", unimplementedFunc),
+    /* 244 */ SyscallDesc("osf_proplist_syscall", unimplementedFunc),
+    /* 245 */ SyscallDesc("osf_ntp_adjtime", unimplementedFunc),
+    /* 246 */ SyscallDesc("osf_ntp_gettime", unimplementedFunc),
+    /* 247 */ SyscallDesc("osf_pathconf", unimplementedFunc),
+    /* 248 */ SyscallDesc("osf_fpathconf", unimplementedFunc),
+    /* 249 */ SyscallDesc("unknown #249", unimplementedFunc),
+    /* 250 */ SyscallDesc("osf_uswitch", unimplementedFunc),
+    /* 251 */ SyscallDesc("osf_usleep_thread", unimplementedFunc),
+    /* 252 */ SyscallDesc("osf_audcntl", unimplementedFunc),
+    /* 253 */ SyscallDesc("osf_audgen", unimplementedFunc),
+    /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
+    /* 255 */ SyscallDesc("osf_subsys_info", unimplementedFunc),
+    /* 256 */ SyscallDesc("osf_getsysinfo", osf_getsysinfoFunc),
+    /* 257 */ SyscallDesc("osf_setsysinfo", osf_setsysinfoFunc),
+    /* 258 */ SyscallDesc("osf_afs_syscall", unimplementedFunc),
+    /* 259 */ SyscallDesc("osf_swapctl", unimplementedFunc),
+    /* 260 */ SyscallDesc("osf_memcntl", unimplementedFunc),
+    /* 261 */ SyscallDesc("osf_fdatasync", unimplementedFunc),
+    /* 262 */ SyscallDesc("unknown #262", unimplementedFunc),
+    /* 263 */ SyscallDesc("unknown #263", unimplementedFunc),
+    /* 264 */ SyscallDesc("unknown #264", unimplementedFunc),
+    /* 265 */ SyscallDesc("unknown #265", unimplementedFunc),
+    /* 266 */ SyscallDesc("unknown #266", unimplementedFunc),
+    /* 267 */ SyscallDesc("unknown #267", unimplementedFunc),
+    /* 268 */ SyscallDesc("unknown #268", unimplementedFunc),
+    /* 269 */ SyscallDesc("unknown #269", unimplementedFunc),
+    /* 270 */ SyscallDesc("unknown #270", unimplementedFunc),
+    /* 271 */ SyscallDesc("unknown #271", unimplementedFunc),
+    /* 272 */ SyscallDesc("unknown #272", unimplementedFunc),
+    /* 273 */ SyscallDesc("unknown #273", unimplementedFunc),
+    /* 274 */ SyscallDesc("unknown #274", unimplementedFunc),
+    /* 275 */ SyscallDesc("unknown #275", unimplementedFunc),
+    /* 276 */ SyscallDesc("unknown #276", unimplementedFunc),
+    /* 277 */ SyscallDesc("unknown #277", unimplementedFunc),
+    /* 278 */ SyscallDesc("unknown #278", unimplementedFunc),
+    /* 279 */ SyscallDesc("unknown #279", unimplementedFunc),
+    /* 280 */ SyscallDesc("unknown #280", unimplementedFunc),
+    /* 281 */ SyscallDesc("unknown #281", unimplementedFunc),
+    /* 282 */ SyscallDesc("unknown #282", unimplementedFunc),
+    /* 283 */ SyscallDesc("unknown #283", unimplementedFunc),
+    /* 284 */ SyscallDesc("unknown #284", unimplementedFunc),
+    /* 285 */ SyscallDesc("unknown #285", unimplementedFunc),
+    /* 286 */ SyscallDesc("unknown #286", unimplementedFunc),
+    /* 287 */ SyscallDesc("unknown #287", unimplementedFunc),
+    /* 288 */ SyscallDesc("unknown #288", unimplementedFunc),
+    /* 289 */ SyscallDesc("unknown #289", unimplementedFunc),
+    /* 290 */ SyscallDesc("unknown #290", unimplementedFunc),
+    /* 291 */ SyscallDesc("unknown #291", unimplementedFunc),
+    /* 292 */ SyscallDesc("unknown #292", unimplementedFunc),
+    /* 293 */ SyscallDesc("unknown #293", unimplementedFunc),
+    /* 294 */ SyscallDesc("unknown #294", unimplementedFunc),
+    /* 295 */ SyscallDesc("unknown #295", unimplementedFunc),
+    /* 296 */ SyscallDesc("unknown #296", unimplementedFunc),
+    /* 297 */ SyscallDesc("unknown #297", unimplementedFunc),
+    /* 298 */ SyscallDesc("unknown #298", unimplementedFunc),
+    /* 299 */ SyscallDesc("unknown #299", unimplementedFunc),
+/*
+ * Linux-specific system calls begin at 300
+ */
+    /* 300 */ SyscallDesc("bdflush", unimplementedFunc),
+    /* 301 */ SyscallDesc("sethae", unimplementedFunc),
+    /* 302 */ SyscallDesc("mount", unimplementedFunc),
+    /* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc),
+    /* 304 */ SyscallDesc("swapoff", unimplementedFunc),
+    /* 305 */ SyscallDesc("getdents", unimplementedFunc),
+    /* 306 */ SyscallDesc("create_module", unimplementedFunc),
+    /* 307 */ SyscallDesc("init_module", unimplementedFunc),
+    /* 308 */ SyscallDesc("delete_module", unimplementedFunc),
+    /* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc),
+    /* 310 */ SyscallDesc("syslog", unimplementedFunc),
+    /* 311 */ SyscallDesc("reboot", unimplementedFunc),
+    /* 312 */ SyscallDesc("clone", unimplementedFunc),
+    /* 313 */ SyscallDesc("uselib", unimplementedFunc),
+    /* 314 */ SyscallDesc("mlock", unimplementedFunc),
+    /* 315 */ SyscallDesc("munlock", unimplementedFunc),
+    /* 316 */ SyscallDesc("mlockall", unimplementedFunc),
+    /* 317 */ SyscallDesc("munlockall", unimplementedFunc),
+    /* 318 */ SyscallDesc("sysinfo", unimplementedFunc),
+    /* 319 */ SyscallDesc("_sysctl", unimplementedFunc),
+    /* 320 */ SyscallDesc("was sys_idle", unimplementedFunc),
+    /* 321 */ SyscallDesc("oldumount", unimplementedFunc),
+    /* 322 */ SyscallDesc("swapon", unimplementedFunc),
+    /* 323 */ SyscallDesc("times", unimplementedFunc),
+    /* 324 */ SyscallDesc("personality", unimplementedFunc),
+    /* 325 */ SyscallDesc("setfsuid", unimplementedFunc),
+    /* 326 */ SyscallDesc("setfsgid", unimplementedFunc),
+    /* 327 */ SyscallDesc("ustat", unimplementedFunc),
+    /* 328 */ SyscallDesc("statfs", unimplementedFunc),
+    /* 329 */ SyscallDesc("fstatfs", unimplementedFunc),
+    /* 330 */ SyscallDesc("sched_setparam", unimplementedFunc),
+    /* 331 */ SyscallDesc("sched_getparam", unimplementedFunc),
+    /* 332 */ SyscallDesc("sched_setscheduler", unimplementedFunc),
+    /* 333 */ SyscallDesc("sched_getscheduler", unimplementedFunc),
+    /* 334 */ SyscallDesc("sched_yield", unimplementedFunc),
+    /* 335 */ SyscallDesc("sched_get_priority_max", unimplementedFunc),
+    /* 336 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
+    /* 337 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
+    /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc),
+    /* 339 */ SyscallDesc("uname", unameFunc),
+    /* 340 */ SyscallDesc("nanosleep", unimplementedFunc),
+    /* 341 */ SyscallDesc("mremap", unimplementedFunc),
+    /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc),
+    /* 343 */ SyscallDesc("setresuid", unimplementedFunc),
+    /* 344 */ SyscallDesc("getresuid", unimplementedFunc),
+    /* 345 */ SyscallDesc("pciconfig_read", unimplementedFunc),
+    /* 346 */ SyscallDesc("pciconfig_write", unimplementedFunc),
+    /* 347 */ SyscallDesc("query_module", unimplementedFunc),
+    /* 348 */ SyscallDesc("prctl", unimplementedFunc),
+    /* 349 */ SyscallDesc("pread", unimplementedFunc),
+    /* 350 */ SyscallDesc("pwrite", unimplementedFunc),
+    /* 351 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
+    /* 352 */ SyscallDesc("rt_sigaction", unimplementedFunc),
+    /* 353 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
+    /* 354 */ SyscallDesc("rt_sigpending", unimplementedFunc),
+    /* 355 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
+    /* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
+    /* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
+    /* 358 */ SyscallDesc("select", unimplementedFunc),
+    /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Linux>),
+    /* 360 */ SyscallDesc("settimeofday", unimplementedFunc),
+    /* 361 */ SyscallDesc("getitimer", unimplementedFunc),
+    /* 362 */ SyscallDesc("setitimer", unimplementedFunc),
+    /* 363 */ SyscallDesc("utimes", unimplementedFunc),
+    /* 364 */ SyscallDesc("getrusage", getrusageFunc<Linux>),
+    /* 365 */ SyscallDesc("wait4", unimplementedFunc),
+    /* 366 */ SyscallDesc("adjtimex", unimplementedFunc),
+    /* 367 */ SyscallDesc("getcwd", unimplementedFunc),
+    /* 368 */ SyscallDesc("capget", unimplementedFunc),
+    /* 369 */ SyscallDesc("capset", unimplementedFunc),
+    /* 370 */ SyscallDesc("sendfile", unimplementedFunc),
+    /* 371 */ SyscallDesc("setresgid", unimplementedFunc),
+    /* 372 */ SyscallDesc("getresgid", unimplementedFunc),
+    /* 373 */ SyscallDesc("dipc", unimplementedFunc),
+    /* 374 */ SyscallDesc("pivot_root", unimplementedFunc),
+    /* 375 */ SyscallDesc("mincore", unimplementedFunc),
+    /* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc),
+    /* 377 */ SyscallDesc("getdents64", unimplementedFunc),
+    /* 378 */ SyscallDesc("gettid", unimplementedFunc),
+    /* 379 */ SyscallDesc("readahead", unimplementedFunc),
+    /* 380 */ SyscallDesc("security", unimplementedFunc),
+    /* 381 */ SyscallDesc("tkill", unimplementedFunc),
+    /* 382 */ SyscallDesc("setxattr", unimplementedFunc),
+    /* 383 */ SyscallDesc("lsetxattr", unimplementedFunc),
+    /* 384 */ SyscallDesc("fsetxattr", unimplementedFunc),
+    /* 385 */ SyscallDesc("getxattr", unimplementedFunc),
+    /* 386 */ SyscallDesc("lgetxattr", unimplementedFunc),
+    /* 387 */ SyscallDesc("fgetxattr", unimplementedFunc),
+    /* 388 */ SyscallDesc("listxattr", unimplementedFunc),
+    /* 389 */ SyscallDesc("llistxattr", unimplementedFunc),
+    /* 390 */ SyscallDesc("flistxattr", unimplementedFunc),
+    /* 391 */ SyscallDesc("removexattr", unimplementedFunc),
+    /* 392 */ SyscallDesc("lremovexattr", unimplementedFunc),
+    /* 393 */ SyscallDesc("fremovexattr", unimplementedFunc),
+};
+
+const int Linux::Num_Syscall_Descs =
+        sizeof(Linux::syscallDescs) / sizeof(SyscallDesc);
+
+const int Linux::Max_Syscall_Desc = Linux::Num_Syscall_Descs - 1;
+
+
+void
+AlphaLinuxProcess::syscall(ExecContext *xc)
+{
+    num_syscalls++;
+
+    int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
+
+    Linux::doSyscall(callnum, this, xc);
+}
+
+
+AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
+                                     ObjectFile *objFile,
+                                     int stdin_fd,
+                                     int stdout_fd,
+                                     int stderr_fd,
+                                     std::vector<std::string> &argv,
+                                     std::vector<std::string> &envp)
+    : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp)
+{
+}
diff --git a/arch/alpha/alpha_linux_process.hh b/arch/alpha/alpha_linux_process.hh
new file mode 100644 (file)
index 0000000..0d2f764
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ALPHA_LINUX_PROCESS_HH__
+#define __ALPHA_LINUX_PROCESS_HH__
+
+#include "sim/process.hh"
+
+class AlphaLinuxProcess : public LiveProcess
+{
+  public:
+    AlphaLinuxProcess(const std::string &name,
+                      ObjectFile *objFile,
+                      int stdin_fd, int stdout_fd, int stderr_fd,
+                      std::vector<std::string> &argv,
+                      std::vector<std::string> &envp);
+
+    virtual void syscall(ExecContext *xc);
+};
+
+
+#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc
new file mode 100644 (file)
index 0000000..85648e6
--- /dev/null
@@ -0,0 +1,1756 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>     // for host open() flags
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>    // for memset()
+#include <dirent.h>
+
+#include "sim/host.hh"
+#include "cpu/base_cpu.hh"
+#include "mem/functional_mem/functional_memory.hh"
+#include "sim/process.hh"
+#include "cpu/exec_context.hh"
+#include "sim/fake_syscall.hh"
+
+#include "arch/alpha/alpha_common_syscall_emul.hh"
+#include "arch/alpha/alpha_tru64_process.hh"
+
+#include "sim/syscall_emul.hh"
+#include "sim/universe.hh"     // for curTick & ticksPerSecond
+
+#include "base/trace.hh"
+
+using namespace std;
+
+class Tru64 {
+
+public:
+
+//
+// basic Tru64 types
+//
+
+typedef uint64_t size_t;
+typedef uint64_t off_t;
+typedef uint16_t nlink_t;
+typedef int32_t  dev_t;
+typedef uint32_t uid_t;
+typedef uint32_t gid_t;
+typedef uint32_t time_t;
+typedef uint32_t mode_t;
+typedef uint32_t ino_t;
+
+// open(2) flags
+static const int TGT_O_RDONLY   = 00000000;
+static const int TGT_O_WRONLY   = 00000001;
+static const int TGT_O_RDWR     = 00000002;
+static const int TGT_O_NONBLOCK  = 00000004;
+static const int TGT_O_APPEND   = 00000010;
+static const int TGT_O_CREAT    = 00001000;
+static const int TGT_O_TRUNC    = 00002000;
+static const int TGT_O_EXCL     = 00004000;
+static const int TGT_O_NOCTTY   = 00010000;
+static const int TGT_O_SYNC     = 00040000;
+static const int TGT_O_DRD      = 00100000;
+static const int TGT_O_DIRECTIO  = 00200000;
+static const int TGT_O_CACHE    = 00400000;
+static const int TGT_O_DSYNC    = 02000000;
+static const int TGT_O_RSYNC    = 04000000;
+
+static OpenFlagTransTable openFlagTable[];
+static const int NUM_OPEN_FLAGS;
+
+//
+// Stat buffer.  Note that Tru64 v5.0+ use a new "F64" stat structure,
+// and a new set of syscall numbers for stat calls.  Backwards
+// compatibility with v4.x should be feasible by implementing another
+// set of stat functions using the old structure definition and
+// binding them to the old syscall numbers, but we haven't done that
+// yet.
+//
+
+struct F64_stat {
+    dev_t      st_dev;
+    int32_t    st_retired1;
+    mode_t     st_mode;
+    nlink_t    st_nlink;
+    uint16_t   st_nlink_reserved;
+    uid_t      st_uid;
+    gid_t      st_gid;
+    dev_t      st_rdev;
+    dev_t      st_ldev;
+    off_t      st_size;
+    time_t     st_retired2;
+    int32_t    st_uatime;
+    time_t     st_retired3;
+    int32_t    st_umtime;
+    time_t     st_retired4;
+    int32_t    st_uctime;
+    int32_t    st_retired5;
+    int32_t    st_retired6;
+    uint32_t   st_flags;
+    uint32_t   st_gen;
+    uint64_t   st_spare[4];
+    ino_t      st_ino;
+    int32_t    st_ino_reserved;
+    time_t     st_atimeX;
+    int32_t    st_atime_reserved;
+    time_t     st_mtimeX;
+    int32_t    st_mtime_reserved;
+    time_t     st_ctimeX;
+    int32_t    st_ctime_reserved;
+    uint64_t   st_blksize;
+    uint64_t   st_blocks;
+};
+
+
+//
+// for getdirentries()
+//
+
+struct dirent
+{
+    ino_t d_ino;               /* file number of entry */
+    uint16_t d_reclen;         /* length of this record */
+    uint16_t d_namlen;         /* length of string in d_name */
+    char d_name[256];          /* dummy name length */
+};
+
+
+//
+// for uname()
+//
+
+static const int _SYS_NMLN = 32;
+
+struct utsname {
+    char sysname[_SYS_NMLN];
+    char nodename[_SYS_NMLN];
+    char release[_SYS_NMLN];
+    char version[_SYS_NMLN];
+    char machine[_SYS_NMLN];
+};
+
+
+//
+// for ioctl()
+//
+
+static const unsigned TIOCGETP   = 0x40067408;
+static const unsigned TIOCSETP   = 0x80067409;
+static const unsigned TIOCSETN   = 0x8006740a;
+static const unsigned TIOCSETC   = 0x80067411;
+static const unsigned TIOCGETC   = 0x40067412;
+static const unsigned FIONREAD   = 0x4004667f;
+static const unsigned TIOCISATTY = 0x2000745e;
+
+//
+// for getrlimit()
+//
+
+enum rlimit_resources {
+    RLIMIT_CPU = 0,
+    RLIMIT_FSIZE = 1,
+    RLIMIT_DATA = 2,
+    RLIMIT_STACK = 3,
+    RLIMIT_CORE = 4,
+    RLIMIT_RSS = 5,
+    RLIMIT_NOFILE = 6,
+    RLIMIT_AS = 7,
+    RLIMIT_VMEM = 7
+};
+
+struct rlimit {
+    uint64_t  rlim_cur;        // soft limit
+    uint64_t  rlim_max;        // hard limit
+};
+
+
+//
+// for mmap()
+//
+    static const unsigned TGT_MAP_ANONYMOUS = 0x10;
+
+
+//
+// for getsysinfo()
+//
+
+static const unsigned GSI_PLATFORM_NAME = 103; // get platform name as string
+static const unsigned GSI_CPU_INFO = 59;       // CPU information
+static const unsigned GSI_PROC_TYPE = 60;      // get proc_type
+static const unsigned GSI_MAX_CPU = 30;        // max # cpu's on this machine
+static const unsigned GSI_CPUS_IN_BOX = 55;    // number of processors in system
+static const unsigned GSI_PHYSMEM = 19;        // Amount of physical memory in KB
+static const unsigned GSI_CLK_TCK = 42;        // clock freq in Hz
+
+struct cpu_info {
+    uint32_t     current_cpu;
+    uint32_t     cpus_in_box;
+    uint32_t     cpu_type;
+    uint32_t     ncpus;
+    uint64_t cpus_present;
+    uint64_t cpus_running;
+    uint64_t cpu_binding;
+    uint64_t cpu_ex_binding;
+    uint32_t     mhz;
+    uint32_t     unused[3];      // future expansion
+};
+
+//
+// for gettimeofday
+//
+
+struct timeval {
+    uint32_t tv_sec;
+    uint32_t tv_usec;
+};
+
+//
+// for getrusage
+//
+
+
+static const int RUSAGE_THREAD = 1;
+static const int RUSAGE_SELF = 0;
+static const int RUSAGE_CHILDREN = -1;
+
+struct rusage {
+     struct timeval ru_utime;  // user time used
+     struct timeval ru_stime;  // system time used
+     uint64_t ru_maxrss;
+     uint64_t ru_ixrss;                // integral shared memory size
+     uint64_t ru_idrss;                // integral unshared data "
+     uint64_t ru_isrss;                // integral unshared stack "
+     uint64_t ru_minflt;               // page reclaims - total vmfaults
+     uint64_t ru_majflt;               // page faults
+     uint64_t ru_nswap;                // swaps
+     uint64_t ru_inblock;      // block input operations
+     uint64_t ru_oublock;      // block output operations
+     uint64_t ru_msgsnd;               // messages sent
+     uint64_t ru_msgrcv;               // messages received
+     uint64_t ru_nsignals;     // signals received
+     uint64_t ru_nvcsw;                // voluntary context switches
+     uint64_t ru_nivcsw;               // involuntary "
+};
+
+//
+// for sigreturn
+//
+
+struct sigcontext {
+     int64_t sc_onstack;       // sigstack state to restore
+     int64_t sc_mask;          // signal mask to restore
+     int64_t sc_pc;            // pc at time of signal
+     int64_t sc_ps;            // psl to retore
+     int64_t sc_regs[32];      // processor regs 0 to 31
+     int64_t sc_ownedfp;       // fp has been used
+     int64_t sc_fpregs[32];    // fp regs 0 to 31
+     uint64_t sc_fpcr;         // floating point control reg
+     uint64_t sc_fp_control;   // software fpcr
+     int64_t sc_reserved1;     // reserved for kernel
+     uint32_t sc_kreserved1;   // reserved for kernel
+     uint32_t sc_kreserved2;   // reserved for kernel
+     size_t  sc_ssize; // stack size
+     caddr_t sc_sbase; // stack start
+     uint64_t sc_traparg_a0;   // a0 argument to trap on exc
+     uint64_t sc_traparg_a1;   // a1 argument to trap on exc
+     uint64_t sc_traparg_a2;   // a2 argument to trap on exc
+     uint64_t sc_fp_trap_pc;   // imprecise pc
+     uint64_t sc_fp_trigger_sum;       // Exception summary at trigg
+     uint64_t sc_fp_trigger_inst; // Instruction at trigger pc
+};
+
+
+//
+// for table
+//
+static const int TBL_SYSINFO = 12;
+
+struct tbl_sysinfo {
+    uint64_t si_user;  // User time
+    uint64_t si_nice;  // Nice time
+    uint64_t si_sys;   // System time
+    uint64_t si_idle;  // Idle time
+    uint64_t si_hz;
+    uint64_t si_phz;
+    uint64_t si_boottime;      // Boot time in seconds
+    uint64_t wait;             // Wait time
+    uint32_t  si_max_procs;    // rpb->rpb_numprocs
+    uint32_t  pad;
+};
+
+
+//
+// for stack_create
+//
+
+struct vm_stack {
+    // void *
+    Addr       address;        // address hint
+    size_t     rsize;          // red zone size
+    size_t     ysize;          // yellow zone size
+    size_t     gsize;          // green zone size
+    size_t     swap;           // amount of swap to reserve
+    size_t     incr;           // growth increment
+    uint64_t   align;          // address alignment
+    uint64_t   flags;          // MAP_FIXED etc.
+    // struct memalloc_attr *
+    Addr       attr;           // allocation policy
+    uint64_t reserved;
+};
+
+//
+// return values for nxm calls
+//
+enum {
+    KERN_NOT_RECEIVER = 7,
+    KERN_NOT_IN_SET = 12
+};
+
+//
+// for nxm_task_init
+//
+
+static const int NXM_TASK_INIT_VP = 2; // initial thread is VP
+
+struct nxm_task_attr {
+    int64_t nxm_callback;
+    unsigned int nxm_version;
+    unsigned short nxm_uniq_offset;
+    unsigned short flags;
+    int nxm_quantum;
+    int pad1;
+    int64_t pad2;
+};
+
+typedef uint64_t   sigset_t;
+
+struct ushared_state {
+    sigset_t        sigmask;        // thread signal mask
+    sigset_t        sig;            // thread pending mask
+    // struct nxm_pth_state *
+    Addr pth_id; // out-of-line state
+    int             flags;          // shared flags
+#define US_SIGSTACK     0x1             // thread called sigaltstack
+#define US_ONSTACK      0x2             // thread is running on altstack
+#define US_PROFILE      0x4             // thread called profil
+#define US_SYSCALL      0x8             // thread in syscall
+#define US_TRAP         0x10            // thread has trapped
+#define US_YELLOW       0x20            // thread has mellowed yellow
+#define US_YZONE        0x40            // thread has zoned out
+#define US_FP_OWNED     0x80            // thread used floating point
+
+    int             cancel_state;   // thread's cancelation state
+#define US_CANCEL         0x1           // cancel pending
+#define US_NOCANCEL       0X2           // synch cancel disabled
+#define US_SYS_NOCANCEL   0x4           // syscall cancel disabled
+#define US_ASYNC_NOCANCEL 0x8           // asynch cancel disabled
+#define US_CANCEL_BITS  (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
+#define US_CANCEL_MASK  (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
+                         US_ASYNC_NOCANCEL)
+
+    // These are semi-shared. They are always visible to
+    // the kernel but are never context-switched by the library.
+
+    int             nxm_ssig;       // scheduler's synchronous signals
+    int             reserved1;
+    int64_t            nxm_active;     // scheduler active
+    int64_t            reserved2;
+};
+
+struct nxm_sched_state {
+    struct          ushared_state nxm_u;    // state own by user thread
+    unsigned int    nxm_bits;               // scheduler state / slot
+    int             nxm_quantum;            // quantum count-down value
+    int             nxm_set_quantum;        // quantum reset value
+    int             nxm_sysevent;           // syscall state
+    // struct nxm_upcall *
+    Addr           nxm_uc_ret; // stack ptr of null thread
+    // void *
+    Addr nxm_tid;               // scheduler's thread id
+    int64_t            nxm_va;                 // page fault address
+    // struct nxm_pth_state *
+    Addr nxm_pthid; // id of null thread
+    uint64_t   nxm_bound_pcs_count;    // bound PCS thread count
+    int64_t            pad[2];
+};
+
+struct nxm_shared {
+    int64_t nxm_callback;              // address of upcall routine
+    unsigned int nxm_version;       // version number
+    unsigned short nxm_uniq_offset; // correction factor for TEB
+    unsigned short pad1;
+    int64_t space[2];                  // future growth
+    struct nxm_sched_state nxm_ss[1]; // array of shared areas
+};
+
+enum nxm_slot_state_t {
+    NXM_SLOT_AVAIL,
+    NXM_SLOT_BOUND,
+    NXM_SLOT_UNBOUND,
+    NXM_SLOT_EMPTY
+};
+
+
+struct nxm_config_info {
+    int nxm_nslots_per_rad;         // max number of VP slots per RAD
+    int nxm_nrads;                  // max number of RADs
+    // nxm_slot_state_t *
+    Addr nxm_slot_state; // per-VP slot state
+    // struct nxm_shared *
+    Addr nxm_rad[1];  // per-RAD shared areas
+};
+
+//
+// for nxm_thread_create
+//
+
+enum nxm_thread_type {
+    NXM_TYPE_SCS       = 0,
+    NXM_TYPE_VP                = 1,
+    NXM_TYPE_MANAGER   = 2
+};
+
+
+struct nxm_thread_attr {
+    int version;
+    int type;
+    int cancel_flags;
+    int priority;
+    int policy;
+    int signal_type;
+    // void *
+    Addr pthid;
+    sigset_t sigmask;
+    struct {
+        uint64_t pc;
+        uint64_t sp;
+        uint64_t a0;
+    } registers;
+    uint64_t pad2[2];
+};
+
+static
+void
+copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
+{
+    TypedBufferArg<Tru64::F64_stat> tgt(addr);
+
+    tgt->st_dev = host->st_dev;
+    tgt->st_ino = host->st_ino;
+    tgt->st_mode = host->st_mode;
+    tgt->st_nlink = host->st_nlink;
+    tgt->st_uid = host->st_uid;
+    tgt->st_gid = host->st_gid;
+    tgt->st_rdev = host->st_rdev;
+    tgt->st_size = host->st_size;
+    tgt->st_atimeX = host->st_atime;
+    tgt->st_mtimeX = host->st_mtime;
+    tgt->st_ctimeX = host->st_ctime;
+    tgt->st_blksize = host->st_blksize;
+    tgt->st_blocks = host->st_blocks;
+
+    tgt.copyOut(mem);
+}
+
+static const char *hostname;
+
+static
+int
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
+
+    strcpy(name->sysname, "OSF1");
+    strcpy(name->nodename, hostname);
+    strcpy(name->release, "V5.1");
+    strcpy(name->version, "732");
+    strcpy(name->machine, "alpha");
+
+    name.copyOut(xc->mem);
+    return 0;
+}
+
+
+static
+int
+getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+               ExecContext *xc)
+{
+    unsigned op = xc->getSyscallArg(0);
+    unsigned nbytes = xc->getSyscallArg(2);
+
+    switch (op) {
+
+      case Tru64::GSI_MAX_CPU: {
+          TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
+          *max_cpu = process->numCpus();
+          max_cpu.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_CPUS_IN_BOX: {
+          TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
+          *cpus_in_box = process->numCpus();
+          cpus_in_box.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_PHYSMEM: {
+          TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
+          *physmem = 1024 * 1024;      // physical memory in KB
+          physmem.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_CPU_INFO: {
+          TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
+
+          infop->current_cpu = 0;
+          infop->cpus_in_box = process->numCpus();
+          infop->cpu_type = 57;
+          infop->ncpus = process->numCpus();
+          int cpumask = (1 << process->numCpus()) - 1;
+          infop->cpus_present = infop->cpus_running = cpumask;
+          infop->cpu_binding = 0;
+          infop->cpu_ex_binding = 0;
+          infop->mhz = 667;
+
+          infop.copyOut(xc->mem);
+          return 1;
+        }
+
+      case Tru64::GSI_PROC_TYPE: {
+          TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
+          *proc_type = 11;
+          proc_type.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_PLATFORM_NAME: {
+          BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+          strncpy((char *)bufArg.bufferPtr(),
+                  "COMPAQ Professional Workstation XP1000",
+                  nbytes);
+          bufArg.copyOut(xc->mem);
+          return 1;
+      }
+
+      case Tru64::GSI_CLK_TCK: {
+          TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
+          *clk_hz = 1024;
+          clk_hz.copyOut(xc->mem);
+          return 1;
+      }
+
+      default:
+        cerr << "getsysinfo: unknown op " << op << endl;
+        abort();
+        break;
+    }
+
+    return 0;
+}
+
+static
+int
+fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
+           ExecContext *xc)
+{
+    int fd = xc->getSyscallArg(0);
+
+    if (fd < 0 || process->sim_fd(fd) < 0)
+        return -EBADF;
+
+    int cmd = xc->getSyscallArg(1);
+    switch (cmd) {
+      case 0: // F_DUPFD
+        // if we really wanted to support this, we'd need to do it
+        // in the target fd space.
+        warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
+        return -EMFILE;
+
+      case 1: // F_GETFD (get close-on-exec flag)
+      case 2: // F_SETFD (set close-on-exec flag)
+        return 0;
+
+      case 3: // F_GETFL (get file flags)
+      case 4: // F_SETFL (set file flags)
+        // not sure if this is totally valid, but we'll pass it through
+        // to the underlying OS
+        warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
+        return fcntl(process->sim_fd(fd), cmd);
+        // return 0;
+
+      case 7: // F_GETLK  (get lock)
+      case 8: // F_SETLK  (set lock)
+      case 9: // F_SETLKW (set lock and wait)
+        // don't mess with file locking... just act like it's OK
+        warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
+        return 0;
+
+      default:
+        warn("Unknown fcntl command %d\n", cmd);
+        return 0;
+    }
+}
+
+
+static
+int
+getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
+                  ExecContext *xc)
+{
+    int fd = process->sim_fd(xc->getSyscallArg(0));
+    Addr tgt_buf = xc->getSyscallArg(1);
+    int tgt_nbytes = xc->getSyscallArg(2);
+    Addr tgt_basep = xc->getSyscallArg(3);
+
+    char * const host_buf = new char[tgt_nbytes];
+
+    // just pass basep through uninterpreted.
+    TypedBufferArg<int64_t> basep(tgt_basep);
+    basep.copyIn(xc->mem);
+    ::off_t host_basep = (off_t)*basep;
+    int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
+
+    // check for error
+    if (host_result < 0) {
+        delete [] host_buf;
+        return -errno;
+    }
+
+    // no error: copy results back to target space
+    Addr tgt_buf_ptr = tgt_buf;
+    char *host_buf_ptr = host_buf;
+    char *host_buf_end = host_buf + host_result;
+    while (host_buf_ptr < host_buf_end) {
+        struct dirent *host_dp = (struct dirent *)host_buf_ptr;
+        int namelen = strlen(host_dp->d_name);
+
+        // Actual size includes padded string rounded up for alignment.
+        // Subtract 256 for dummy char array in Tru64::dirent definition.
+        // Add 1 to namelen for terminating null char.
+        int tgt_bufsize = sizeof(Tru64::dirent) - 256 + RoundUp(namelen+1, 8);
+        TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
+        tgt_dp->d_ino = host_dp->d_ino;
+        tgt_dp->d_reclen = tgt_bufsize;
+        tgt_dp->d_namlen = namelen;
+        strcpy(tgt_dp->d_name, host_dp->d_name);
+        tgt_dp.copyOut(xc->mem);
+
+        tgt_buf_ptr += tgt_bufsize;
+        host_buf_ptr += host_dp->d_reclen;
+    }
+
+    delete [] host_buf;
+
+    *basep = host_basep;
+    basep.copyOut(xc->mem);
+
+    return (tgt_buf_ptr - tgt_buf);
+}
+
+
+static
+int
+sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
+              ExecContext *xc)
+{
+    RegFile *regs = &xc->regs;
+    TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
+
+    sc.copyIn(xc->mem);
+
+    // Restore state from sigcontext structure.
+    // Note that we'll advance PC <- NPC before the end of the cycle,
+    // so we need to restore the desired PC into NPC.
+    // The current regs->pc will get clobbered.
+    regs->npc = sc->sc_pc;
+
+    for (int i = 0; i < 31; ++i) {
+        regs->intRegFile[i] = sc->sc_regs[i];
+        regs->floatRegFile.q[i] = sc->sc_fpregs[i];
+    }
+
+    regs->miscRegs.fpcr = sc->sc_fpcr;
+
+    return 0;
+}
+
+static
+int
+tableFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    int id = xc->getSyscallArg(0);             // table ID
+    int index = xc->getSyscallArg(1);  // index into table
+    // arg 2 is buffer pointer; type depends on table ID
+    int nel = xc->getSyscallArg(3);            // number of elements
+    int lel = xc->getSyscallArg(4);            // expected element size
+
+    switch (id) {
+      case Tru64::TBL_SYSINFO: {
+          if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
+              return -EINVAL;
+          TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
+
+          const int clk_hz = one_million;
+          elp->si_user = curTick / (ticksPerSecond / clk_hz);
+          elp->si_nice = 0;
+          elp->si_sys = 0;
+          elp->si_idle = 0;
+          elp->wait = 0;
+          elp->si_hz = clk_hz;
+          elp->si_phz = clk_hz;
+          elp->si_boottime = seconds_since_epoch; // seconds since epoch?
+          elp->si_max_procs = process->numCpus();
+          elp.copyOut(xc->mem);
+          return 0;
+      }
+
+      default:
+        cerr << "table(): id " << id << " unknown." << endl;
+        return -EINVAL;
+    }
+}
+
+static SyscallDesc syscallDescs[];
+
+static const int Num_Syscall_Descs;
+static const int Max_Syscall_Desc;
+
+//
+// Mach syscalls -- identified by negated syscall numbers
+//
+
+// Create a stack region for a thread.
+static
+int
+stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
+                 ExecContext *xc)
+{
+    TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
+
+    argp.copyIn(xc->mem);
+
+    // if the user chose an address, just let them have it.  Otherwise
+    // pick one for them.
+    if (argp->address == 0) {
+        argp->address = process->next_thread_stack_base;
+        int stack_size = (argp->rsize + argp->ysize + argp->gsize);
+        process->next_thread_stack_base -= stack_size;
+        argp.copyOut(xc->mem);
+    }
+
+    return 0;
+}
+
+static
+const int NXM_LIB_VERSION = 301003;
+
+//
+// This call sets up the interface between the user and kernel
+// schedulers by creating a shared-memory region.  The shared memory
+// region has several structs, some global, some per-RAD, some per-VP.
+//
+static
+int
+nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
+                 ExecContext *xc)
+{
+    TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
+    TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
+
+    attrp.copyIn(xc->mem);
+
+    if (attrp->nxm_version != NXM_LIB_VERSION) {
+        cerr << "nxm_task_init: thread library version mismatch! "
+             << "got " << attrp->nxm_version
+             << ", expected " << NXM_LIB_VERSION << endl;
+        abort();
+    }
+
+    if (attrp->flags != Tru64::NXM_TASK_INIT_VP) {
+        cerr << "nxm_task_init: bad flag value " << attrp->flags
+             << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
+        abort();
+    }
+
+    const Addr base_addr = 0x12000; // was 0x3f0000000LL;
+    Addr cur_addr = base_addr; // next addresses to use
+    // first comes the config_info struct
+    Addr config_addr = cur_addr;
+    cur_addr += sizeof(Tru64::nxm_config_info);
+    // next comes the per-cpu state vector
+    Addr slot_state_addr = cur_addr;
+    int slot_state_size = process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+    cur_addr += slot_state_size;
+    // now the per-RAD state struct (we only support one RAD)
+    cur_addr = 0x14000;        // bump up addr for alignment
+    Addr rad_state_addr = cur_addr;
+    int rad_state_size =
+        (sizeof(Tru64::nxm_shared)
+         + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+    cur_addr += rad_state_size;
+
+    // now initialize a config_info struct and copy it out to user space
+    TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
+
+    config->nxm_nslots_per_rad = process->numCpus();
+    config->nxm_nrads = 1;     // only one RAD in our system!
+    config->nxm_slot_state = slot_state_addr;
+    config->nxm_rad[0] = rad_state_addr;
+
+    config.copyOut(xc->mem);
+
+    // initialize the slot_state array and copy it out
+    TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
+                                                     slot_state_size);
+    for (int i = 0; i < process->numCpus(); ++i) {
+        // CPU 0 is bound to the calling process; all others are available
+        slot_state[i] = (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
+    }
+
+    slot_state.copyOut(xc->mem);
+
+    // same for the per-RAD "shared" struct.  Note that we need to
+    // allocate extra bytes for the per-VP array which is embedded at
+    // the end.
+    TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
+                                              rad_state_size);
+
+    rad_state->nxm_callback = attrp->nxm_callback;
+    rad_state->nxm_version = attrp->nxm_version;
+    rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
+    for (int i = 0; i < process->numCpus(); ++i) {
+        Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
+        ssp->nxm_u.sigmask = 0;
+        ssp->nxm_u.sig = 0;
+        ssp->nxm_u.flags = 0;
+        ssp->nxm_u.cancel_state = 0;
+        ssp->nxm_u.nxm_ssig = 0;
+        ssp->nxm_bits = 0;
+        ssp->nxm_quantum = attrp->nxm_quantum;
+        ssp->nxm_set_quantum = attrp->nxm_quantum;
+        ssp->nxm_sysevent = 0;
+
+        if (i == 0) {
+            uint64_t uniq = xc->regs.miscRegs.uniq;
+            ssp->nxm_u.pth_id = uniq + attrp->nxm_uniq_offset;
+            ssp->nxm_u.nxm_active = uniq | 1;
+        }
+        else {
+            ssp->nxm_u.pth_id = 0;
+            ssp->nxm_u.nxm_active = 0;
+        }
+    }
+
+    rad_state.copyOut(xc->mem);
+
+    //
+    // copy pointer to shared config area out to user
+    //
+    *configptr_ptr = config_addr;
+    configptr_ptr.copyOut(xc->mem);
+
+    return 0;
+}
+
+
+static void
+init_exec_context(ExecContext *ec,
+                  Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
+{
+    memset(&ec->regs, 0, sizeof(ec->regs));
+
+    ec->regs.intRegFile[ArgumentReg0] = attrp->registers.a0;
+    ec->regs.intRegFile[27/*t12*/] = attrp->registers.pc;
+    ec->regs.intRegFile[StackPointerReg] = attrp->registers.sp;
+    ec->regs.miscRegs.uniq = uniq_val;
+
+    ec->regs.pc = attrp->registers.pc;
+    ec->regs.npc = attrp->registers.pc + sizeof(MachInst);
+
+    ec->setStatus(ExecContext::Active);
+}
+
+static
+int
+nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
+                      ExecContext *xc)
+{
+    TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0));
+    TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1));
+    int thread_index = xc->getSyscallArg(2);
+
+    // get attribute args
+    attrp.copyIn(xc->mem);
+
+    if (attrp->version != NXM_LIB_VERSION) {
+        cerr << "nxm_thread_create: thread library version mismatch! "
+             << "got " << attrp->version
+             << ", expected " << NXM_LIB_VERSION << endl;
+        abort();
+    }
+
+    if (thread_index < 0 | thread_index > process->numCpus()) {
+        cerr << "nxm_thread_create: bad thread index " << thread_index
+             << endl;
+        abort();
+    }
+
+    // On a real machine, the per-RAD shared structure is in
+    // shared memory, so both the user and kernel can get at it.
+    // We don't have that luxury, so we just copy it in and then
+    // back out again.
+    int rad_state_size =
+        (sizeof(Tru64::nxm_shared) +
+         (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+
+    TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
+                                              rad_state_size);
+    rad_state.copyIn(xc->mem);
+
+    uint64_t uniq_val = attrp->pthid - rad_state->nxm_uniq_offset;
+
+    if (attrp->type == Tru64::NXM_TYPE_MANAGER) {
+        // DEC pthreads seems to always create one of these (in
+        // addition to N application threads), but we don't use it,
+        // so don't bother creating it.
+
+        // This is supposed to be a port number.  Make something up.
+        *kidp = 99;
+        kidp.copyOut(xc->mem);
+
+        return 0;
+    } else if (attrp->type == Tru64::NXM_TYPE_VP) {
+        // A real "virtual processor" kernel thread.  Need to fork
+        // this thread on another CPU.
+        Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
+
+        if (ssp->nxm_u.nxm_active != 0)
+            return Tru64::KERN_NOT_RECEIVER;
+
+        ssp->nxm_u.pth_id = attrp->pthid;
+        ssp->nxm_u.nxm_active = uniq_val | 1;
+
+        rad_state.copyOut(xc->mem);
+
+        Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
+        int slot_state_size = process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+
+        TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
+                                                         slot_state_size);
+
+        slot_state.copyIn(xc->mem);
+
+        if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
+            cerr << "nxm_thread_createFunc: requested VP slot "
+                 << thread_index << " not available!" << endl;
+            fatal("");
+        }
+
+        slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
+
+        slot_state.copyOut(xc->mem);
+
+        // Find a free simulator execution context.
+        for (int i = 0; i < process->numCpus(); ++i) {
+            ExecContext *xc = process->execContexts[i];
+
+            if (xc->status() == ExecContext::Unallocated) {
+                // inactive context... grab it
+                init_exec_context(xc, attrp, uniq_val);
+
+                // This is supposed to be a port number, but we'll try
+                // and get away with just sticking the thread index
+                // here.
+                *kidp = thread_index;
+                kidp.copyOut(xc->mem);
+
+                return 0;
+            }
+        }
+
+        // fell out of loop... no available inactive context
+        cerr << "nxm_thread_create: no idle contexts available." << endl;
+        abort();
+    } else {
+        cerr << "nxm_thread_create: can't handle thread type "
+             << attrp->type << endl;
+        abort();
+    }
+
+    return 0;
+}
+
+
+static
+int
+nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
+             ExecContext *xc)
+{
+    return 0;
+}
+
+static
+int
+nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+                     ExecContext *xc)
+{
+    uint64_t tid = xc->getSyscallArg(0);
+    uint64_t secs = xc->getSyscallArg(1);
+    uint64_t flags = xc->getSyscallArg(2);
+    uint64_t action = xc->getSyscallArg(3);
+    uint64_t usecs = xc->getSyscallArg(4);
+
+    cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs
+         << " " << flags << " " << action << " " << usecs << endl;
+
+    return 0;
+}
+
+
+static
+int
+nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+              ExecContext *xc)
+{
+    Addr uaddr = xc->getSyscallArg(0);
+    uint64_t val = xc->getSyscallArg(1);
+    uint64_t secs = xc->getSyscallArg(2);
+    uint64_t usecs = xc->getSyscallArg(3);
+    uint64_t flags = xc->getSyscallArg(4);
+
+    BaseCPU *cpu = xc->cpu;
+
+    cout << cpu->name() << ": nxm_block " << hex << uaddr << dec << " " << val
+         << " " << secs << " " << usecs
+         << " " << flags << endl;
+
+    return 0;
+}
+
+
+static
+int
+nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
+              ExecContext *xc)
+{
+    Addr uaddr = xc->getSyscallArg(0);
+
+    cout << xc->cpu->name() << ": nxm_unblock "
+         << hex << uaddr << dec << endl;
+
+    return 0;
+}
+
+
+static
+int
+swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
+              ExecContext *xc)
+{
+    // Attempts to switch to another runnable thread (if there is
+    // one).  Returns false if there are no other threads to run
+    // (i.e., the thread can reasonably spin-wait) or true if there
+    // are other threads.
+    //
+    // Since we assume at most one "kernel" thread per CPU, it's
+    // always safe to return false here.
+    return false;
+}
+
+
+// just activate one by default
+static int
+activate_waiting_context(Addr uaddr, Process *process,
+                         bool activate_all = false)
+{
+    int num_activated = 0;
+
+    list<Process::WaitRec>::iterator i = process->waitList.begin();
+    list<Process::WaitRec>::iterator end = process->waitList.end();
+
+    while (i != end && (num_activated == 0 || activate_all)) {
+        if (i->waitChan == uaddr) {
+            // found waiting process: make it active
+            ExecContext *newCtx = i->waitingContext;
+            assert(newCtx->status() == ExecContext::Suspended);
+            newCtx->setStatus(ExecContext::Active);
+
+            // get rid of this record
+            i = process->waitList.erase(i);
+
+            ++num_activated;
+        } else {
+            ++i;
+        }
+    }
+
+    return num_activated;
+}
+
+
+static void
+m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+{
+    TypedBufferArg<uint64_t> lockp(uaddr);
+
+    lockp.copyIn(xc->mem);
+
+    if (*lockp == 0) {
+        // lock is free: grab it
+        *lockp = 1;
+        lockp.copyOut(xc->mem);
+    } else {
+        // lock is busy: disable until free
+        process->waitList.push_back(Process::WaitRec(uaddr, xc));
+        xc->setStatus(ExecContext::Suspended);
+    }
+}
+
+static void
+m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+{
+    TypedBufferArg<uint64_t> lockp(uaddr);
+
+    lockp.copyIn(xc->mem);
+    assert(*lockp != 0);
+
+    // Check for a process waiting on the lock.
+    int num_waiting = activate_waiting_context(uaddr, process);
+
+    // clear lock field if no waiting context is taking over the lock
+    if (num_waiting == 0) {
+        *lockp = 0;
+        lockp.copyOut(xc->mem);
+    }
+}
+
+
+static
+int
+m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
+                  ExecContext *xc)
+{
+    Addr uaddr = xc->getSyscallArg(0);
+
+    m5_lock_mutex(uaddr, process, xc);
+
+    // Return 0 since we will always return to the user with the lock
+    // acquired.  We will just keep the context inactive until that is
+    // true.
+    return 0;
+}
+
+
+static
+int
+m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
+                     ExecContext *xc)
+{
+    Addr uaddr = xc->getSyscallArg(0);
+    TypedBufferArg<uint64_t> lockp(uaddr);
+
+    lockp.copyIn(xc->mem);
+
+    if (*lockp == 0) {
+        // lock is free: grab it
+        *lockp = 1;
+        lockp.copyOut(xc->mem);
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+
+static
+int
+m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
+                    ExecContext *xc)
+{
+    Addr uaddr = xc->getSyscallArg(0);
+
+    m5_unlock_mutex(uaddr, process, xc);
+
+    return 0;
+}
+
+
+static
+int
+m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
+                   ExecContext *xc)
+{
+    Addr cond_addr = xc->getSyscallArg(0);
+
+    // Wqake up one process waiting on the condition variable.
+    activate_waiting_context(cond_addr, process);
+
+    return 0;
+}
+
+
+static
+int
+m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
+                      ExecContext *xc)
+{
+    Addr cond_addr = xc->getSyscallArg(0);
+
+    // Wake up all processes waiting on the condition variable.
+    activate_waiting_context(cond_addr, process, true);
+
+    return 0;
+}
+
+
+static
+int
+m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
+                 ExecContext *xc)
+{
+    Addr cond_addr = xc->getSyscallArg(0);
+    Addr lock_addr = xc->getSyscallArg(1);
+    TypedBufferArg<uint64_t> condp(cond_addr);
+    TypedBufferArg<uint64_t> lockp(lock_addr);
+
+    // user is supposed to acquire lock before entering
+    lockp.copyIn(xc->mem);
+    assert(*lockp != 0);
+
+    m5_unlock_mutex(lock_addr, process, xc);
+
+    process->waitList.push_back(Process::WaitRec(cond_addr, xc));
+    xc->setStatus(ExecContext::Suspended);
+
+    return 0;
+}
+
+
+static
+int
+m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
+                   ExecContext *xc)
+{
+    assert(xc->status() == ExecContext::Active);
+    xc->setStatus(ExecContext::Unallocated);
+
+    return 0;
+}
+
+
+static SyscallDesc machSyscallDescs[];
+
+static const int Num_Mach_Syscall_Descs;
+static const int Max_Mach_Syscall_Desc;
+
+// Since negated values are used to identify Mach syscalls, the
+// minimum (signed) valid syscall number is the negated max Mach
+// syscall number.
+static const int Min_Syscall_Desc;
+
+//
+// helper function for invoking syscalls
+//
+static
+void
+doSyscall(int callnum, Process *process, ExecContext *xc)
+{
+    if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) {
+        cerr << "Syscall " << callnum << " out of range" << endl;
+        abort();
+    }
+
+    SyscallDesc *desc =
+        (callnum < 0) ? &machSyscallDescs[-callnum] : &syscallDescs[callnum];
+
+    desc->doSyscall(callnum, process, xc);
+}
+
+//
+// Indirect syscall invocation (call #0)
+//
+static
+int
+indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
+                    ExecContext *xc)
+{
+    int new_callnum = xc->getSyscallArg(0);
+
+    for (int i = 0; i < 5; ++i)
+        xc->setSyscallArg(i, xc->getSyscallArg(i+1));
+
+    doSyscall(new_callnum, process, xc);
+
+    return 0;
+}
+
+
+};  // class Tru64
+
+
+// open(2) flags translation table
+OpenFlagTransTable Tru64::openFlagTable[] = {
+  /* target flag */    /* host flag */
+#ifdef _MSC_VER
+  { Tru64::TGT_O_RDONLY,       _O_RDONLY },
+  { Tru64::TGT_O_WRONLY,       _O_WRONLY },
+  { Tru64::TGT_O_RDWR,         _O_RDWR },
+  { Tru64::TGT_O_APPEND,       _O_APPEND },
+  { Tru64::TGT_O_CREAT,                _O_CREAT },
+  { Tru64::TGT_O_TRUNC,                        _O_TRUNC },
+  { Tru64::TGT_O_EXCL,                 _O_EXCL },
+#ifdef _O_NONBLOCK
+  { Tru64::TGT_O_NONBLOCK,     _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+  { Tru64::TGT_O_NOCTTY,       _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+  { Tru64::TGT_O_SYNC, _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+  { Tru64::TGT_O_RDONLY,       O_RDONLY },
+  { Tru64::TGT_O_WRONLY,       O_WRONLY },
+  { Tru64::TGT_O_RDWR,         O_RDWR },
+  { Tru64::TGT_O_APPEND,       O_APPEND },
+  { Tru64::TGT_O_CREAT,                O_CREAT },
+  { Tru64::TGT_O_TRUNC,                O_TRUNC },
+  { Tru64::TGT_O_EXCL,         O_EXCL },
+  { Tru64::TGT_O_NONBLOCK,     O_NONBLOCK },
+  { Tru64::TGT_O_NOCTTY,       O_NOCTTY },
+#ifdef O_SYNC
+  { Tru64::TGT_O_SYNC,         O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int Tru64::NUM_OPEN_FLAGS = (sizeof(Tru64::openFlagTable)/sizeof(Tru64::openFlagTable[0]));
+
+const char *Tru64::hostname = "m5.eecs.umich.edu";
+
+SyscallDesc Tru64::syscallDescs[] = {
+    /* 0 */ SyscallDesc("syscall (#0)", indirectSyscallFunc,
+                        SyscallDesc::SuppressReturnValue),
+    /* 1 */ SyscallDesc("exit", exitFunc),
+    /* 2 */ SyscallDesc("fork", unimplementedFunc),
+    /* 3 */ SyscallDesc("read", readFunc),
+    /* 4 */ SyscallDesc("write", writeFunc),
+    /* 5 */ SyscallDesc("old_open", unimplementedFunc),
+    /* 6 */ SyscallDesc("close", closeFunc),
+    /* 7 */ SyscallDesc("wait4", unimplementedFunc),
+    /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
+    /* 9 */ SyscallDesc("link", unimplementedFunc),
+    /* 10 */ SyscallDesc("unlink", unimplementedFunc),
+    /* 11 */ SyscallDesc("execv", unimplementedFunc),
+    /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+    /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
+    /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+    /* 15 */ SyscallDesc("chmod", unimplementedFunc),
+    /* 16 */ SyscallDesc("chown", unimplementedFunc),
+    /* 17 */ SyscallDesc("obreak", obreakFunc),
+    /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
+    /* 19 */ SyscallDesc("lseek", lseekFunc),
+    /* 20 */ SyscallDesc("getpid", getpidFunc),
+    /* 21 */ SyscallDesc("mount", unimplementedFunc),
+    /* 22 */ SyscallDesc("unmount", unimplementedFunc),
+    /* 23 */ SyscallDesc("setuid", setuidFunc),
+    /* 24 */ SyscallDesc("getuid", getuidFunc),
+    /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
+    /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
+    /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
+    /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
+    /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
+    /* 30 */ SyscallDesc("accept", unimplementedFunc),
+    /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
+    /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
+    /* 33 */ SyscallDesc("access", unimplementedFunc),
+    /* 34 */ SyscallDesc("chflags", unimplementedFunc),
+    /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
+    /* 36 */ SyscallDesc("sync", unimplementedFunc),
+    /* 37 */ SyscallDesc("kill", unimplementedFunc),
+    /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
+    /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
+    /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
+    /* 41 */ SyscallDesc("dup", unimplementedFunc),
+    /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+    /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
+    /* 44 */ SyscallDesc("profil", unimplementedFunc),
+    /* 45 */ SyscallDesc("open", openFunc<Tru64>),
+    /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
+    /* 47 */ SyscallDesc("getgid", getgidFunc),
+    /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
+    /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
+    /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
+    /* 51 */ SyscallDesc("acct", unimplementedFunc),
+    /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
+    /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
+    /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>),
+    /* 55 */ SyscallDesc("reboot", unimplementedFunc),
+    /* 56 */ SyscallDesc("revoke", unimplementedFunc),
+    /* 57 */ SyscallDesc("symlink", unimplementedFunc),
+    /* 58 */ SyscallDesc("readlink", unimplementedFunc),
+    /* 59 */ SyscallDesc("execve", unimplementedFunc),
+    /* 60 */ SyscallDesc("umask", unimplementedFunc),
+    /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+    /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
+    /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
+    /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
+    /* 65 */ SyscallDesc("mremap", unimplementedFunc),
+    /* 66 */ SyscallDesc("vfork", unimplementedFunc),
+    /* 67 */ SyscallDesc("pre_F64_stat", unimplementedFunc),
+    /* 68 */ SyscallDesc("pre_F64_lstat", unimplementedFunc),
+    /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
+    /* 70 */ SyscallDesc("sstk", unimplementedFunc),
+    /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>),
+    /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
+    /* 73 */ SyscallDesc("munmap", munmapFunc),
+    /* 74 */ SyscallDesc("mprotect", ignoreFunc),
+    /* 75 */ SyscallDesc("madvise", unimplementedFunc),
+    /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
+    /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
+    /* 78 */ SyscallDesc("mincore", unimplementedFunc),
+    /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
+    /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
+    /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
+    /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
+    /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
+    /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
+    /* 85 */ SyscallDesc("table", tableFunc),
+    /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
+    /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
+    /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
+    /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
+    /* 90 */ SyscallDesc("dup2", unimplementedFunc),
+    /* 91 */ SyscallDesc("pre_F64_fstat", unimplementedFunc),
+    /* 92 */ SyscallDesc("fcntl", fcntlFunc),
+    /* 93 */ SyscallDesc("select", unimplementedFunc),
+    /* 94 */ SyscallDesc("poll", unimplementedFunc),
+    /* 95 */ SyscallDesc("fsync", unimplementedFunc),
+    /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
+    /* 97 */ SyscallDesc("socket", unimplementedFunc),
+    /* 98 */ SyscallDesc("connect", unimplementedFunc),
+    /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
+    /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
+    /* 101 */ SyscallDesc("old_send", unimplementedFunc),
+    /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
+    /* 103 */ SyscallDesc("sigreturn", sigreturnFunc,
+                          SyscallDesc::SuppressReturnValue),
+    /* 104 */ SyscallDesc("bind", unimplementedFunc),
+    /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
+    /* 106 */ SyscallDesc("listen", unimplementedFunc),
+    /* 107 */ SyscallDesc("plock", unimplementedFunc),
+    /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
+    /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
+    /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
+    /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
+    /* 112 */ SyscallDesc("sigstack", ignoreFunc),
+    /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
+    /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
+    /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
+    /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Tru64>),
+    /* 117 */ SyscallDesc("getrusage", getrusageFunc<Tru64>),
+    /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
+    /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
+    /* 120 */ SyscallDesc("readv", unimplementedFunc),
+    /* 121 */ SyscallDesc("writev", unimplementedFunc),
+    /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
+    /* 123 */ SyscallDesc("fchown", unimplementedFunc),
+    /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
+    /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
+    /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
+    /* 127 */ SyscallDesc("setregid", unimplementedFunc),
+    /* 128 */ SyscallDesc("rename", unimplementedFunc),
+    /* 129 */ SyscallDesc("truncate", unimplementedFunc),
+    /* 130 */ SyscallDesc("ftruncate", unimplementedFunc),
+    /* 131 */ SyscallDesc("flock", unimplementedFunc),
+    /* 132 */ SyscallDesc("setgid", unimplementedFunc),
+    /* 133 */ SyscallDesc("sendto", unimplementedFunc),
+    /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
+    /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
+    /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
+    /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
+    /* 138 */ SyscallDesc("utimes", unimplementedFunc),
+    /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
+    /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
+    /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
+    /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
+    /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
+    /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>),
+    /* 145 */ SyscallDesc("setrlimit", unimplementedFunc),
+    /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
+    /* 147 */ SyscallDesc("setsid", unimplementedFunc),
+    /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
+    /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
+    /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
+    /* 151 */ SyscallDesc("pread", unimplementedFunc),
+    /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
+    /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
+    /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
+    /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
+    /* 156 */ SyscallDesc("sigaction", ignoreFunc),
+    /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
+    /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
+    /* 159 */ SyscallDesc("getdirentries", getdirentriesFunc),
+    /* 160 */ SyscallDesc("pre_F64_statfs", unimplementedFunc),
+    /* 161 */ SyscallDesc("pre_F64_fstatfs", unimplementedFunc),
+    /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
+    /* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
+    /* 164 */ SyscallDesc("getfh", unimplementedFunc),
+    /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
+    /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
+    /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
+    /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
+    /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
+    /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
+    /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
+    /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
+    /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
+    /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
+    /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
+    /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
+    /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
+    /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
+    /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
+    /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
+    /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
+    /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
+    /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
+    /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
+    /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
+    /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
+    /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
+    /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
+    /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
+    /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
+    /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
+    /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
+    /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
+    /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
+    /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
+    /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
+    /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
+    /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
+    /* 199 */ SyscallDesc("swapon", unimplementedFunc),
+    /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
+    /* 201 */ SyscallDesc("msgget", unimplementedFunc),
+    /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
+    /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
+    /* 204 */ SyscallDesc("semctl", unimplementedFunc),
+    /* 205 */ SyscallDesc("semget", unimplementedFunc),
+    /* 206 */ SyscallDesc("semop", unimplementedFunc),
+    /* 207 */ SyscallDesc("uname", unameFunc),
+    /* 208 */ SyscallDesc("lchown", unimplementedFunc),
+    /* 209 */ SyscallDesc("shmat", unimplementedFunc),
+    /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
+    /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
+    /* 212 */ SyscallDesc("shmget", unimplementedFunc),
+    /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
+    /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
+    /* 215 */ SyscallDesc("msleep", unimplementedFunc),
+    /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
+    /* 217 */ SyscallDesc("msync", unimplementedFunc),
+    /* 218 */ SyscallDesc("signal", unimplementedFunc),
+    /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
+    /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
+    /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
+    /* 222 */ SyscallDesc("security", unimplementedFunc),
+    /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
+    /* 224 */ SyscallDesc("stat", statFunc<Tru64>),
+    /* 225 */ SyscallDesc("lstat", lstatFunc<Tru64>),
+    /* 226 */ SyscallDesc("fstat", fstatFunc<Tru64>),
+    /* 227 */ SyscallDesc("statfs", unimplementedFunc),
+    /* 228 */ SyscallDesc("fstatfs", unimplementedFunc),
+    /* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
+    /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
+    /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
+    /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
+    /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
+    /* 234 */ SyscallDesc("getsid", unimplementedFunc),
+    /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
+    /* 236 */ SyscallDesc("waitid", unimplementedFunc),
+    /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
+    /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
+    /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
+    /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
+    /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
+    /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
+    /* 243 */ SyscallDesc("fuser", unimplementedFunc),
+    /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
+    /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
+    /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
+    /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
+    /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
+    /* 249 */ SyscallDesc("sync2", unimplementedFunc),
+    /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
+    /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
+    /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
+    /* 253 */ SyscallDesc("audgen", unimplementedFunc),
+    /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
+    /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
+    /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
+    /* 257 */ SyscallDesc("setsysinfo", unimplementedFunc),
+    /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
+    /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
+    /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
+    /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
+    /* 262 */ SyscallDesc("oflock", unimplementedFunc),
+    /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
+    /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
+    /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
+    /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
+};
+
+const int Tru64::Num_Syscall_Descs =
+        sizeof(Tru64::syscallDescs) / sizeof(SyscallDesc);
+
+const int Tru64::Max_Syscall_Desc = Tru64::Num_Syscall_Descs - 1;
+
+SyscallDesc Tru64::machSyscallDescs[] = {
+    /* 0 */  SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 1 */  SyscallDesc("m5_mutex_lock", m5_mutex_lockFunc),
+    /* 2 */  SyscallDesc("m5_mutex_trylock", m5_mutex_trylockFunc),
+    /* 3 */  SyscallDesc("m5_mutex_unlock", m5_mutex_unlockFunc),
+    /* 4 */  SyscallDesc("m5_cond_signal", m5_cond_signalFunc),
+    /* 5 */  SyscallDesc("m5_cond_broadcast", m5_cond_broadcastFunc),
+    /* 6 */  SyscallDesc("m5_cond_wait", m5_cond_waitFunc),
+    /* 7 */  SyscallDesc("m5_thread_exit", m5_thread_exitFunc),
+    /* 8 */  SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 9 */  SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 10 */ SyscallDesc("task_self", unimplementedFunc),
+    /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
+    /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
+    /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
+    /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
+    /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
+    /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
+    /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 24 */ SyscallDesc("nxm_block", nxm_blockFunc),
+    /* 25 */ SyscallDesc("nxm_unblock", nxm_unblockFunc),
+    /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
+    /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
+    /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
+    /* 32 */ SyscallDesc("nxm_thread_create", nxm_thread_createFunc),
+    /* 33 */ SyscallDesc("nxm_task_init", nxm_task_initFunc),
+    /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 35 */ SyscallDesc("nxm_idle", nxm_idleFunc),
+    /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
+    /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
+    /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
+    /* 39 */ SyscallDesc("nxm_thread_block", nxm_thread_blockFunc),
+    /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
+    /* 41 */ SyscallDesc("init_process", unimplementedFunc),
+    /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
+    /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
+    /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
+    /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
+    /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
+    /* 47 */ SyscallDesc("stack_create", stack_createFunc),
+    /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
+    /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
+    /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
+    /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
+    /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
+    /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 55 */ SyscallDesc("host_self", unimplementedFunc),
+    /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
+    /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 59 */ SyscallDesc("swtch_pri", swtch_priFunc),
+    /* 60 */ SyscallDesc("swtch", unimplementedFunc),
+    /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
+    /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
+    /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
+    /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
+    /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
+    /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
+    /* 67 */ SyscallDesc("nxm_swtch_pri", swtch_priFunc),
+    /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
+    /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
+    /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
+    /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
+    /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
+    /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
+    /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
+    /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
+    /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
+    /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
+    /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
+    /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
+    /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
+    /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
+    /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
+};
+
+const int Tru64::Num_Mach_Syscall_Descs =
+                sizeof(Tru64::machSyscallDescs) / sizeof(SyscallDesc);
+const int Tru64::Max_Mach_Syscall_Desc = Tru64::Num_Mach_Syscall_Descs - 1;
+const int Tru64::Min_Syscall_Desc = -Tru64::Max_Mach_Syscall_Desc;
+
+
+void
+AlphaTru64Process::syscall(ExecContext *xc)
+{
+    num_syscalls++;
+
+    int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
+
+    Tru64::doSyscall(callnum, this, xc);
+}
+
+
+AlphaTru64Process::AlphaTru64Process(const std::string &name,
+                                     ObjectFile *objFile,
+                                     int stdin_fd,
+                                     int stdout_fd,
+                                     int stderr_fd,
+                                     std::vector<std::string> &argv,
+                                     std::vector<std::string> &envp)
+    : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp)
+{
+}
diff --git a/arch/alpha/alpha_tru64_process.hh b/arch/alpha/alpha_tru64_process.hh
new file mode 100644 (file)
index 0000000..2b03d66
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ALPHA_TRU64_PROCESS_HH__
+#define __ALPHA_TRU64_PROCESS_HH__
+
+#include "sim/process.hh"
+
+class AlphaTru64Process : public LiveProcess
+{
+  public:
+    AlphaTru64Process(const std::string &name,
+                      ObjectFile *objFile,
+                      int stdin_fd, int stdout_fd, int stderr_fd,
+                      std::vector<std::string> &argv,
+                      std::vector<std::string> &envp);
+
+    virtual void syscall(ExecContext *xc);
+};
+
+
+#endif // __ALPHA_TRU64_PROCESS_HH__
diff --git a/arch/alpha/fake_syscall.cc b/arch/alpha/fake_syscall.cc
deleted file mode 100644 (file)
index dc5619d..0000000
+++ /dev/null
@@ -1,1845 +0,0 @@
-/*
- * Copyright (c) 2003 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>    // for memset()
-#include <dirent.h>
-
-#include "sim/host.hh"
-#include "cpu/base_cpu.hh"
-#include "mem/functional_mem/functional_memory.hh"
-#include "sim/prog.hh"
-#include "cpu/exec_context.hh"
-#include "sim/fake_syscall.hh"
-#include "sim/sim_events.hh"
-
-#include "targetarch/osf_syscalls.h"
-#include "sim/universe.hh"     // for curTick & ticksPerSecond
-
-#include "base/trace.hh"
-
-using namespace std;
-
-//
-// System call descriptor
-//
-class SyscallDesc {
-
-  public:
-
-    typedef int (*FuncPtr)(SyscallDesc *, int num,
-                           Process *, ExecContext *);
-
-    const char *name;
-    FuncPtr funcPtr;
-    int flags;
-
-    enum Flags {
-        SuppressReturnValue = 1
-    };
-
-    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
-        : name(_name), funcPtr(_funcPtr), flags(_flags)
-    {
-    }
-
-    int doFunc(int num, Process *proc, ExecContext *xc)
-    {
-        return (*funcPtr)(this, num, proc, xc);
-    }
-};
-
-
-class BaseBufferArg {
-
-  public:
-
-    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
-    {
-        bufPtr = new uint8_t[size];
-        // clear out buffer: in case we only partially populate this,
-        // and then do a copyOut(), we want to make sure we don't
-        // introduce any random junk into the simulated address space
-        memset(bufPtr, 0, size);
-    }
-
-    virtual ~BaseBufferArg() { delete [] bufPtr; }
-
-    //
-    // copy data into simulator space (read from target memory)
-    //
-    virtual bool copyIn(FunctionalMemory *mem)
-    {
-        mem->access(Read, addr, bufPtr, size);
-        return true;   // no EFAULT detection for now
-    }
-
-    //
-    // copy data out of simulator space (write to target memory)
-    //
-    virtual bool copyOut(FunctionalMemory *mem)
-    {
-        mem->access(Write, addr, bufPtr, size);
-        return true;   // no EFAULT detection for now
-    }
-
-  protected:
-    Addr addr;
-    int size;
-    uint8_t *bufPtr;
-};
-
-
-class BufferArg : public BaseBufferArg
-{
-  public:
-    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
-    void *bufferPtr()  { return bufPtr; }
-};
-
-template <class T>
-class TypedBufferArg : public BaseBufferArg
-{
-  public:
-    // user can optionally specify a specific number of bytes to
-    // allocate to deal with those structs that have variable-size
-    // arrays at the end
-    TypedBufferArg(Addr _addr, int _size = sizeof(T))
-        : BaseBufferArg(_addr, _size)
-    { }
-
-    // type case
-    operator T*() { return (T *)bufPtr; }
-
-    // dereference operators
-    T& operator*()      { return *((T *)bufPtr); }
-    T* operator->()     { return (T *)bufPtr; }
-    T& operator[](int i) { return ((T *)bufPtr)[i]; }
-};
-
-
-static IntReg
-getArg(ExecContext *xc, int i)
-{
-    return xc->regs.intRegFile[ArgumentReg0 + i];
-}
-
-
-//
-// used to shift args for indirect syscall
-//
-static void
-setArg(ExecContext *xc, int i, IntReg val)
-{
-    xc->regs.intRegFile[ArgumentReg0 + i] = val;
-}
-
-
-static void
-set_return_value(ExecContext *xc, int64_t return_value)
-{
-    // check for error condition.  Alpha syscall convention is to
-    // indicate success/failure in reg a3 (r19) and put the
-    // return value itself in the standard return value reg (v0).
-    const int RegA3 = 19;      // only place this is used
-    if (return_value >= 0) {
-        // no error
-        xc->regs.intRegFile[RegA3] = 0;
-        xc->regs.intRegFile[ReturnValueReg] = return_value;
-    } else {
-        // got an error, return details
-        xc->regs.intRegFile[RegA3] = (IntReg) -1;
-        xc->regs.intRegFile[ReturnValueReg] = -return_value;
-    }
-}
-
-
-int
-getpagesizeFunc(SyscallDesc *desc, int callnum, Process *process,
-                ExecContext *xc)
-{
-    return VMPageSize;
-}
-
-
-int
-obreakFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
-{
-    // change brk addr to first arg
-    process->brk_point = getArg(xc, 0);
-    return process->brk_point;
-}
-
-
-int
-ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    int fd = getArg(xc, 0);
-    unsigned req = getArg(xc, 1);
-
-    DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
-
-    if (fd < 0 || process->sim_fd(fd) < 0) {
-        // doesn't map to any simulator fd: not a valid target fd
-        return -EBADF;
-    }
-
-    switch (req) {
-      case OSF::TIOCISATTY:
-      case OSF::TIOCGETP:
-      case OSF::TIOCSETP:
-      case OSF::TIOCSETN:
-      case OSF::TIOCSETC:
-      case OSF::TIOCGETC:
-        return -ENOTTY;
-
-      default:
-        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...)\n", fd, req);
-    }
-}
-
-
-int
-openFunc(SyscallDesc *desc, int callnum, Process *process,
-         ExecContext *xc)
-{
-    string path;
-
-    if (xc->mem->readString(path, getArg(xc, 0)) != No_Fault)
-        return -EFAULT;
-
-    if (path == "/dev/sysdev0") {
-        // This is a memory-mapped high-resolution timer device on Alpha.
-        // We don't support it, so just punt.
-        DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl;
-        return -ENOENT;
-    }
-
-    int osfFlags = getArg(xc, 1);
-    int mode = getArg(xc, 2);
-    int hostFlags = 0;
-
-    // translate open flags
-    for (int i = 0; i < OSF::NUM_OPEN_FLAGS; i++) {
-        if (osfFlags & OSF::openFlagTable[i].osfFlag) {
-            osfFlags &= ~OSF::openFlagTable[i].osfFlag;
-            hostFlags |= OSF::openFlagTable[i].hostFlag;
-        }
-    }
-
-    // any target flags left?
-    if (osfFlags != 0)
-        cerr << "Syscall: open: cannot decode flags: " <<  osfFlags << endl;
-
-#ifdef __CYGWIN32__
-    hostFlags |= O_BINARY;
-#endif
-
-    // open the file
-    int fd = open(path.c_str(), hostFlags, mode);
-
-    return (fd == -1) ? -errno : process->open_fd(fd);
-}
-
-
-int
-closeFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    int fd = process->sim_fd(getArg(xc, 0));
-    return close(fd);
-}
-
-
-int
-readFunc(SyscallDesc *desc, int callnum, Process *process,
-         ExecContext *xc)
-{
-    int fd = process->sim_fd(getArg(xc, 0));
-    int nbytes = getArg(xc, 2);
-    BufferArg bufArg(getArg(xc, 1), nbytes);
-
-    int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
-
-    if (bytes_read != -1)
-        bufArg.copyOut(xc->mem);
-
-    return bytes_read;
-}
-
-int
-writeFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    int fd = process->sim_fd(getArg(xc, 0));
-    int nbytes = getArg(xc, 2);
-    BufferArg bufArg(getArg(xc, 1), nbytes);
-
-    bufArg.copyIn(xc->mem);
-
-    int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
-
-    fsync(fd);
-
-    return bytes_written;
-}
-
-
-int
-lseekFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    int fd = process->sim_fd(getArg(xc, 0));
-    uint64_t offs = getArg(xc, 1);
-    int whence = getArg(xc, 2);
-
-    off_t result = lseek(fd, offs, whence);
-
-    return (result == (off_t)-1) ? -errno : result;
-}
-
-static
-void
-copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
-{
-    TypedBufferArg<OSF::F64_stat> tgt(addr);
-
-    tgt->st_dev = host->st_dev;
-    tgt->st_ino = host->st_ino;
-    tgt->st_mode = host->st_mode;
-    tgt->st_nlink = host->st_nlink;
-    tgt->st_uid = host->st_uid;
-    tgt->st_gid = host->st_gid;
-    tgt->st_rdev = host->st_rdev;
-    tgt->st_size = host->st_size;
-    tgt->st_atimeX = host->st_atime;
-    tgt->st_mtimeX = host->st_mtime;
-    tgt->st_ctimeX = host->st_ctime;
-    tgt->st_blksize = host->st_blksize;
-    tgt->st_blocks = host->st_blocks;
-
-    tgt.copyOut(mem);
-}
-
-int
-statFunc(SyscallDesc *desc, int callnum, Process *process,
-         ExecContext *xc)
-{
-    string path;
-
-    if (xc->mem->readString(path, getArg(xc, 0)) != No_Fault)
-        return -EFAULT;
-
-    struct stat hostBuf;
-    int result = stat(path.c_str(), &hostBuf);
-
-    if (result < 0)
-        return -errno;
-
-    copyOutStatBuf(xc->mem, getArg(xc, 1), &hostBuf);
-
-    return 0;
-}
-
-
-int
-lstatFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    string path;
-
-    if (xc->mem->readString(path, getArg(xc, 0)) != No_Fault)
-        return -EFAULT;
-
-    struct stat hostBuf;
-    int result = lstat(path.c_str(), &hostBuf);
-
-    if (result < 0)
-        return -errno;
-
-    copyOutStatBuf(xc->mem, getArg(xc, 1), &hostBuf);
-
-    return 0;
-}
-
-int
-fstatFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    int fd = process->sim_fd(getArg(xc, 0));
-
-    DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd);
-
-    if (fd < 0)
-        return -EBADF;
-
-    struct stat hostBuf;
-    int result = fstat(fd, &hostBuf);
-
-    if (result < 0)
-        return -errno;
-
-    copyOutStatBuf(xc->mem, getArg(xc, 1), &hostBuf);
-
-    return 0;
-}
-
-
-//
-// We don't handle mmap().  If the target is really mmaping /dev/zero,
-// we can get away with doing nothing (since the simulator doesn't
-// really check addresses anyway).  Always print a warning, since this
-// could be seriously broken if we're not mapping /dev/zero.
-//
-// Someday we should explicitly check for /dev/zero in open, flag the
-// file descriptor, and fail an mmap to anything else.
-//
-int
-mmapFunc(SyscallDesc *desc, int callnum, Process *process,
-         ExecContext *xc)
-{
-    Addr start = getArg(xc, 0);
-    uint64_t length = getArg(xc, 1);
-    int prot = getArg(xc, 2);
-    int flags = getArg(xc, 3);
-    int fd = process->sim_fd(getArg(xc, 4));
-    int offset = getArg(xc, 5);
-
-    cerr << "Warning: ignoring syscall mmap("
-         << start << ", " << length << ", "
-         << prot << ", " << flags << ", "
-         << fd << " " << getArg(xc, 4) << ", "
-         << offset << ")" << endl;
-
-    return start;
-}
-
-
-const char *hostname = "m5.eecs.umich.edu";
-
-int
-unameFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    TypedBufferArg<OSF::utsname> name(getArg(xc, 0));
-
-    strcpy(name->sysname, "OSF1");
-    strcpy(name->nodename, hostname);
-    strcpy(name->release, "V5.1");
-    strcpy(name->version, "732");
-    strcpy(name->machine, "alpha");
-
-    name.copyOut(xc->mem);
-    return 0;
-}
-
-
-int
-gethostnameFunc(SyscallDesc *desc, int callnum, Process *process,
-                ExecContext *xc)
-{
-    int name_len = getArg(xc, 1);
-    BufferArg name(getArg(xc, 0), name_len);
-
-    strncpy((char *)name.bufferPtr(), hostname, name_len);
-
-    name.copyOut(xc->mem);
-
-    return 0;
-}
-
-
-int
-getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
-               ExecContext *xc)
-{
-    unsigned op = getArg(xc, 0);
-    unsigned nbytes = getArg(xc, 2);
-
-    switch (op) {
-
-      case OSF::GSI_MAX_CPU: {
-          TypedBufferArg<uint32_t> max_cpu(getArg(xc, 1));
-          *max_cpu = process->numCpus();
-          max_cpu.copyOut(xc->mem);
-          return 1;
-      }
-
-      case OSF::GSI_CPUS_IN_BOX: {
-          TypedBufferArg<uint32_t> cpus_in_box(getArg(xc, 1));
-          *cpus_in_box = process->numCpus();
-          cpus_in_box.copyOut(xc->mem);
-          return 1;
-      }
-
-      case OSF::GSI_PHYSMEM: {
-          TypedBufferArg<uint64_t> physmem(getArg(xc, 1));
-          *physmem = 1024 * 1024;      // physical memory in KB
-          physmem.copyOut(xc->mem);
-          return 1;
-      }
-
-      case OSF::GSI_CPU_INFO: {
-          TypedBufferArg<OSF::cpu_info> infop(getArg(xc, 1));
-
-          infop->current_cpu = 0;
-          infop->cpus_in_box = process->numCpus();
-          infop->cpu_type = 57;
-          infop->ncpus = process->numCpus();
-          int cpumask = (1 << process->numCpus()) - 1;
-          infop->cpus_present = infop->cpus_running = cpumask;
-          infop->cpu_binding = 0;
-          infop->cpu_ex_binding = 0;
-          infop->mhz = 667;
-
-          infop.copyOut(xc->mem);
-          return 1;
-        }
-
-      case OSF::GSI_PROC_TYPE: {
-          TypedBufferArg<uint64_t> proc_type(getArg(xc, 1));
-          *proc_type = 11;
-          proc_type.copyOut(xc->mem);
-          return 1;
-      }
-
-      case OSF::GSI_PLATFORM_NAME: {
-          BufferArg bufArg(getArg(xc, 1), nbytes);
-          strncpy((char *)bufArg.bufferPtr(),
-                  "COMPAQ Professional Workstation XP1000",
-                  nbytes);
-          bufArg.copyOut(xc->mem);
-          return 1;
-      }
-
-      case OSF::GSI_CLK_TCK: {
-          TypedBufferArg<uint64_t> clk_hz(getArg(xc, 1));
-          *clk_hz = 1024;
-          clk_hz.copyOut(xc->mem);
-          return 1;
-      }
-
-      default:
-        cerr << "getsysinfo: unknown op " << op << endl;
-        abort();
-        break;
-    }
-
-    return 0;
-}
-
-int
-getpidFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
-{
-    // Make up a PID.  There's no interprocess communication in
-    // fake_syscall mode, so there's no way for a process to know it's
-    // not getting a unique value.
-
-    // This is one of the funky syscalls that has two return values,
-    // with the second one (parent PID) going in r20.
-    xc->regs.intRegFile[20] = 99;
-    return 100;
-}
-
-
-int
-getuidFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
-{
-    // Make up a UID and EUID... it shouldn't matter, and we want the
-    // simulation to be deterministic.
-
-    // EUID goes in r20.
-    xc->regs.intRegFile[20] = 100;     // EUID
-    return 100;                                // UID
-}
-
-
-int
-getgidFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
-{
-    // Get current group ID.  EGID goes in r20.
-    xc->regs.intRegFile[20] = 100;
-    return 100;
-}
-
-
-int
-setuidFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
-{
-    // can't fathom why a benchmark would call this.
-    warn("Ignoring call to setuid(%d)\n", getArg(xc, 0));
-    return 0;
-}
-
-
-int
-fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
-{
-    int fd = getArg(xc,0);
-
-    if (fd < 0 || process->sim_fd(fd) < 0)
-        return -EBADF;
-
-    int cmd = getArg(xc,1);
-    switch (cmd) {
-      case 0: // F_DUPFD
-        // if we really wanted to support this, we'd need to do it
-        // in the target fd space.
-        warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
-        return -EMFILE;
-
-      case 1: // F_GETFD (get fd flags)
-      case 2: // F_SETFD (set fd flags)
-      case 3: // F_GETFL (get file flags)
-      case 4: // F_SETFL (set file flags)
-        // not sure if this is totally valid, but we'll pass it through
-        // to the underlying OS
-        warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
-        return fcntl(process->sim_fd(fd), cmd);
-        // return 0;
-
-      case 7: // F_GETLK  (get lock)
-      case 8: // F_SETLK  (set lock)
-      case 9: // F_SETLKW (set lock and wait)
-        // don't mess with file locking... just act like it's OK
-        warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
-        return 0;
-
-      default:
-        warn("Unknown fcntl command %d\n", cmd);
-        return 0;
-    }
-}
-
-
-int
-getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
-                  ExecContext *xc)
-{
-    int fd = process->sim_fd(getArg(xc, 0));
-    Addr tgt_buf = getArg(xc, 1);
-    int tgt_nbytes = getArg(xc, 2);
-    Addr tgt_basep = getArg(xc, 3);
-
-    char * const host_buf = new char[tgt_nbytes];
-
-    // just pass basep through uninterpreted.
-    TypedBufferArg<int64_t> basep(tgt_basep);
-    basep.copyIn(xc->mem);
-    off_t host_basep = (off_t)*basep;
-    int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
-
-    // check for error
-    if (host_result < 0) {
-        delete [] host_buf;
-        return -errno;
-    }
-
-    // no error: copy results back to target space
-    Addr tgt_buf_ptr = tgt_buf;
-    char *host_buf_ptr = host_buf;
-    char *host_buf_end = host_buf + host_result;
-    while (host_buf_ptr < host_buf_end) {
-        struct dirent *host_dp = (struct dirent *)host_buf_ptr;
-        int namelen = strlen(host_dp->d_name);
-
-        // Actual size includes padded string rounded up for alignment.
-        // Subtract 256 for dummy char array in OSF::dirent definition.
-        // Add 1 to namelen for terminating null char.
-        int tgt_bufsize = sizeof(OSF::dirent) - 256 + RoundUp(namelen+1, 8);
-        TypedBufferArg<OSF::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
-        tgt_dp->d_ino = host_dp->d_ino;
-        tgt_dp->d_reclen = tgt_bufsize;
-        tgt_dp->d_namlen = namelen;
-        strcpy(tgt_dp->d_name, host_dp->d_name);
-        tgt_dp.copyOut(xc->mem);
-
-        tgt_buf_ptr += tgt_bufsize;
-        host_buf_ptr += host_dp->d_reclen;
-    }
-
-    delete [] host_buf;
-
-    *basep = host_basep;
-    basep.copyOut(xc->mem);
-
-    return (tgt_buf_ptr - tgt_buf);
-}
-
-
-int
-getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-{
-    unsigned resource = getArg(xc, 0);
-    TypedBufferArg<OSF::rlimit> rlp(getArg(xc, 1));
-
-    switch (resource) {
-      case OSF::RLIMIT_STACK:
-        // max stack size in bytes: make up a number (2MB for now)
-        rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
-        break;
-
-      default:
-        cerr << "getrlimitFunc: unimplemented resource " << resource << endl;
-        abort();
-        break;
-    }
-
-    rlp.copyOut(xc->mem);
-    return 0;
-}
-
-// 1M usecs in 1 sec, for readability
-static const int one_million = 1000000;
-
-// seconds since the epoch (1/1/1970)... about a billion, by my reckoning
-static const unsigned seconds_since_epoch = 1000000000;
-
-//
-// helper function: populate struct timeval with approximation of
-// current elapsed time
-//
-static void
-getElapsedTime(OSF::timeval *tp)
-{
-    int cycles_per_usec = ticksPerSecond / one_million;
-
-    int elapsed_usecs = curTick / cycles_per_usec;
-    tp->tv_sec = elapsed_usecs / one_million;
-    tp->tv_usec = elapsed_usecs % one_million;
-}
-
-
-int
-gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
-                 ExecContext *xc)
-{
-    TypedBufferArg<OSF::timeval> tp(getArg(xc, 0));
-
-    getElapsedTime(tp);
-    tp->tv_sec += seconds_since_epoch;
-
-    tp.copyOut(xc->mem);
-
-    return 0;
-}
-
-
-int
-getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-{
-    int who = getArg(xc, 0);   // THREAD, SELF, or CHILDREN
-    TypedBufferArg<OSF::rusage> rup(getArg(xc, 1));
-
-    if (who != OSF::RUSAGE_SELF) {
-        // don't really handle THREAD or CHILDREN, but just warn and
-        // plow ahead
-        DCOUT(SyscallWarnings)
-            << "Warning: getrusage() only supports RUSAGE_SELF."
-            << "  Parameter " << who << " ignored." << endl;
-    }
-
-    getElapsedTime(&rup->ru_utime);
-    rup->ru_stime.tv_sec = 0;
-    rup->ru_stime.tv_usec = 0;
-    rup->ru_maxrss = 0;
-    rup->ru_ixrss = 0;
-    rup->ru_idrss = 0;
-    rup->ru_isrss = 0;
-    rup->ru_minflt = 0;
-    rup->ru_majflt = 0;
-    rup->ru_nswap = 0;
-    rup->ru_inblock = 0;
-    rup->ru_oublock = 0;
-    rup->ru_msgsnd = 0;
-    rup->ru_msgrcv = 0;
-    rup->ru_nsignals = 0;
-    rup->ru_nvcsw = 0;
-    rup->ru_nivcsw = 0;
-
-    rup.copyOut(xc->mem);
-
-    return 0;
-}
-
-
-int
-sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-{
-    RegFile *regs = &xc->regs;
-    TypedBufferArg<OSF::sigcontext> sc(getArg(xc, 0));
-
-    sc.copyIn(xc->mem);
-
-    // Restore state from sigcontext structure.
-    // Note that we'll advance PC <- NPC before the end of the cycle,
-    // so we need to restore the desired PC into NPC.
-    // The current regs->pc will get clobbered.
-    regs->npc = sc->sc_pc;
-
-    for (int i = 0; i < 31; ++i) {
-        regs->intRegFile[i] = sc->sc_regs[i];
-        regs->floatRegFile.q[i] = sc->sc_fpregs[i];
-    }
-
-    regs->miscRegs.fpcr = sc->sc_fpcr;
-
-    return 0;
-}
-
-int
-tableFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
-{
-    int id = getArg(xc, 0);            // table ID
-    int index = getArg(xc, 1); // index into table
-    // arg 2 is buffer pointer; type depends on table ID
-    int nel = getArg(xc, 3);           // number of elements
-    int lel = getArg(xc, 4);           // expected element size
-
-    switch (id) {
-      case OSF::TBL_SYSINFO: {
-          if (index != 0 || nel != 1 || lel != sizeof(OSF::tbl_sysinfo))
-              return -EINVAL;
-          TypedBufferArg<OSF::tbl_sysinfo> elp(getArg(xc, 2));
-
-          const int clk_hz = one_million;
-          elp->si_user = curTick / (ticksPerSecond / clk_hz);
-          elp->si_nice = 0;
-          elp->si_sys = 0;
-          elp->si_idle = 0;
-          elp->wait = 0;
-          elp->si_hz = clk_hz;
-          elp->si_phz = clk_hz;
-          elp->si_boottime = seconds_since_epoch; // seconds since epoch?
-          elp->si_max_procs = process->numCpus();
-          elp.copyOut(xc->mem);
-          return 0;
-      }
-
-      default:
-        cerr << "table(): id " << id << " unknown." << endl;
-        return -EINVAL;
-    }
-}
-
-//
-// forward declaration... defined below table
-//
-int
-indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
-                    ExecContext *xc);
-
-//
-// Handler for unimplemented syscalls that we haven't thought about.
-//
-int
-unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
-                  ExecContext *xc)
-{
-    cerr << "Error: syscall " << desc->name
-         << " (#" << callnum << ") unimplemented.";
-    cerr << "  Args: " << getArg(xc, 0) << ", " << getArg(xc, 1)
-         << ", ..." << endl;
-
-    abort();
-}
-
-
-//
-// Handler for unimplemented syscalls that we never intend to
-// implement (signal handling, etc.) and should not affect the correct
-// behavior of the program.  Print a warning only if the appropriate
-// trace flag is enabled.  Return success to the target program.
-//
-int
-ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
-{
-    DCOUT(SyscallWarnings) << "Warning: ignoring syscall " << desc->name
-                           << "(" << getArg(xc, 0)
-                           << ", " << getArg(xc, 1)
-                           << ", ...)" << endl;
-
-    return 0;
-}
-
-
-int
-exitFunc(SyscallDesc *desc, int callnum, Process *process,
-         ExecContext *xc)
-{
-    new SimExitEvent("syscall caused exit", getArg(xc, 0) & 0xff);
-
-    return 1;
-}
-
-
-SyscallDesc syscallDescs[] = {
-    /* 0 */ SyscallDesc("syscall (#0)", indirectSyscallFunc, SyscallDesc::SuppressReturnValue),
-    /* 1 */ SyscallDesc("exit", exitFunc),
-    /* 2 */ SyscallDesc("fork", unimplementedFunc),
-    /* 3 */ SyscallDesc("read", readFunc),
-    /* 4 */ SyscallDesc("write", writeFunc),
-    /* 5 */ SyscallDesc("old_open", unimplementedFunc),
-    /* 6 */ SyscallDesc("close", closeFunc),
-    /* 7 */ SyscallDesc("wait4", unimplementedFunc),
-    /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
-    /* 9 */ SyscallDesc("link", unimplementedFunc),
-    /* 10 */ SyscallDesc("unlink", unimplementedFunc),
-    /* 11 */ SyscallDesc("execv", unimplementedFunc),
-    /* 12 */ SyscallDesc("chdir", unimplementedFunc),
-    /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
-    /* 14 */ SyscallDesc("mknod", unimplementedFunc),
-    /* 15 */ SyscallDesc("chmod", unimplementedFunc),
-    /* 16 */ SyscallDesc("chown", unimplementedFunc),
-    /* 17 */ SyscallDesc("obreak", obreakFunc),
-    /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
-    /* 19 */ SyscallDesc("lseek", lseekFunc),
-    /* 20 */ SyscallDesc("getpid", getpidFunc),
-    /* 21 */ SyscallDesc("mount", unimplementedFunc),
-    /* 22 */ SyscallDesc("unmount", unimplementedFunc),
-    /* 23 */ SyscallDesc("setuid", setuidFunc),
-    /* 24 */ SyscallDesc("getuid", getuidFunc),
-    /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
-    /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
-    /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
-    /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
-    /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
-    /* 30 */ SyscallDesc("accept", unimplementedFunc),
-    /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
-    /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
-    /* 33 */ SyscallDesc("access", unimplementedFunc),
-    /* 34 */ SyscallDesc("chflags", unimplementedFunc),
-    /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
-    /* 36 */ SyscallDesc("sync", unimplementedFunc),
-    /* 37 */ SyscallDesc("kill", unimplementedFunc),
-    /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
-    /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
-    /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
-    /* 41 */ SyscallDesc("dup", unimplementedFunc),
-    /* 42 */ SyscallDesc("pipe", unimplementedFunc),
-    /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
-    /* 44 */ SyscallDesc("profil", unimplementedFunc),
-    /* 45 */ SyscallDesc("open", openFunc),
-    /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
-    /* 47 */ SyscallDesc("getgid", getgidFunc),
-    /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
-    /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
-    /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
-    /* 51 */ SyscallDesc("acct", unimplementedFunc),
-    /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
-    /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
-    /* 54 */ SyscallDesc("ioctl", ioctlFunc),
-    /* 55 */ SyscallDesc("reboot", unimplementedFunc),
-    /* 56 */ SyscallDesc("revoke", unimplementedFunc),
-    /* 57 */ SyscallDesc("symlink", unimplementedFunc),
-    /* 58 */ SyscallDesc("readlink", unimplementedFunc),
-    /* 59 */ SyscallDesc("execve", unimplementedFunc),
-    /* 60 */ SyscallDesc("umask", unimplementedFunc),
-    /* 61 */ SyscallDesc("chroot", unimplementedFunc),
-    /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
-    /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
-    /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
-    /* 65 */ SyscallDesc("mremap", unimplementedFunc),
-    /* 66 */ SyscallDesc("vfork", unimplementedFunc),
-    /* 67 */ SyscallDesc("pre_F64_stat", unimplementedFunc),
-    /* 68 */ SyscallDesc("pre_F64_lstat", unimplementedFunc),
-    /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
-    /* 70 */ SyscallDesc("sstk", unimplementedFunc),
-    /* 71 */ SyscallDesc("mmap", mmapFunc),
-    /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
-    /* 73 */ SyscallDesc("munmap", unimplementedFunc),
-    /* 74 */ SyscallDesc("mprotect", ignoreFunc),
-    /* 75 */ SyscallDesc("madvise", unimplementedFunc),
-    /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
-    /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
-    /* 78 */ SyscallDesc("mincore", unimplementedFunc),
-    /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
-    /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
-    /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
-    /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
-    /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
-    /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
-    /* 85 */ SyscallDesc("table", tableFunc),
-    /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
-    /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
-    /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
-    /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
-    /* 90 */ SyscallDesc("dup2", unimplementedFunc),
-    /* 91 */ SyscallDesc("pre_F64_fstat", unimplementedFunc),
-    /* 92 */ SyscallDesc("fcntl", fcntlFunc),
-    /* 93 */ SyscallDesc("select", unimplementedFunc),
-    /* 94 */ SyscallDesc("poll", unimplementedFunc),
-    /* 95 */ SyscallDesc("fsync", unimplementedFunc),
-    /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
-    /* 97 */ SyscallDesc("socket", unimplementedFunc),
-    /* 98 */ SyscallDesc("connect", unimplementedFunc),
-    /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
-    /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
-    /* 101 */ SyscallDesc("old_send", unimplementedFunc),
-    /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
-    /* 103 */ SyscallDesc("sigreturn", sigreturnFunc, SyscallDesc::SuppressReturnValue),
-    /* 104 */ SyscallDesc("bind", unimplementedFunc),
-    /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
-    /* 106 */ SyscallDesc("listen", unimplementedFunc),
-    /* 107 */ SyscallDesc("plock", unimplementedFunc),
-    /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
-    /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
-    /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
-    /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
-    /* 112 */ SyscallDesc("sigstack", ignoreFunc),
-    /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
-    /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
-    /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
-    /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc),
-    /* 117 */ SyscallDesc("getrusage", getrusageFunc),
-    /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
-    /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
-    /* 120 */ SyscallDesc("readv", unimplementedFunc),
-    /* 121 */ SyscallDesc("writev", unimplementedFunc),
-    /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
-    /* 123 */ SyscallDesc("fchown", unimplementedFunc),
-    /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
-    /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
-    /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
-    /* 127 */ SyscallDesc("setregid", unimplementedFunc),
-    /* 128 */ SyscallDesc("rename", unimplementedFunc),
-    /* 129 */ SyscallDesc("truncate", unimplementedFunc),
-    /* 130 */ SyscallDesc("ftruncate", unimplementedFunc),
-    /* 131 */ SyscallDesc("flock", unimplementedFunc),
-    /* 132 */ SyscallDesc("setgid", unimplementedFunc),
-    /* 133 */ SyscallDesc("sendto", unimplementedFunc),
-    /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
-    /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
-    /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
-    /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
-    /* 138 */ SyscallDesc("utimes", unimplementedFunc),
-    /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
-    /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
-    /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
-    /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
-    /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
-    /* 144 */ SyscallDesc("getrlimit", getrlimitFunc),
-    /* 145 */ SyscallDesc("setrlimit", unimplementedFunc),
-    /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
-    /* 147 */ SyscallDesc("setsid", unimplementedFunc),
-    /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
-    /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
-    /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
-    /* 151 */ SyscallDesc("pread", unimplementedFunc),
-    /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
-    /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
-    /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
-    /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
-    /* 156 */ SyscallDesc("sigaction", ignoreFunc),
-    /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
-    /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
-    /* 159 */ SyscallDesc("getdirentries", getdirentriesFunc),
-    /* 160 */ SyscallDesc("pre_F64_statfs", unimplementedFunc),
-    /* 161 */ SyscallDesc("pre_F64_fstatfs", unimplementedFunc),
-    /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
-    /* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
-    /* 164 */ SyscallDesc("getfh", unimplementedFunc),
-    /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
-    /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
-    /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
-    /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
-    /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
-    /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
-    /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
-    /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
-    /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
-    /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
-    /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
-    /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
-    /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
-    /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
-    /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
-    /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
-    /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
-    /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
-    /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
-    /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
-    /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
-    /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
-    /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
-    /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
-    /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
-    /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
-    /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
-    /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
-    /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
-    /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
-    /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
-    /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
-    /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
-    /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
-    /* 199 */ SyscallDesc("swapon", unimplementedFunc),
-    /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
-    /* 201 */ SyscallDesc("msgget", unimplementedFunc),
-    /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
-    /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
-    /* 204 */ SyscallDesc("semctl", unimplementedFunc),
-    /* 205 */ SyscallDesc("semget", unimplementedFunc),
-    /* 206 */ SyscallDesc("semop", unimplementedFunc),
-    /* 207 */ SyscallDesc("uname", unameFunc),
-    /* 208 */ SyscallDesc("lchown", unimplementedFunc),
-    /* 209 */ SyscallDesc("shmat", unimplementedFunc),
-    /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
-    /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
-    /* 212 */ SyscallDesc("shmget", unimplementedFunc),
-    /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
-    /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
-    /* 215 */ SyscallDesc("msleep", unimplementedFunc),
-    /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
-    /* 217 */ SyscallDesc("msync", unimplementedFunc),
-    /* 218 */ SyscallDesc("signal", unimplementedFunc),
-    /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
-    /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
-    /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
-    /* 222 */ SyscallDesc("security", unimplementedFunc),
-    /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
-    /* 224 */ SyscallDesc("stat", statFunc),
-    /* 225 */ SyscallDesc("lstat", lstatFunc),
-    /* 226 */ SyscallDesc("fstat", fstatFunc),
-    /* 227 */ SyscallDesc("statfs", unimplementedFunc),
-    /* 228 */ SyscallDesc("fstatfs", unimplementedFunc),
-    /* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
-    /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
-    /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
-    /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
-    /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
-    /* 234 */ SyscallDesc("getsid", unimplementedFunc),
-    /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
-    /* 236 */ SyscallDesc("waitid", unimplementedFunc),
-    /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
-    /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
-    /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
-    /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
-    /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
-    /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
-    /* 243 */ SyscallDesc("fuser", unimplementedFunc),
-    /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
-    /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
-    /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
-    /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
-    /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
-    /* 249 */ SyscallDesc("sync2", unimplementedFunc),
-    /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
-    /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
-    /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
-    /* 253 */ SyscallDesc("audgen", unimplementedFunc),
-    /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
-    /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
-    /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
-    /* 257 */ SyscallDesc("setsysinfo", unimplementedFunc),
-    /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
-    /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
-    /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
-    /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
-    /* 262 */ SyscallDesc("oflock", unimplementedFunc),
-    /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
-    /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
-    /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
-    /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
-};
-
-const int Num_Syscall_Descs = sizeof(syscallDescs) / sizeof(SyscallDesc);
-
-const int Max_Syscall_Desc = Num_Syscall_Descs - 1;
-
-//
-// Mach syscalls -- identified by negated syscall numbers
-//
-
-// Create a stack region for a thread.
-int
-stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
-                 ExecContext *xc)
-{
-    TypedBufferArg<OSF::vm_stack> argp(getArg(xc, 0));
-
-    argp.copyIn(xc->mem);
-
-    // if the user chose an address, just let them have it.  Otherwise
-    // pick one for them.
-    if (argp->address == 0) {
-        argp->address = process->next_thread_stack_base;
-        int stack_size = (argp->rsize + argp->ysize + argp->gsize);
-        process->next_thread_stack_base -= stack_size;
-        argp.copyOut(xc->mem);
-    }
-
-    return 0;
-}
-
-const int NXM_LIB_VERSION = 301003;
-
-//
-// This call sets up the interface between the user and kernel
-// schedulers by creating a shared-memory region.  The shared memory
-// region has several structs, some global, some per-RAD, some per-VP.
-//
-int
-nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
-                 ExecContext *xc)
-{
-    TypedBufferArg<OSF::nxm_task_attr> attrp(getArg(xc, 0));
-    TypedBufferArg<Addr> configptr_ptr(getArg(xc, 1));
-
-    attrp.copyIn(xc->mem);
-
-    if (attrp->nxm_version != NXM_LIB_VERSION) {
-        cerr << "nxm_task_init: thread library version mismatch! "
-             << "got " << attrp->nxm_version
-             << ", expected " << NXM_LIB_VERSION << endl;
-        abort();
-    }
-
-    if (attrp->flags != OSF::NXM_TASK_INIT_VP) {
-        cerr << "nxm_task_init: bad flag value " << attrp->flags
-             << " (expected " << OSF::NXM_TASK_INIT_VP << ")" << endl;
-        abort();
-    }
-
-    const Addr base_addr = 0x12000; // was 0x3f0000000LL;
-    Addr cur_addr = base_addr; // next addresses to use
-    // first comes the config_info struct
-    Addr config_addr = cur_addr;
-    cur_addr += sizeof(OSF::nxm_config_info);
-    // next comes the per-cpu state vector
-    Addr slot_state_addr = cur_addr;
-    int slot_state_size = process->numCpus() * sizeof(OSF::nxm_slot_state_t);
-    cur_addr += slot_state_size;
-    // now the per-RAD state struct (we only support one RAD)
-    cur_addr = 0x14000;        // bump up addr for alignment
-    Addr rad_state_addr = cur_addr;
-    int rad_state_size =
-        (sizeof(OSF::nxm_shared)
-         + (process->numCpus()-1) * sizeof(OSF::nxm_sched_state));
-    cur_addr += rad_state_size;
-
-    // now initialize a config_info struct and copy it out to user space
-    TypedBufferArg<OSF::nxm_config_info> config(config_addr);
-
-    config->nxm_nslots_per_rad = process->numCpus();
-    config->nxm_nrads = 1;     // only one RAD in our system!
-    config->nxm_slot_state = slot_state_addr;
-    config->nxm_rad[0] = rad_state_addr;
-
-    config.copyOut(xc->mem);
-
-    // initialize the slot_state array and copy it out
-    TypedBufferArg<OSF::nxm_slot_state_t> slot_state(slot_state_addr,
-                                                     slot_state_size);
-    for (int i = 0; i < process->numCpus(); ++i) {
-        // CPU 0 is bound to the calling process; all others are available
-        slot_state[i] = (i == 0) ? OSF::NXM_SLOT_BOUND : OSF::NXM_SLOT_AVAIL;
-    }
-
-    slot_state.copyOut(xc->mem);
-
-    // same for the per-RAD "shared" struct.  Note that we need to
-    // allocate extra bytes for the per-VP array which is embedded at
-    // the end.
-    TypedBufferArg<OSF::nxm_shared> rad_state(rad_state_addr,
-                                              rad_state_size);
-
-    rad_state->nxm_callback = attrp->nxm_callback;
-    rad_state->nxm_version = attrp->nxm_version;
-    rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
-    for (int i = 0; i < process->numCpus(); ++i) {
-        OSF::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
-        ssp->nxm_u.sigmask = 0;
-        ssp->nxm_u.sig = 0;
-        ssp->nxm_u.flags = 0;
-        ssp->nxm_u.cancel_state = 0;
-        ssp->nxm_u.nxm_ssig = 0;
-        ssp->nxm_bits = 0;
-        ssp->nxm_quantum = attrp->nxm_quantum;
-        ssp->nxm_set_quantum = attrp->nxm_quantum;
-        ssp->nxm_sysevent = 0;
-
-        if (i == 0) {
-            uint64_t uniq = xc->regs.miscRegs.uniq;
-            ssp->nxm_u.pth_id = uniq + attrp->nxm_uniq_offset;
-            ssp->nxm_u.nxm_active = uniq | 1;
-        }
-        else {
-            ssp->nxm_u.pth_id = 0;
-            ssp->nxm_u.nxm_active = 0;
-        }
-    }
-
-    rad_state.copyOut(xc->mem);
-
-    //
-    // copy pointer to shared config area out to user
-    //
-    *configptr_ptr = config_addr;
-    configptr_ptr.copyOut(xc->mem);
-
-    return 0;
-}
-
-
-static void
-init_exec_context(ExecContext *ec,
-                  OSF::nxm_thread_attr *attrp, uint64_t uniq_val)
-{
-    memset(&ec->regs, 0, sizeof(ec->regs));
-
-    ec->regs.intRegFile[ArgumentReg0] = attrp->registers.a0;
-    ec->regs.intRegFile[27/*t12*/] = attrp->registers.pc;
-    ec->regs.intRegFile[StackPointerReg] = attrp->registers.sp;
-    ec->regs.miscRegs.uniq = uniq_val;
-
-    ec->regs.pc = attrp->registers.pc;
-    ec->regs.npc = attrp->registers.pc + sizeof(MachInst);
-
-    ec->setStatus(ExecContext::Active);
-}
-
-int
-nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
-                      ExecContext *xc)
-{
-    TypedBufferArg<OSF::nxm_thread_attr> attrp(getArg(xc, 0));
-    TypedBufferArg<uint64_t> kidp(getArg(xc, 1));
-    int thread_index = getArg(xc, 2);
-
-    // get attribute args
-    attrp.copyIn(xc->mem);
-
-    if (attrp->version != NXM_LIB_VERSION) {
-        cerr << "nxm_thread_create: thread library version mismatch! "
-             << "got " << attrp->version
-             << ", expected " << NXM_LIB_VERSION << endl;
-        abort();
-    }
-
-    if (thread_index < 0 | thread_index > process->numCpus()) {
-        cerr << "nxm_thread_create: bad thread index " << thread_index
-             << endl;
-        abort();
-    }
-
-    // On a real machine, the per-RAD shared structure is in
-    // shared memory, so both the user and kernel can get at it.
-    // We don't have that luxury, so we just copy it in and then
-    // back out again.
-    int rad_state_size =
-        (sizeof(OSF::nxm_shared) +
-         (process->numCpus()-1) * sizeof(OSF::nxm_sched_state));
-
-    TypedBufferArg<OSF::nxm_shared> rad_state(0x14000,
-                                              rad_state_size);
-    rad_state.copyIn(xc->mem);
-
-    uint64_t uniq_val = attrp->pthid - rad_state->nxm_uniq_offset;
-
-    if (attrp->type == OSF::NXM_TYPE_MANAGER) {
-        // DEC pthreads seems to always create one of these (in
-        // addition to N application threads), but we don't use it,
-        // so don't bother creating it.
-
-        // This is supposed to be a port number.  Make something up.
-        *kidp = 99;
-        kidp.copyOut(xc->mem);
-
-        return 0;
-    } else if (attrp->type == OSF::NXM_TYPE_VP) {
-        // A real "virtual processor" kernel thread.  Need to fork
-        // this thread on another CPU.
-        OSF::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
-
-        if (ssp->nxm_u.nxm_active != 0)
-            return OSF::KERN_NOT_RECEIVER;
-
-        ssp->nxm_u.pth_id = attrp->pthid;
-        ssp->nxm_u.nxm_active = uniq_val | 1;
-
-        rad_state.copyOut(xc->mem);
-
-        Addr slot_state_addr = 0x12000 + sizeof(OSF::nxm_config_info);
-        int slot_state_size = process->numCpus() * sizeof(OSF::nxm_slot_state_t);
-
-        TypedBufferArg<OSF::nxm_slot_state_t> slot_state(slot_state_addr,
-                                                         slot_state_size);
-
-        slot_state.copyIn(xc->mem);
-
-        if (slot_state[thread_index] != OSF::NXM_SLOT_AVAIL) {
-            cerr << "nxm_thread_createFunc: requested VP slot "
-                 << thread_index << " not available!" << endl;
-            fatal("");
-        }
-
-        slot_state[thread_index] = OSF::NXM_SLOT_BOUND;
-
-        slot_state.copyOut(xc->mem);
-
-        // Find a free simulator execution context.
-        for (int i = 0; i < process->numCpus(); ++i) {
-            ExecContext *xc = process->execContexts[i];
-
-            if (xc->status() == ExecContext::Unallocated) {
-                // inactive context... grab it
-                init_exec_context(xc, attrp, uniq_val);
-
-                // This is supposed to be a port number, but we'll try
-                // and get away with just sticking the thread index
-                // here.
-                *kidp = thread_index;
-                kidp.copyOut(xc->mem);
-
-                return 0;
-            }
-        }
-
-        // fell out of loop... no available inactive context
-        cerr << "nxm_thread_create: no idle contexts available." << endl;
-        abort();
-    } else {
-        cerr << "nxm_thread_create: can't handle thread type "
-             << attrp->type << endl;
-        abort();
-    }
-
-    return 0;
-}
-
-
-int
-nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
-             ExecContext *xc)
-{
-    return 0;
-}
-
-int
-nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
-                     ExecContext *xc)
-{
-    uint64_t tid = getArg(xc, 0);
-    uint64_t secs = getArg(xc, 1);
-    uint64_t flags = getArg(xc, 2);
-    uint64_t action = getArg(xc, 3);
-    uint64_t usecs = getArg(xc, 4);
-
-    cout << xc->cpu->name() << ": nxm_thread_block " << tid << " " << secs
-         << " " << flags << " " << action << " " << usecs << endl;
-
-    return 0;
-}
-
-
-int
-nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-{
-    Addr uaddr = getArg(xc, 0);
-    uint64_t val = getArg(xc, 1);
-    uint64_t secs = getArg(xc, 2);
-    uint64_t usecs = getArg(xc, 3);
-    uint64_t flags = getArg(xc, 4);
-
-    BaseCPU *cpu = xc->cpu;
-
-    cout << cpu->name() << ": nxm_block " << hex << uaddr << dec << " " << val
-         << " " << secs << " " << usecs
-         << " " << flags << endl;
-
-    return 0;
-}
-
-
-int
-nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-{
-    Addr uaddr = getArg(xc, 0);
-
-    cout << xc->cpu->name() << ": nxm_unblock "
-         << hex << uaddr << dec << endl;
-
-    return 0;
-}
-
-
-int
-swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
-{
-    // Attempts to switch to another runnable thread (if there is
-    // one).  Returns false if there are no other threads to run
-    // (i.e., the thread can reasonably spin-wait) or true if there
-    // are other threads.
-    //
-    // Since we assume at most one "kernel" thread per CPU, it's
-    // always safe to return false here.
-    return false;
-}
-
-
-// just activate one by default
-static int
-activate_waiting_context(Addr uaddr, Process *process,
-                         bool activate_all = false)
-{
-    int num_activated = 0;
-
-    list<Process::WaitRec>::iterator i = process->waitList.begin();
-    list<Process::WaitRec>::iterator end = process->waitList.end();
-
-    while (i != end && (num_activated == 0 || activate_all)) {
-        if (i->waitChan == uaddr) {
-            // found waiting process: make it active
-            ExecContext *newCtx = i->waitingContext;
-            assert(newCtx->status() == ExecContext::Suspended);
-            newCtx->setStatus(ExecContext::Active);
-
-            // get rid of this record
-            i = process->waitList.erase(i);
-
-            ++num_activated;
-        } else {
-            ++i;
-        }
-    }
-
-    return num_activated;
-}
-
-
-static void
-m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
-{
-    TypedBufferArg<uint64_t> lockp(uaddr);
-
-    lockp.copyIn(xc->mem);
-
-    if (*lockp == 0) {
-        // lock is free: grab it
-        *lockp = 1;
-        lockp.copyOut(xc->mem);
-    } else {
-        // lock is busy: disable until free
-        process->waitList.push_back(Process::WaitRec(uaddr, xc));
-        xc->setStatus(ExecContext::Suspended);
-    }
-}
-
-static void
-m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
-{
-    TypedBufferArg<uint64_t> lockp(uaddr);
-
-    lockp.copyIn(xc->mem);
-    assert(*lockp != 0);
-
-    // Check for a process waiting on the lock.
-    int num_waiting = activate_waiting_context(uaddr, process);
-
-    // clear lock field if no waiting context is taking over the lock
-    if (num_waiting == 0) {
-        *lockp = 0;
-        lockp.copyOut(xc->mem);
-    }
-}
-
-
-int
-m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
-                  ExecContext *xc)
-{
-    Addr uaddr = getArg(xc, 0);
-
-    m5_lock_mutex(uaddr, process, xc);
-
-    // Return 0 since we will always return to the user with the lock
-    // acquired.  We will just keep the context inactive until that is
-    // true.
-    return 0;
-}
-
-
-int
-m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
-                     ExecContext *xc)
-{
-    Addr uaddr = getArg(xc, 0);
-    TypedBufferArg<uint64_t> lockp(uaddr);
-
-    lockp.copyIn(xc->mem);
-
-    if (*lockp == 0) {
-        // lock is free: grab it
-        *lockp = 1;
-        lockp.copyOut(xc->mem);
-        return 0;
-    } else {
-        return 1;
-    }
-}
-
-
-int
-m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
-                    ExecContext *xc)
-{
-    Addr uaddr = getArg(xc, 0);
-
-    m5_unlock_mutex(uaddr, process, xc);
-
-    return 0;
-}
-
-
-int
-m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
-                   ExecContext *xc)
-{
-    Addr cond_addr = getArg(xc, 0);
-
-    // Wqake up one process waiting on the condition variable.
-    activate_waiting_context(cond_addr, process);
-
-    return 0;
-}
-
-
-int
-m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
-                      ExecContext *xc)
-{
-    Addr cond_addr = getArg(xc, 0);
-
-    // Wake up all processes waiting on the condition variable.
-    activate_waiting_context(cond_addr, process, true);
-
-    return 0;
-}
-
-
-int
-m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
-                 ExecContext *xc)
-{
-    Addr cond_addr = getArg(xc, 0);
-    Addr lock_addr = getArg(xc, 1);
-    TypedBufferArg<uint64_t> condp(cond_addr);
-    TypedBufferArg<uint64_t> lockp(lock_addr);
-
-    // user is supposed to acquire lock before entering
-    lockp.copyIn(xc->mem);
-    assert(*lockp != 0);
-
-    m5_unlock_mutex(lock_addr, process, xc);
-
-    process->waitList.push_back(Process::WaitRec(cond_addr, xc));
-    xc->setStatus(ExecContext::Suspended);
-
-    return 0;
-}
-
-
-int
-m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
-                   ExecContext *xc)
-{
-    assert(xc->status() == ExecContext::Active);
-    xc->setStatus(ExecContext::Unallocated);
-
-    return 0;
-}
-
-
-SyscallDesc machSyscallDescs[] = {
-    /* 0 */  SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 1 */  SyscallDesc("m5_mutex_lock", m5_mutex_lockFunc),
-    /* 2 */  SyscallDesc("m5_mutex_trylock", m5_mutex_trylockFunc),
-    /* 3 */  SyscallDesc("m5_mutex_unlock", m5_mutex_unlockFunc),
-    /* 4 */  SyscallDesc("m5_cond_signal", m5_cond_signalFunc),
-    /* 5 */  SyscallDesc("m5_cond_broadcast", m5_cond_broadcastFunc),
-    /* 6 */  SyscallDesc("m5_cond_wait", m5_cond_waitFunc),
-    /* 7 */  SyscallDesc("m5_thread_exit", m5_thread_exitFunc),
-    /* 8 */  SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 9 */  SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 10 */ SyscallDesc("task_self", unimplementedFunc),
-    /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
-    /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
-    /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
-    /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
-    /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
-    /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
-    /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 24 */ SyscallDesc("nxm_block", nxm_blockFunc),
-    /* 25 */ SyscallDesc("nxm_unblock", nxm_unblockFunc),
-    /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
-    /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
-    /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
-    /* 32 */ SyscallDesc("nxm_thread_create", nxm_thread_createFunc),
-    /* 33 */ SyscallDesc("nxm_task_init", nxm_task_initFunc),
-    /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 35 */ SyscallDesc("nxm_idle", nxm_idleFunc),
-    /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
-    /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
-    /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
-    /* 39 */ SyscallDesc("nxm_thread_block", nxm_thread_blockFunc),
-    /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
-    /* 41 */ SyscallDesc("init_process", unimplementedFunc),
-    /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
-    /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
-    /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
-    /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
-    /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
-    /* 47 */ SyscallDesc("stack_create", stack_createFunc),
-    /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
-    /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
-    /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
-    /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
-    /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
-    /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 55 */ SyscallDesc("host_self", unimplementedFunc),
-    /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
-    /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 59 */ SyscallDesc("swtch_pri", swtch_priFunc),
-    /* 60 */ SyscallDesc("swtch", unimplementedFunc),
-    /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
-    /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
-    /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
-    /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
-    /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
-    /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
-    /* 67 */ SyscallDesc("nxm_swtch_pri", swtch_priFunc),
-    /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
-    /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
-    /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
-    /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
-    /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
-    /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
-    /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
-    /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
-    /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
-    /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
-    /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
-    /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
-    /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
-    /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
-    /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
-};
-
-const int Num_Mach_Syscall_Descs =
-                sizeof(machSyscallDescs) / sizeof(SyscallDesc);
-
-const int Max_Mach_Syscall_Desc = Num_Mach_Syscall_Descs - 1;
-
-// Since negated values are used to identify Mach syscalls, the
-// minimum (signed) valid syscall number is the negated max Mach
-// syscall number.
-const int Min_Syscall_Desc = -Max_Mach_Syscall_Desc;
-
-
-//
-// helper function for invoking syscalls
-//
-static
-void
-doSyscall(int callnum, Process *process, ExecContext *xc)
-{
-    if (callnum < Min_Syscall_Desc || callnum > Max_Syscall_Desc) {
-        cerr << "Syscall " << callnum << " out of range" << endl;
-        abort();
-    }
-
-    SyscallDesc *desc =
-        (callnum < 0) ? &machSyscallDescs[-callnum] : &syscallDescs[callnum];
-
-    DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
-             xc->cpu->name(), desc->name);
-
-    int retval = desc->doFunc(callnum, process, xc);
-
-    DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
-             xc->cpu->name(), desc->name, retval);
-
-    if (!((desc->flags & SyscallDesc::SuppressReturnValue) && retval == 0))
-        set_return_value(xc, retval);
-}
-
-//
-// Indirect syscall invocation (call #0)
-//
-int
-indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
-                    ExecContext *xc)
-{
-    int new_callnum = getArg(xc, 0);
-
-    for (int i = 0; i < 5; ++i)
-        setArg(xc, i, getArg(xc, i+1));
-
-    doSyscall(new_callnum, process, xc);
-
-    return 0;
-}
-
-
-void
-fake_syscall(Process *process, ExecContext *xc)
-{
-    int64_t callnum = xc->regs.intRegFile[ReturnValueReg];
-
-    doSyscall(callnum, process, xc);
-}
index 0270e02a35367e07010833a4f5fcda0b630b210d..42a376ed1ce27846c09adfd76152ad418b047543 100644 (file)
@@ -43,7 +43,9 @@ ObjectFile *
 AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
 {
     if (!N_BADMAG(*(aout_exechdr *)data)) {
-        return new AoutObject(fname, fd, len, data);
+        // right now this is only used for Alpha PAL code
+        return new AoutObject(fname, fd, len, data,
+                              ObjectFile::Alpha, ObjectFile::UnknownOpSys);
     }
     else {
         return NULL;
@@ -52,8 +54,9 @@ AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
 
 
 AoutObject::AoutObject(const string &_filename, int _fd,
-                         size_t _len, uint8_t *_data)
-    : ObjectFile(_filename, _fd, _len, _data)
+                       size_t _len, uint8_t *_data,
+                       Arch _arch, OpSys _opSys)
+    : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
 {
     execHdr = (aout_exechdr *)fileData;
 
index 77c59aef6b67644bfff73505ee05ae95bd80dc4a..9fb8cb3e804ce62e407d92551b66acf34d1654f3 100644 (file)
@@ -40,7 +40,8 @@ class AoutObject : public ObjectFile
     aout_exechdr *execHdr;
 
     AoutObject(const std::string &_filename, int _fd,
-                size_t _len, uint8_t *_data);
+               size_t _len, uint8_t *_data,
+               Arch _arch, OpSys _opSys);
 
   public:
     virtual ~AoutObject() {}
index 5e726a1c5b0b94819d3ac7c542318e8d70c3b7f5..bab75944da37b50d763d1830ba13eeedf353f826 100644 (file)
@@ -46,7 +46,8 @@ EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
 {
     if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) {
         // it's Alpha ECOFF
-        return new EcoffObject(fname, fd, len, data);
+        return new EcoffObject(fname, fd, len, data,
+                               ObjectFile::Alpha, ObjectFile::Tru64);
     }
     else {
         return NULL;
@@ -55,8 +56,9 @@ EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
 
 
 EcoffObject::EcoffObject(const string &_filename, int _fd,
-                         size_t _len, uint8_t *_data)
-    : ObjectFile(_filename, _fd, _len, _data)
+                         size_t _len, uint8_t *_data,
+                         Arch _arch, OpSys _opSys)
+    : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
 {
     execHdr = (ecoff_exechdr *)fileData;
     fileHdr = &(execHdr->f);
index 94b11c7200df1c4f6859112bc3339a48a4c6b3db..05d026d0020ac7fbe9006242fdb434096e59624f 100644 (file)
@@ -44,7 +44,8 @@ class EcoffObject : public ObjectFile
     ecoff_aouthdr *aoutHdr;
 
     EcoffObject(const std::string &_filename, int _fd,
-                size_t _len, uint8_t *_data);
+                size_t _len, uint8_t *_data,
+                Arch _arch, OpSys _opSys);
 
   public:
     virtual ~EcoffObject() {}
index 605895c9c8e3f77213962f55a9ba55f6ca16873e..30dec4c916f1e27d69519f99991e4bca73e003b8 100644 (file)
@@ -43,8 +43,9 @@ ObjectFile *
 ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
 {
     if (memcmp(((Elf64_Ehdr *)data)->e_ident, ELFMAG, SELFMAG) == 0) {
-        // for now we'll assume it's a 64-bit Alpha binary
-        return new ElfObject(fname, fd, len, data);
+        // for now we'll assume it's a 64-bit Alpha Linux binary
+        return new ElfObject(fname, fd, len, data,
+                             ObjectFile::Alpha, ObjectFile::Linux);
     }
     else {
         return NULL;
@@ -53,8 +54,9 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
 
 
 ElfObject::ElfObject(const string &_filename, int _fd,
-                         size_t _len, uint8_t *_data)
-    : ObjectFile(_filename, _fd, _len, _data)
+                     size_t _len, uint8_t *_data,
+                     Arch _arch, OpSys _opSys)
+    : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
 {
     ehdr = (Elf64_Ehdr *)fileData;
 
index 28f6bb24322d107da3e9c66aef94e3e03501f2e5..10d97d089eea8c2d13e3a317f0499be5fec000c1 100644 (file)
@@ -45,7 +45,8 @@ class ElfObject : public ObjectFile
     int dataPhdrIdx;
 
     ElfObject(const std::string &_filename, int _fd,
-              size_t _len, uint8_t *_data);
+              size_t _len, uint8_t *_data,
+              Arch _arch, OpSys _opSys);
 
   public:
     virtual ~ElfObject() {}
index 5a13d180ccb8650b46272f63b7dab0302537b095..25e9b2d192b5d9099ef8c84e0aa74861b55431ab 100644 (file)
 using namespace std;
 
 ObjectFile::ObjectFile(const string &_filename, int _fd,
-                       size_t _len, uint8_t *_data)
-    : filename(_filename), descriptor(_fd), fileData(_data), len(_len)
+                       size_t _len, uint8_t *_data,
+                       Arch _arch, OpSys _opSys)
+    : filename(_filename), descriptor(_fd), fileData(_data), len(_len),
+      arch(_arch), opSys(_opSys)
 {
 }
 
index 5950ea326b445c099612f59bdcec5ef0aeb1b799..a29bdc1532e9863d7de53d4c85b6def0d42b132c 100644 (file)
@@ -36,14 +36,31 @@ class SymbolTable;
 
 class ObjectFile
 {
+  public:
+
+    enum Arch {
+        UnknownArch,
+        Alpha
+    };
+
+    enum OpSys {
+        UnknownOpSys,
+        Tru64,
+        Linux
+    };
+
   protected:
     const std::string filename;
     int descriptor;
     uint8_t *fileData;
     size_t len;
 
+    Arch  arch;
+    OpSys opSys;
+
     ObjectFile(const std::string &_filename, int _fd,
-               size_t _len, uint8_t *_data);
+               size_t _len, uint8_t *_data,
+               Arch _arch, OpSys _opSys);
 
   public:
     virtual ~ObjectFile();
@@ -55,6 +72,9 @@ class ObjectFile
     virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
     virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
 
+    Arch  getArch()  const { return arch; }
+    OpSys getOpSys() const { return opSys; }
+
   protected:
 
     struct Section {
index 92144bd931647585da72e25f4c9e1482676e995c..7332b86a670a1d52328e2969046945c012047bf1 100644 (file)
@@ -34,7 +34,7 @@
 #ifdef FULL_SYSTEM
 #include "sim/system.hh"
 #else
-#include "sim/prog.hh"
+#include "sim/process.hh"
 #endif
 
 using namespace std;
index 274a3778bba49d2f346b75a73c01bcccffc3f76c..7999e37350dfc5ebc7acb3068008bcf50d68910a 100644 (file)
@@ -52,7 +52,7 @@ class MemoryController;
 
 #else // !FULL_SYSTEM
 
-#include "sim/prog.hh"
+#include "sim/process.hh"
 
 #endif // FULL_SYSTEM
 
@@ -376,6 +376,34 @@ class ExecContext
 #endif
 
 #ifndef FULL_SYSTEM
+    IntReg getSyscallArg(int i)
+    {
+        return regs.intRegFile[ArgumentReg0 + i];
+    }
+
+    // used to shift args for indirect syscall
+    void setSyscallArg(int i, IntReg val)
+    {
+        regs.intRegFile[ArgumentReg0 + i] = val;
+    }
+
+    void setSyscallReturn(int64_t return_value)
+    {
+        // check for error condition.  Alpha syscall convention is to
+        // indicate success/failure in reg a3 (r19) and put the
+        // return value itself in the standard return value reg (v0).
+        const int RegA3 = 19;  // only place this is used
+        if (return_value >= 0) {
+            // no error
+            regs.intRegFile[RegA3] = 0;
+            regs.intRegFile[ReturnValueReg] = return_value;
+        } else {
+            // got an error, return details
+            regs.intRegFile[RegA3] = (IntReg) -1;
+            regs.intRegFile[ReturnValueReg] = -return_value;
+        }
+    }
+
     void syscall()
     {
         process->syscall(this);
index a63f860986d2db5de1e0eeef69a84d833a67bfe0..476f28ea003aea0d207c1ce9f43a959bb7c0e3a5 100644 (file)
@@ -70,7 +70,6 @@
 #else // !FULL_SYSTEM
 #include "eio/eio.hh"
 #include "mem/functional_mem/functional_memory.hh"
-#include "sim/prog.hh"
 #endif // FULL_SYSTEM
 
 using namespace std;
diff --git a/sim/process.cc b/sim/process.cc
new file mode 100644 (file)
index 0000000..bb43338
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <cstdio>
+#include <string>
+
+#include "base/intmath.hh"
+#include "base/loader/object_file.hh"
+#include "base/statistics.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/full_cpu/smt.hh"
+#include "cpu/full_cpu/thread.hh"
+#include "eio/eio.hh"
+#include "mem/functional_mem/main_memory.hh"
+#include "sim/builder.hh"
+#include "sim/fake_syscall.hh"
+#include "sim/process.hh"
+#include "sim/sim_stats.hh"
+
+#ifdef TARGET_ALPHA
+#include "arch/alpha/alpha_tru64_process.hh"
+#include "arch/alpha/alpha_linux_process.hh"
+#endif
+
+using namespace std;
+
+//
+// The purpose of this code is to fake the loader & syscall mechanism
+// when there's no OS: thus there's no resone to use it in FULL_SYSTEM
+// mode when we do have an OS
+//
+#ifdef FULL_SYSTEM
+#error "process.cc not compatible with FULL_SYSTEM"
+#endif
+
+// current number of allocated processes
+int num_processes = 0;
+
+Process::Process(const string &name,
+                 int stdin_fd,         // initial I/O descriptors
+                 int stdout_fd,
+                 int stderr_fd)
+    : SimObject(name)
+{
+    // allocate memory space
+    memory = new MainMemory(name + ".MainMem");
+
+    // allocate initial register file
+    init_regs = new RegFile;
+
+    // initialize first 3 fds (stdin, stdout, stderr)
+    fd_map[STDIN_FILENO] = stdin_fd;
+    fd_map[STDOUT_FILENO] = stdout_fd;
+    fd_map[STDERR_FILENO] = stderr_fd;
+
+    // mark remaining fds as free
+    for (int i = 3; i <= MAX_FD; ++i) {
+        fd_map[i] = -1;
+    }
+
+    num_syscalls = 0;
+
+    // other parameters will be initialized when the program is loaded
+}
+
+void
+Process::regStats()
+{
+    using namespace Statistics;
+
+    num_syscalls
+        .name(name() + ".PROG:num_syscalls")
+        .desc("Number of system calls")
+        ;
+}
+
+//
+// static helper functions
+//
+int
+Process::openInputFile(const string &filename)
+{
+    int fd = open(filename.c_str(), O_RDONLY);
+
+    if (fd == -1) {
+        perror(NULL);
+        cerr << "unable to open \"" << filename << "\" for reading\n";
+        fatal("can't open input file");
+    }
+
+    return fd;
+}
+
+
+int
+Process::openOutputFile(const string &filename)
+{
+    int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774);
+
+    if (fd == -1) {
+        perror(NULL);
+        cerr << "unable to open \"" << filename << "\" for writing\n";
+        fatal("can't open output file");
+    }
+
+    return fd;
+}
+
+
+int
+Process::registerExecContext(ExecContext *xc)
+{
+    // add to list
+    int myIndex = execContexts.size();
+    execContexts.push_back(xc);
+
+    if (myIndex == 0) {
+        // first exec context for this process... initialize & enable
+
+        // copy process's initial regs struct
+        xc->regs = *init_regs;
+
+        // mark this context as active
+        xc->setStatus(ExecContext::Active);
+    }
+
+    // return CPU number to caller and increment available CPU count
+    return myIndex;
+}
+
+
+void
+Process::replaceExecContext(int xcIndex, ExecContext *xc)
+{
+    if (xcIndex >= execContexts.size()) {
+        panic("replaceExecContext: bad xcIndex, %d >= %d\n",
+              xcIndex, execContexts.size());
+    }
+
+    execContexts[xcIndex] = xc;
+}
+
+// map simulator fd sim_fd to target fd tgt_fd
+void
+Process::dup_fd(int sim_fd, int tgt_fd)
+{
+    if (tgt_fd < 0 || tgt_fd > MAX_FD)
+        panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd);
+
+    fd_map[tgt_fd] = sim_fd;
+}
+
+
+// generate new target fd for sim_fd
+int
+Process::open_fd(int sim_fd)
+{
+    int free_fd;
+
+    // in case open() returns an error, don't allocate a new fd
+    if (sim_fd == -1)
+        return -1;
+
+    // find first free target fd
+    for (free_fd = 0; fd_map[free_fd] >= 0; ++free_fd) {
+        if (free_fd == MAX_FD)
+            panic("Process::open_fd: out of file descriptors!");
+    }
+
+    fd_map[free_fd] = sim_fd;
+
+    return free_fd;
+}
+
+
+// look up simulator fd for given target fd
+int
+Process::sim_fd(int tgt_fd)
+{
+    if (tgt_fd > MAX_FD)
+        return -1;
+
+    return fd_map[tgt_fd];
+}
+
+
+
+//
+// need to declare these here since there is no concrete Process type
+// that can be constructed (i.e., no REGISTER_SIM_OBJECT() macro call,
+// which is where these get declared for concrete types).
+//
+DEFINE_SIM_OBJECT_CLASS_NAME("Process object", Process)
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// LiveProcess member definitions
+//
+////////////////////////////////////////////////////////////////////////
+
+
+static void
+copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
+                FunctionalMemory *memory)
+{
+    for (int i = 0; i < strings.size(); ++i) {
+        memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
+        memory->writeString(data_ptr, strings[i].c_str());
+        array_ptr += sizeof(Addr);
+        data_ptr += strings[i].size() + 1;
+    }
+    // add NULL terminator
+    data_ptr = 0;
+    memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
+}
+
+LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
+                         int stdin_fd, int stdout_fd, int stderr_fd,
+                         vector<string> &argv, vector<string> &envp)
+    : Process(name, stdin_fd, stdout_fd, stderr_fd)
+{
+    prog_fname = argv[0];
+
+    prog_entry = objFile->entryPoint();
+    text_base = objFile->textBase();
+    text_size = objFile->textSize();
+    data_base = objFile->dataBase();
+    data_size = objFile->dataSize() + objFile->bssSize();
+    brk_point = RoundUp<uint64_t>(data_base + data_size, VMPageSize);
+
+    // load object file into target memory
+    objFile->loadSections(memory);
+
+    // Set up stack.  On Alpha, stack goes below text section.  This
+    // code should get moved to some architecture-specific spot.
+    stack_base = text_base - (409600+4096);
+
+    // Set up region for mmaps.  Tru64 seems to start just above 0 and
+    // grow up from there.
+    mmap_base = 0x10000;
+
+    // Set pointer for next thread stack.  Reserve 8M for main stack.
+    next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+
+    // Calculate how much space we need for arg & env arrays.
+    int argv_array_size = sizeof(Addr) * (argv.size() + 1);
+    int envp_array_size = sizeof(Addr) * (envp.size() + 1);
+    int arg_data_size = 0;
+    for (int i = 0; i < argv.size(); ++i) {
+        arg_data_size += argv[i].size() + 1;
+    }
+    int env_data_size = 0;
+    for (int i = 0; i < envp.size(); ++i) {
+        env_data_size += envp[i].size() + 1;
+    }
+
+    int space_needed =
+        argv_array_size + envp_array_size + arg_data_size + env_data_size;
+    // for SimpleScalar compatibility
+    if (space_needed < 16384)
+        space_needed = 16384;
+
+    // set bottom of stack
+    stack_min = stack_base - space_needed;
+    // align it
+    stack_min &= ~7;
+    stack_size = stack_base - stack_min;
+
+    // map out initial stack contents
+    Addr argv_array_base = stack_min + sizeof(uint64_t); // room for argc
+    Addr envp_array_base = argv_array_base + argv_array_size;
+    Addr arg_data_base = envp_array_base + envp_array_size;
+    Addr env_data_base = arg_data_base + arg_data_size;
+
+    // write contents to stack
+    uint64_t argc = argv.size();
+    memory->access(Write, stack_min, &argc, sizeof(uint64_t));
+
+    copyStringArray(argv, argv_array_base, arg_data_base, memory);
+    copyStringArray(envp, envp_array_base, env_data_base, memory);
+
+    init_regs->intRegFile[ArgumentReg0] = argc;
+    init_regs->intRegFile[ArgumentReg1] = argv_array_base;
+    init_regs->intRegFile[StackPointerReg] = stack_min;
+    init_regs->intRegFile[GlobalPointerReg] = objFile->globalPointer();
+    init_regs->pc = prog_entry;
+    init_regs->npc = prog_entry + sizeof(MachInst);
+}
+
+
+LiveProcess *
+LiveProcess::create(const string &name,
+                    int stdin_fd, int stdout_fd, int stderr_fd,
+                    vector<string> &argv, vector<string> &envp)
+{
+    LiveProcess *process = NULL;
+    ObjectFile *objFile = createObjectFile(argv[0]);
+    if (objFile == NULL) {
+        fatal("Can't load object file %s", argv[0]);
+    }
+
+    // check object type & set up syscall emulation pointer
+    if (objFile->getArch() == ObjectFile::Alpha) {
+        switch (objFile->getOpSys()) {
+          case ObjectFile::Tru64:
+            process = new AlphaTru64Process(name, objFile,
+                                            stdin_fd, stdout_fd, stderr_fd,
+                                            argv, envp);
+            break;
+
+          case ObjectFile::Linux:
+            process = new AlphaLinuxProcess(name, objFile,
+                                            stdin_fd, stdout_fd, stderr_fd,
+                                            argv, envp);
+            break;
+
+          default:
+            fatal("Unknown/unsupported operating system.");
+        }
+    } else {
+        fatal("Unknown object file architecture.");
+    }
+
+    delete objFile;
+
+    if (process == NULL)
+        fatal("Unknown error creating process object.");
+
+    return process;
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
+
+    VectorParam<string> cmd;
+    Param<string> input;
+    Param<string> output;
+    VectorParam<string> env;
+
+END_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
+
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(LiveProcess)
+
+    INIT_PARAM(cmd, "command line (executable plus arguments)"),
+    INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"),
+    INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"),
+    INIT_PARAM(env, "environment settings")
+
+END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
+
+
+CREATE_SIM_OBJECT(LiveProcess)
+{
+    // initialize file descriptors to default: same as simulator
+    int stdin_fd = input.isValid() ? Process::openInputFile(input) : 0;
+    int stdout_fd = output.isValid() ? Process::openOutputFile(output) : 1;
+    int stderr_fd = output.isValid() ? stdout_fd : 2;
+
+    // dummy for default env
+    vector<string> null_vec;
+
+    //  We do this with "temp" because of the bogus compiler warning
+    //  you get with g++ 2.95 -O if you just "return new LiveProcess(..."
+    LiveProcess *temp = LiveProcess::create(getInstanceName(),
+                                            stdin_fd, stdout_fd, stderr_fd,
+                                            cmd,
+                                            env.isValid() ? env : null_vec);
+
+    return temp;
+}
+
+
+REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)
diff --git a/sim/process.hh b/sim/process.hh
new file mode 100644 (file)
index 0000000..5df5736
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PROCESS_HH__
+#define __PROCESS_HH__
+
+//
+// The purpose of this code is to fake the loader & syscall mechanism
+// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
+// mode when we do have an OS.
+//
+#ifndef FULL_SYSTEM
+
+#include <vector>
+
+#include "targetarch/isa_traits.hh"
+#include "sim/sim_object.hh"
+#include "sim/sim_stats.hh"
+#include "base/statistics.hh"
+
+class ExecContext;
+class FunctionalMemory;
+class Process : public SimObject
+{
+  public:
+
+    // have we initialized an execution context from this process?  If
+    // yes, subsequent contexts are assumed to be for dynamically
+    // created threads and are not initialized.
+    bool initialContextLoaded;
+
+    // execution contexts associated with this process
+    std::vector<ExecContext *> execContexts;
+
+    // number of CPUs (esxec contexts, really) assigned to this process.
+    unsigned int numCpus() { return execContexts.size(); }
+
+    // record of blocked context
+    struct WaitRec
+    {
+        Addr waitChan;
+        ExecContext *waitingContext;
+
+        WaitRec(Addr chan, ExecContext *ctx)
+            : waitChan(chan), waitingContext(ctx)
+        {
+        }
+    };
+
+    // list of all blocked contexts
+    std::list<WaitRec> waitList;
+
+    RegFile *init_regs;                // initial register contents
+
+    Addr text_base;            // text (code) segment base
+    unsigned text_size;                // text (code) size in bytes
+
+    Addr data_base;            // initialized data segment base
+    unsigned data_size;                // initialized data + bss size in bytes
+
+    Addr brk_point;            // top of the data segment
+
+    Addr stack_base;           // stack segment base (highest address)
+    unsigned stack_size;       // initial stack size
+    Addr stack_min;            // lowest address accessed on the stack
+
+    // addr to use for next stack region (for multithreaded apps)
+    Addr next_thread_stack_base;
+
+    // Base of region for mmaps (when user doesn't specify an address).
+    Addr mmap_base;
+
+    std::string prog_fname;    // file name
+    Addr prog_entry;           // entry point (initial PC)
+
+    Statistics::Scalar<> num_syscalls; // number of syscalls executed
+
+
+  protected:
+    // constructor
+    Process(const std::string &name,
+            int stdin_fd,      // initial I/O descriptors
+            int stdout_fd,
+            int stderr_fd);
+
+
+  protected:
+    FunctionalMemory *memory;
+
+  private:
+    // file descriptor remapping support
+    static const int MAX_FD = 100;     // max legal fd value
+    int fd_map[MAX_FD+1];
+
+  public:
+    // static helper functions to generate file descriptors for constructor
+    static int openInputFile(const std::string &filename);
+    static int openOutputFile(const std::string &filename);
+
+    // override of virtual SimObject method: register statistics
+    virtual void regStats();
+
+    // register an execution context for this process.
+    // returns xc's cpu number (index into execContexts[])
+    int registerExecContext(ExecContext *xc);
+
+
+    void replaceExecContext(int xcIndex, ExecContext *xc);
+
+    // map simulator fd sim_fd to target fd tgt_fd
+    void dup_fd(int sim_fd, int tgt_fd);
+
+    // generate new target fd for sim_fd
+    int open_fd(int sim_fd);
+
+    // look up simulator fd for given target fd
+    int sim_fd(int tgt_fd);
+
+    // is this a valid instruction fetch address?
+    bool validInstAddr(Addr addr)
+    {
+        return (text_base <= addr &&
+                addr < text_base + text_size &&
+                !(addr & (sizeof(MachInst)-1)));
+    }
+
+    // is this a valid address? (used to filter data fetches)
+    // note that we just assume stack size <= 16MB
+    // this may be alpha-specific
+    bool validDataAddr(Addr addr)
+    {
+        return ((data_base <= addr && addr < brk_point) ||
+                ((stack_base - 16*1024*1024) <= addr && addr < stack_base) ||
+                (text_base <= addr && addr < (text_base + text_size)));
+    }
+
+    virtual void syscall(ExecContext *xc) = 0;
+
+    virtual FunctionalMemory *getMemory() { return memory; }
+};
+
+//
+// "Live" process with system calls redirected to host system
+//
+class ObjectFile;
+class LiveProcess : public Process
+{
+  protected:
+    LiveProcess(const std::string &name, ObjectFile *objFile,
+                int stdin_fd, int stdout_fd, int stderr_fd,
+                std::vector<std::string> &argv,
+                std::vector<std::string> &envp);
+
+  public:
+    // this function is used to create the LiveProcess object, since
+    // we can't tell which subclass of LiveProcess to use until we
+    // open and look at the object file.
+    static LiveProcess *create(const std::string &name,
+                               int stdin_fd, int stdout_fd, int stderr_fd,
+                               std::vector<std::string> &argv,
+                               std::vector<std::string> &envp);
+};
+
+
+#endif // !FULL_SYSTEM
+
+#endif // __PROCESS_HH__
diff --git a/sim/prog.cc b/sim/prog.cc
deleted file mode 100644 (file)
index fca4b45..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2003 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <cstdio>
-#include <string>
-
-#include "base/intmath.hh"
-#include "base/loader/object_file.hh"
-#include "base/statistics.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/full_cpu/smt.hh"
-#include "cpu/full_cpu/thread.hh"
-#include "eio/eio.hh"
-#include "mem/functional_mem/main_memory.hh"
-#include "sim/builder.hh"
-#include "sim/fake_syscall.hh"
-#include "sim/prog.hh"
-#include "sim/sim_stats.hh"
-
-using namespace std;
-
-//
-// The purpose of this code is to fake the loader & syscall mechanism
-// when there's no OS: thus there's no resone to use it in FULL_SYSTEM
-// mode when we do have an OS
-//
-#ifdef FULL_SYSTEM
-#error "prog.cc not compatible with FULL_SYSTEM"
-#endif
-
-// max allowable number of processes: should be no real cost to
-// cranking this up if necessary
-const int MAX_PROCESSES = 8;
-
-// current number of allocated processes
-int num_processes = 0;
-
-Process::Process(const string &name,
-                 int stdin_fd,         // initial I/O descriptors
-                 int stdout_fd,
-                 int stderr_fd)
-    : SimObject(name)
-{
-    // allocate memory space
-    memory = new MainMemory(name + ".MainMem");
-
-    // allocate initial register file
-    init_regs = new RegFile;
-
-    // initialize first 3 fds (stdin, stdout, stderr)
-    fd_map[STDIN_FILENO] = stdin_fd;
-    fd_map[STDOUT_FILENO] = stdout_fd;
-    fd_map[STDERR_FILENO] = stderr_fd;
-
-    // mark remaining fds as free
-    for (int i = 3; i <= MAX_FD; ++i) {
-        fd_map[i] = -1;
-    }
-
-    num_syscalls = 0;
-
-    // other parameters will be initialized when the program is loaded
-}
-
-void
-Process::regStats()
-{
-    using namespace Statistics;
-
-    num_syscalls
-        .name(name() + ".PROG:num_syscalls")
-        .desc("Number of system calls")
-        ;
-}
-
-//
-// static helper functions
-//
-int
-Process::openInputFile(const string &filename)
-{
-    int fd = open(filename.c_str(), O_RDONLY);
-
-    if (fd == -1) {
-        perror(NULL);
-        cerr << "unable to open \"" << filename << "\" for reading\n";
-        fatal("can't open input file");
-    }
-
-    return fd;
-}
-
-
-int
-Process::openOutputFile(const string &filename)
-{
-    int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774);
-
-    if (fd == -1) {
-        perror(NULL);
-        cerr << "unable to open \"" << filename << "\" for writing\n";
-        fatal("can't open output file");
-    }
-
-    return fd;
-}
-
-
-int
-Process::registerExecContext(ExecContext *xc)
-{
-    // add to list
-    int myIndex = execContexts.size();
-    execContexts.push_back(xc);
-
-    if (myIndex == 0) {
-        // first exec context for this process... initialize & enable
-
-        // copy process's initial regs struct
-        xc->regs = *init_regs;
-
-        // mark this context as active
-        xc->setStatus(ExecContext::Active);
-    }
-
-    // return CPU number to caller and increment available CPU count
-    return myIndex;
-}
-
-
-void
-Process::replaceExecContext(int xcIndex, ExecContext *xc)
-{
-    if (xcIndex >= execContexts.size()) {
-        panic("replaceExecContext: bad xcIndex, %d >= %d\n",
-              xcIndex, execContexts.size());
-    }
-
-    execContexts[xcIndex] = xc;
-}
-
-// map simulator fd sim_fd to target fd tgt_fd
-void
-Process::dup_fd(int sim_fd, int tgt_fd)
-{
-    if (tgt_fd < 0 || tgt_fd > MAX_FD)
-        panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd);
-
-    fd_map[tgt_fd] = sim_fd;
-}
-
-
-// generate new target fd for sim_fd
-int
-Process::open_fd(int sim_fd)
-{
-    int free_fd;
-
-    // in case open() returns an error, don't allocate a new fd
-    if (sim_fd == -1)
-        return -1;
-
-    // find first free target fd
-    for (free_fd = 0; fd_map[free_fd] >= 0; ++free_fd) {
-        if (free_fd == MAX_FD)
-            panic("Process::open_fd: out of file descriptors!");
-    }
-
-    fd_map[free_fd] = sim_fd;
-
-    return free_fd;
-}
-
-
-// look up simulator fd for given target fd
-int
-Process::sim_fd(int tgt_fd)
-{
-    if (tgt_fd > MAX_FD)
-        return -1;
-
-    return fd_map[tgt_fd];
-}
-
-
-
-//
-// need to declare these here since there is no concrete Process type
-// that can be constructed (i.e., no REGISTER_SIM_OBJECT() macro call,
-// which is where these get declared for concrete types).
-//
-DEFINE_SIM_OBJECT_CLASS_NAME("Process object", Process)
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// LiveProcess member definitions
-//
-////////////////////////////////////////////////////////////////////////
-
-
-static void
-copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
-                FunctionalMemory *memory)
-{
-    for (int i = 0; i < strings.size(); ++i) {
-        memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
-        memory->writeString(data_ptr, strings[i].c_str());
-        array_ptr += sizeof(Addr);
-        data_ptr += strings[i].size() + 1;
-    }
-    // add NULL terminator
-    data_ptr = 0;
-    memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
-}
-
-LiveProcess::LiveProcess(const string &name,
-                         int stdin_fd, int stdout_fd, int stderr_fd,
-                         vector<string> &argv, vector<string> &envp)
-    : Process(name, stdin_fd, stdout_fd, stderr_fd)
-{
-    prog_fname = argv[0];
-    ObjectFile *objFile = createObjectFile(prog_fname);
-    if (objFile == NULL) {
-        fatal("Can't load object file %s", prog_fname);
-    }
-
-    prog_entry = objFile->entryPoint();
-    text_base = objFile->textBase();
-    text_size = objFile->textSize();
-    data_base = objFile->dataBase();
-    data_size = objFile->dataSize() + objFile->bssSize();
-    brk_point = RoundUp<uint64_t>(data_base + data_size, VMPageSize);
-
-    // load object file into target memory
-    objFile->loadSections(memory);
-
-    // Set up stack.  On Alpha, stack goes below text section.  This
-    // code should get moved to some architecture-specific spot.
-    stack_base = text_base - (409600+4096);
-
-    // Set pointer for next thread stack.  Reserve 8M for main stack.
-    next_thread_stack_base = stack_base - (8 * 1024 * 1024);
-
-    // Calculate how much space we need for arg & env arrays.
-    int argv_array_size = sizeof(Addr) * (argv.size() + 1);
-    int envp_array_size = sizeof(Addr) * (envp.size() + 1);
-    int arg_data_size = 0;
-    for (int i = 0; i < argv.size(); ++i) {
-        arg_data_size += argv[i].size() + 1;
-    }
-    int env_data_size = 0;
-    for (int i = 0; i < envp.size(); ++i) {
-        env_data_size += envp[i].size() + 1;
-    }
-
-    int space_needed =
-        argv_array_size + envp_array_size + arg_data_size + env_data_size;
-    // for SimpleScalar compatibility
-    if (space_needed < 16384)
-        space_needed = 16384;
-
-    // set bottom of stack
-    stack_min = stack_base - space_needed;
-    // align it
-    stack_min &= ~7;
-    stack_size = stack_base - stack_min;
-
-    // map out initial stack contents
-    Addr argv_array_base = stack_min + sizeof(uint64_t); // room for argc
-    Addr envp_array_base = argv_array_base + argv_array_size;
-    Addr arg_data_base = envp_array_base + envp_array_size;
-    Addr env_data_base = arg_data_base + arg_data_size;
-
-    // write contents to stack
-    uint64_t argc = argv.size();
-    memory->access(Write, stack_min, &argc, sizeof(uint64_t));
-
-    copyStringArray(argv, argv_array_base, arg_data_base, memory);
-    copyStringArray(envp, envp_array_base, env_data_base, memory);
-
-    init_regs->intRegFile[ArgumentReg0] = argc;
-    init_regs->intRegFile[ArgumentReg1] = argv_array_base;
-    init_regs->intRegFile[StackPointerReg] = stack_min;
-    init_regs->intRegFile[GlobalPointerReg] = objFile->globalPointer();
-    init_regs->pc = prog_entry;
-    init_regs->npc = prog_entry + sizeof(MachInst);
-}
-
-
-void
-LiveProcess::syscall(ExecContext *xc)
-{
-    num_syscalls++;
-
-    fake_syscall(this, xc);
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
-
-    VectorParam<string> cmd;
-    Param<string> input;
-    Param<string> output;
-    VectorParam<string> env;
-
-END_DECLARE_SIM_OBJECT_PARAMS(LiveProcess)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(LiveProcess)
-
-    INIT_PARAM(cmd, "command line (executable plus arguments)"),
-    INIT_PARAM(input, "filename for stdin (dflt: use sim stdin)"),
-    INIT_PARAM(output, "filename for stdout/stderr (dflt: use sim stdout)"),
-    INIT_PARAM(env, "environment settings")
-
-END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
-
-
-CREATE_SIM_OBJECT(LiveProcess)
-{
-    // initialize file descriptors to default: same as simulator
-    int stdin_fd = input.isValid() ? Process::openInputFile(input) : 0;
-    int stdout_fd = output.isValid() ? Process::openOutputFile(output) : 1;
-    int stderr_fd = output.isValid() ? stdout_fd : 2;
-
-    // dummy for default env
-    vector<string> null_vec;
-
-    //  We do this with "temp" because of the bogus compiler warning
-    //  you get with g++ 2.95 -O if you just "return new LiveProcess(..."
-    LiveProcess *temp = new LiveProcess(getInstanceName(),
-                                        stdin_fd, stdout_fd, stderr_fd,
-                                        cmd,
-                                        env.isValid() ? env : null_vec);
-
-    return temp;
-}
-
-
-REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)
diff --git a/sim/prog.hh b/sim/prog.hh
deleted file mode 100644 (file)
index e93dd68..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 2003 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __PROG_HH__
-#define __PROG_HH__
-
-//
-// The purpose of this code is to fake the loader & syscall mechanism
-// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
-// mode when we do have an OS.
-//
-#ifndef FULL_SYSTEM
-
-#include <vector>
-
-#include "targetarch/isa_traits.hh"
-#include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
-#include "base/statistics.hh"
-
-class ExecContext;
-class FunctionalMemory;
-class Process : public SimObject
-{
-  public:
-
-    // have we initialized an execution context from this process?  If
-    // yes, subsequent contexts are assumed to be for dynamically
-    // created threads and are not initialized.
-    bool initialContextLoaded;
-
-    // execution contexts associated with this process
-    std::vector<ExecContext *> execContexts;
-
-    // number of CPUs (esxec contexts, really) assigned to this process.
-    unsigned int numCpus() { return execContexts.size(); }
-
-    // record of blocked context
-    struct WaitRec
-    {
-        Addr waitChan;
-        ExecContext *waitingContext;
-
-        WaitRec(Addr chan, ExecContext *ctx)
-            : waitChan(chan), waitingContext(ctx)
-        {
-        }
-    };
-
-    // list of all blocked contexts
-    std::list<WaitRec> waitList;
-
-    RegFile *init_regs;                // initial register contents
-
-    Addr text_base;            // text (code) segment base
-    unsigned text_size;                // text (code) size in bytes
-
-    Addr data_base;            // initialized data segment base
-    unsigned data_size;                // initialized data + bss size in bytes
-
-    Addr brk_point;            // top of the data segment
-
-    Addr stack_base;           // stack segment base (highest address)
-    unsigned stack_size;       // initial stack size
-    Addr stack_min;            // lowest address accessed on the stack
-
-
-    // addr to use for next stack region (for multithreaded apps)
-    Addr next_thread_stack_base;
-
-    std::string prog_fname;    // file name
-    Addr prog_entry;           // entry point (initial PC)
-
-    Statistics::Scalar<> num_syscalls; // number of syscalls executed
-
-
-  protected:
-    // constructor
-    Process(const std::string &name,
-            int stdin_fd,      // initial I/O descriptors
-            int stdout_fd,
-            int stderr_fd);
-
-
-  protected:
-    FunctionalMemory *memory;
-
-  private:
-    // file descriptor remapping support
-    static const int MAX_FD = 100;     // max legal fd value
-    int fd_map[MAX_FD+1];
-
-  public:
-    // static helper functions to generate file descriptors for constructor
-    static int openInputFile(const std::string &filename);
-    static int openOutputFile(const std::string &filename);
-
-    // override of virtual SimObject method: register statistics
-    virtual void regStats();
-
-    // register an execution context for this process.
-    // returns xc's cpu number (index into execContexts[])
-    int registerExecContext(ExecContext *xc);
-
-
-    void replaceExecContext(int xcIndex, ExecContext *xc);
-
-    // map simulator fd sim_fd to target fd tgt_fd
-    void dup_fd(int sim_fd, int tgt_fd);
-
-    // generate new target fd for sim_fd
-    int open_fd(int sim_fd);
-
-    // look up simulator fd for given target fd
-    int sim_fd(int tgt_fd);
-
-    // is this a valid instruction fetch address?
-    bool validInstAddr(Addr addr)
-    {
-        return (text_base <= addr &&
-                addr < text_base + text_size &&
-                !(addr & (sizeof(MachInst)-1)));
-    }
-
-    // is this a valid address? (used to filter data fetches)
-    // note that we just assume stack size <= 16MB
-    // this may be alpha-specific
-    bool validDataAddr(Addr addr)
-    {
-        return ((data_base <= addr && addr < brk_point) ||
-                ((stack_base - 16*1024*1024) <= addr && addr < stack_base) ||
-                (text_base <= addr && addr < (text_base + text_size)));
-    }
-
-    virtual void syscall(ExecContext *xc) = 0;
-
-    virtual FunctionalMemory *getMemory() { return memory; }
-};
-
-//
-// "Live" process with system calls redirected to host system
-//
-class MainMemory;
-class LiveProcess : public Process
-{
-  public:
-    LiveProcess(const std::string &name,
-                int stdin_fd, int stdout_fd, int stderr_fd,
-                std::vector<std::string> &argv,
-                std::vector<std::string> &envp);
-
-    virtual void syscall(ExecContext *xc);
-};
-
-#endif // !FULL_SYSTEM
-
-#endif // __PROG_HH__
diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc
new file mode 100644 (file)
index 0000000..0e4e786
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+
+#include <string>
+#include <iostream>
+
+#include "sim/syscall_emul.hh"
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base_cpu.hh"
+#include "sim/process.hh"
+
+#include "sim/sim_events.hh"
+
+using namespace std;
+
+void
+SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
+{
+    DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
+             xc->cpu->name(), name);
+
+    int retval = (*funcPtr)(this, callnum, process, xc);
+
+    DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
+             xc->cpu->name(), name, retval);
+
+    if (!((flags & SyscallDesc::SuppressReturnValue) && retval == 0))
+        xc->setSyscallReturn(retval);
+}
+
+
+//
+// Handler for unimplemented syscalls that we haven't thought about.
+//
+int
+unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
+                  ExecContext *xc)
+{
+    cerr << "Error: syscall " << desc->name
+         << " (#" << callnum << ") unimplemented.";
+    cerr << "  Args: " << xc->getSyscallArg(0) << ", " << xc->getSyscallArg(1)
+         << ", ..." << endl;
+
+    abort();
+}
+
+
+//
+// Handler for unimplemented syscalls that we never intend to
+// implement (signal handling, etc.) and should not affect the correct
+// behavior of the program.  Print a warning only if the appropriate
+// trace flag is enabled.  Return success to the target program.
+//
+int
+ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
+           ExecContext *xc)
+{
+    DCOUT(SyscallWarnings) << "Warning: ignoring syscall " << desc->name
+                           << "(" << xc->getSyscallArg(0)
+                           << ", " << xc->getSyscallArg(1)
+                           << ", ...)" << endl;
+
+    return 0;
+}
+
+
+int
+exitFunc(SyscallDesc *desc, int callnum, Process *process,
+         ExecContext *xc)
+{
+    new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
+
+    return 1;
+}
+
+
+int
+getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    return VMPageSize;
+}
+
+
+int
+obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    // change brk addr to first arg
+    p->brk_point = xc->getSyscallArg(0);
+    return p->brk_point;
+}
+
+
+int
+closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    int fd = p->sim_fd(xc->getSyscallArg(0));
+    return close(fd);
+}
+
+
+int
+readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    int fd = p->sim_fd(xc->getSyscallArg(0));
+    int nbytes = xc->getSyscallArg(2);
+    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+
+    int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
+
+    if (bytes_read != -1)
+        bufArg.copyOut(xc->mem);
+
+    return bytes_read;
+}
+
+int
+writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    int fd = p->sim_fd(xc->getSyscallArg(0));
+    int nbytes = xc->getSyscallArg(2);
+    BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+
+    bufArg.copyIn(xc->mem);
+
+    int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
+
+    fsync(fd);
+
+    return bytes_written;
+}
+
+
+int
+lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    int fd = p->sim_fd(xc->getSyscallArg(0));
+    uint64_t offs = xc->getSyscallArg(1);
+    int whence = xc->getSyscallArg(2);
+
+    off_t result = lseek(fd, offs, whence);
+
+    return (result == (off_t)-1) ? -errno : result;
+}
+
+
+int
+munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    // given that we don't really implement mmap, munmap is really easy
+    return 0;
+}
+
+
+const char *hostname = "m5.eecs.umich.edu";
+
+int
+gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    int name_len = xc->getSyscallArg(1);
+    BufferArg name(xc->getSyscallArg(0), name_len);
+
+    strncpy((char *)name.bufferPtr(), hostname, name_len);
+
+    name.copyOut(xc->mem);
+
+    return 0;
+}
+
+
diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh
new file mode 100644 (file)
index 0000000..a02b4a6
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYSCALL_EMUL_HH__
+#define __SYSCALL_EMUL_HH__
+
+///
+/// @file syscall_emul.hh
+///
+/// This file defines objects used to emulate syscalls from the target
+/// application on the host machine.
+
+#include <string>
+
+#include "base/intmath.hh"     // for RoundUp
+#include "targetarch/isa_traits.hh"    // for Addr
+#include "mem/functional_mem/functional_memory.hh"
+
+class Process;
+class ExecContext;
+
+///
+/// System call descriptor.
+///
+class SyscallDesc {
+
+  public:
+
+    typedef int (*FuncPtr)(SyscallDesc *, int num,
+                           Process *, ExecContext *);
+
+    const char *name;  //!< Syscall name (e.g., "open").
+    FuncPtr funcPtr;   //!< Pointer to emulation function.
+    int flags;         //!< Flags (see Flags enum).
+
+
+    /// Flag values for controlling syscall behavior.
+    enum Flags {
+        /// Don't set return regs according to funcPtr return value.
+        /// Used for syscalls with non-standard return conventions
+        /// that explicitly set the ExecContext regs (e.g.,
+        /// sigreturn).
+        SuppressReturnValue = 1
+    };
+
+    /// Constructor.
+    SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
+        : name(_name), funcPtr(_funcPtr), flags(_flags)
+    {
+    }
+
+    /// Emulate the syscall.  Public interface for calling through funcPtr.
+    void doSyscall(int callnum, Process *proc, ExecContext *xc);
+};
+
+
+class BaseBufferArg {
+
+  public:
+
+    BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
+    {
+        bufPtr = new uint8_t[size];
+        // clear out buffer: in case we only partially populate this,
+        // and then do a copyOut(), we want to make sure we don't
+        // introduce any random junk into the simulated address space
+        memset(bufPtr, 0, size);
+    }
+
+    virtual ~BaseBufferArg() { delete [] bufPtr; }
+
+    //
+    // copy data into simulator space (read from target memory)
+    //
+    virtual bool copyIn(FunctionalMemory *mem)
+    {
+        mem->access(Read, addr, bufPtr, size);
+        return true;   // no EFAULT detection for now
+    }
+
+    //
+    // copy data out of simulator space (write to target memory)
+    //
+    virtual bool copyOut(FunctionalMemory *mem)
+    {
+        mem->access(Write, addr, bufPtr, size);
+        return true;   // no EFAULT detection for now
+    }
+
+  protected:
+    Addr addr;
+    int size;
+    uint8_t *bufPtr;
+};
+
+
+class BufferArg : public BaseBufferArg
+{
+  public:
+    BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
+    void *bufferPtr()  { return bufPtr; }
+};
+
+template <class T>
+class TypedBufferArg : public BaseBufferArg
+{
+  public:
+    // user can optionally specify a specific number of bytes to
+    // allocate to deal with those structs that have variable-size
+    // arrays at the end
+    TypedBufferArg(Addr _addr, int _size = sizeof(T))
+        : BaseBufferArg(_addr, _size)
+    { }
+
+    // type case
+    operator T*() { return (T *)bufPtr; }
+
+    // dereference operators
+    T& operator*()      { return *((T *)bufPtr); }
+    T* operator->()     { return (T *)bufPtr; }
+    T& operator[](int i) { return ((T *)bufPtr)[i]; }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// The following emulation functions are generic enough that they
+// don't need to be recompiled for different emulated OS's.  They are
+// defined in sim/syscall_emul.cc.
+//
+//////////////////////////////////////////////////////////////////////
+
+
+int unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+
+int exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+int gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+
+//////////////////////////////////////////////////////////////////////
+//
+// The following emulation functions are generic, but need to be
+// templated to account for differences in types, constants, etc.
+//
+//////////////////////////////////////////////////////////////////////
+
+template <class OS>
+int
+ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    int fd = xc->getSyscallArg(0);
+    unsigned req = xc->getSyscallArg(1);
+
+    // DPRINTFR(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
+
+    if (fd < 0 || process->sim_fd(fd) < 0) {
+        // doesn't map to any simulator fd: not a valid target fd
+        return -EBADF;
+    }
+
+    switch (req) {
+      case OS::TIOCISATTY:
+      case OS::TIOCGETP:
+      case OS::TIOCSETP:
+      case OS::TIOCSETN:
+      case OS::TIOCSETC:
+      case OS::TIOCGETC:
+        return -ENOTTY;
+
+      default:
+        fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...)\n", fd, req);
+    }
+}
+
+struct OpenFlagTransTable {
+    int tgtFlag;
+    int hostFlag;
+};
+
+
+template <class OS>
+int
+openFunc(SyscallDesc *desc, int callnum, Process *process,
+         ExecContext *xc)
+{
+    std::string path;
+
+    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+        return -EFAULT;
+
+    if (path == "/dev/sysdev0") {
+        // This is a memory-mapped high-resolution timer device on Alpha.
+        // We don't support it, so just punt.
+        DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl;
+        return -ENOENT;
+    }
+
+    int tgtFlags = xc->getSyscallArg(1);
+    int mode = xc->getSyscallArg(2);
+    int hostFlags = 0;
+
+    // translate open flags
+    for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
+        if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
+            tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
+            hostFlags |= OS::openFlagTable[i].hostFlag;
+        }
+    }
+
+    // any target flags left?
+    if (tgtFlags != 0)
+        cerr << "Syscall: open: cannot decode flags: " <<  tgtFlags << endl;
+
+#ifdef __CYGWIN32__
+    hostFlags |= O_BINARY;
+#endif
+
+    // open the file
+    int fd = open(path.c_str(), hostFlags, mode);
+
+    return (fd == -1) ? -errno : process->open_fd(fd);
+}
+
+
+template <class OS>
+int
+statFunc(SyscallDesc *desc, int callnum, Process *process,
+         ExecContext *xc)
+{
+    std::string path;
+
+    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+        return -EFAULT;
+
+    struct stat hostBuf;
+    int result = stat(path.c_str(), &hostBuf);
+
+    if (result < 0)
+        return -errno;
+
+    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+
+    return 0;
+}
+
+
+template <class OS>
+int
+lstatFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    std::string path;
+
+    if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
+        return -EFAULT;
+
+    struct stat hostBuf;
+    int result = lstat(path.c_str(), &hostBuf);
+
+    if (result < 0)
+        return -errno;
+
+    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+
+    return 0;
+}
+
+template <class OS>
+int
+fstatFunc(SyscallDesc *desc, int callnum, Process *process,
+          ExecContext *xc)
+{
+    int fd = process->sim_fd(xc->getSyscallArg(0));
+
+    // DPRINTFR(SyscallVerbose, "fstat(%d, ...)\n", fd);
+
+    if (fd < 0)
+        return -EBADF;
+
+    struct stat hostBuf;
+    int result = fstat(fd, &hostBuf);
+
+    if (result < 0)
+        return -errno;
+
+    OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
+
+    return 0;
+}
+
+
+//
+// We don't really handle mmap().  If the target is mmaping an
+// anonymous region or /dev/zero, we can get away with doing basically
+// nothing (since memory is initialized to zero and the simulator
+// doesn't really check addresses anyway).  Always print a warning,
+// since this could be seriously broken if we're not mapping
+// /dev/zero.
+//
+// Someday we should explicitly check for /dev/zero in open, flag the
+// file descriptor, and fail (or implement!) a non-anonymous mmap to
+// anything else.
+//
+template <class OS>
+int
+mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+    Addr start = xc->getSyscallArg(0);
+    uint64_t length = xc->getSyscallArg(1);
+    // int prot = xc->getSyscallArg(2);
+    int flags = xc->getSyscallArg(3);
+    int fd = p->sim_fd(xc->getSyscallArg(4));
+    // int offset = xc->getSyscallArg(5);
+
+    if (start == 0) {
+        // user didn't give an address... pick one from our "mmap region"
+        start = p->mmap_base;
+        p->mmap_base += RoundUp<Addr>(length, VMPageSize);
+    }
+
+    if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
+        DPRINTF(SyscallWarnings, "Warning: allowing mmap of file @ fd %d.  "
+                "This will break if not /dev/zero.", fd);
+    }
+
+    return start;
+}
+
+
+template <class OS>
+int
+getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
+              ExecContext *xc)
+{
+    unsigned resource = xc->getSyscallArg(0);
+    TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
+
+    switch (resource) {
+      case OS::RLIMIT_STACK:
+        // max stack size in bytes: make up a number (2MB for now)
+        rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
+        break;
+
+      default:
+        cerr << "getrlimitFunc: unimplemented resource " << resource << endl;
+        abort();
+        break;
+    }
+
+    rlp.copyOut(xc->mem);
+    return 0;
+}
+
+// 1M usecs in 1 sec, for readability
+const int one_million = 1000000;
+
+// seconds since the epoch (1/1/1970)... about a billion, by my reckoning
+const unsigned seconds_since_epoch = 1000000000;
+
+//
+// helper function: populate struct timeval with approximation of
+// current elapsed time
+//
+template <class T1, class T2>
+void
+getElapsedTime(T1 &sec, T2 &usec)
+{
+    int cycles_per_usec = ticksPerSecond / one_million;
+
+    int elapsed_usecs = curTick / cycles_per_usec;
+    sec = elapsed_usecs / one_million;
+    usec = elapsed_usecs % one_million;
+}
+
+
+template <class OS>
+int
+gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
+                 ExecContext *xc)
+{
+    TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
+
+    getElapsedTime(tp->tv_sec, tp->tv_usec);
+    tp->tv_sec += seconds_since_epoch;
+
+    tp.copyOut(xc->mem);
+
+    return 0;
+}
+
+
+template <class OS>
+int
+getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
+              ExecContext *xc)
+{
+    int who = xc->getSyscallArg(0);    // THREAD, SELF, or CHILDREN
+    TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
+
+    if (who != OS::RUSAGE_SELF) {
+        // don't really handle THREAD or CHILDREN, but just warn and
+        // plow ahead
+        DCOUT(SyscallWarnings)
+            << "Warning: getrusage() only supports RUSAGE_SELF."
+            << "  Parameter " << who << " ignored." << endl;
+    }
+
+    getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
+    rup->ru_stime.tv_sec = 0;
+    rup->ru_stime.tv_usec = 0;
+    rup->ru_maxrss = 0;
+    rup->ru_ixrss = 0;
+    rup->ru_idrss = 0;
+    rup->ru_isrss = 0;
+    rup->ru_minflt = 0;
+    rup->ru_majflt = 0;
+    rup->ru_nswap = 0;
+    rup->ru_inblock = 0;
+    rup->ru_oublock = 0;
+    rup->ru_msgsnd = 0;
+    rup->ru_msgrcv = 0;
+    rup->ru_nsignals = 0;
+    rup->ru_nvcsw = 0;
+    rup->ru_nivcsw = 0;
+
+    rup.copyOut(xc->mem);
+
+    return 0;
+}
+
+
+
+#endif // __SYSCALL_EMUL_HH__