simplesim-3.0/target-pisa/syscall.c

2036 lines
52 KiB
C

/* syscall.c - proxy system call handler routines */
/* SimpleScalar(TM) Tool Suite
* Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC.
* All Rights Reserved.
*
* THIS IS A LEGAL DOCUMENT, BY USING SIMPLESCALAR,
* YOU ARE AGREEING TO THESE TERMS AND CONDITIONS.
*
* No portion of this work may be used by any commercial entity, or for any
* commercial purpose, without the prior, written permission of SimpleScalar,
* LLC (info@simplescalar.com). Nonprofit and noncommercial use is permitted
* as described below.
*
* 1. SimpleScalar is provided AS IS, with no warranty of any kind, express
* or implied. The user of the program accepts full responsibility for the
* application of the program and the use of any results.
*
* 2. Nonprofit and noncommercial use is encouraged. SimpleScalar may be
* downloaded, compiled, executed, copied, and modified solely for nonprofit,
* educational, noncommercial research, and noncommercial scholarship
* purposes provided that this notice in its entirety accompanies all copies.
* Copies of the modified software can be delivered to persons who use it
* solely for nonprofit, educational, noncommercial research, and
* noncommercial scholarship purposes provided that this notice in its
* entirety accompanies all copies.
*
* 3. ALL COMMERCIAL USE, AND ALL USE BY FOR PROFIT ENTITIES, IS EXPRESSLY
* PROHIBITED WITHOUT A LICENSE FROM SIMPLESCALAR, LLC (info@simplescalar.com).
*
* 4. No nonprofit user may place any restrictions on the use of this software,
* including as modified by the user, by any other authorized user.
*
* 5. Noncommercial and nonprofit users may distribute copies of SimpleScalar
* in compiled or executable form as set forth in Section 2, provided that
* either: (A) it is accompanied by the corresponding machine-readable source
* code, or (B) it is accompanied by a written offer, with no time limit, to
* give anyone a machine-readable copy of the corresponding source code in
* return for reimbursement of the cost of distribution. This written offer
* must permit verbatim duplication by anyone, or (C) it is distributed by
* someone who received only the executable form, and is accompanied by a
* copy of the written offer of source code.
*
* 6. SimpleScalar was developed by Todd M. Austin, Ph.D. The tool suite is
* currently maintained by SimpleScalar LLC (info@simplescalar.com). US Mail:
* 2395 Timbercrest Court, Ann Arbor, MI 48105.
*
* Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC.
*/
#include <stdio.h>
#include <stdlib.h>
#include "host.h"
#include "misc.h"
#include "machine.h"
#include "regs.h"
#include "memory.h"
#include "loader.h"
#include "sim.h"
#include "endian.h"
#include "eio.h"
#include "syscall.h"
/* live execution only support on same-endian hosts... */
#ifndef MD_CROSS_ENDIAN
#ifdef _MSC_VER
#include <io.h>
#else /* !_MSC_VER */
#include <unistd.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#ifndef _MSC_VER
#include <sys/param.h>
#endif
#include <errno.h>
#include <time.h>
#ifndef _MSC_VER
#include <sys/time.h>
#endif
#ifndef _MSC_VER
#include <sys/resource.h>
#endif
#include <signal.h>
/* #include <sys/file.h> */
#include <sys/stat.h>
#ifndef _MSC_VER
#include <sys/uio.h>
#endif
#include <setjmp.h>
#ifndef _MSC_VER
#include <sys/times.h>
#endif
#include <limits.h>
#ifndef _MSC_VER
#include <sys/ioctl.h>
#endif
#if !defined(linux) && !defined(sparc) && !defined(hpux) && !defined(__hpux) && !defined(__CYGWIN32__) && !defined(ultrix)
#ifndef _MSC_VER
#include <sys/select.h>
#endif
#endif
#ifdef linux
#include <utime.h>
#include <sgtty.h>
#endif /* linux */
#if defined(hpux) || defined(__hpux)
#include <sgtty.h>
#endif
#ifdef __svr4__
#include "utime.h"
#endif
#if defined(sparc) && defined(__unix__)
#if defined(__svr4__) || defined(__USLC__)
#include <dirent.h>
#else
#include <sys/dir.h>
#endif
/* dorks */
#undef NL0
#undef NL1
#undef CR0
#undef CR1
#undef CR2
#undef CR3
#undef TAB0
#undef TAB1
#undef TAB2
#undef XTABS
#undef BS0
#undef BS1
#undef FF0
#undef FF1
#undef ECHO
#undef NOFLSH
#undef TOSTOP
#undef FLUSHO
#undef PENDIN
#endif
#if defined(hpux) || defined(__hpux)
#undef CR0
#endif
#ifdef __FreeBSD__
#include <termios.h>
/*#include <sys/ioctl_compat.h>*/
#else /* !__FreeBSD__ */
#ifndef _MSC_VER
#include <termio.h>
#endif
#endif
#if defined(hpux) || defined(__hpux)
/* et tu, dorks! */
#undef HUPCL
#undef ECHO
#undef B50
#undef B75
#undef B110
#undef B134
#undef B150
#undef B200
#undef B300
#undef B600
#undef B1200
#undef B1800
#undef B2400
#undef B4800
#undef B9600
#undef B19200
#undef B38400
#undef NL0
#undef NL1
#undef CR0
#undef CR1
#undef CR2
#undef CR3
#undef TAB0
#undef TAB1
#undef BS0
#undef BS1
#undef FF0
#undef FF1
#undef EXTA
#undef EXTB
#undef B900
#undef B3600
#undef B7200
#undef XTABS
#include <sgtty.h>
#include <utime.h>
#endif
#ifdef _MSC_VER
#define access _access
#define chmod _chmod
#define chdir _chdir
#define unlink _unlink
#define open _open
#define creat _creat
#define pipe _pipe
#define dup _dup
#define dup2 _dup2
#define stat _stat
#define fstat _fstat
#define lseek _lseek
#define read _read
#define write _write
#define close _close
#define getpid _getpid
#define utime _utime
#include <sys/utime.h>
#endif /* _MSC_VER */
/* SimpleScalar SStrix (a derivative of Ultrix) system call codes, note these
codes reside in register $r2 at the point a `syscall' inst is executed,
not all of these codes are implemented, see the main switch statement in
syscall.c for a list of implemented system calls */
#define SS_SYS_syscall 0
/* SS_SYS_exit was moved to pisa.h */
#define SS_SYS_fork 2
#define SS_SYS_read 3
/* SS_SYS_write was moved to pisa.h */
#define SS_SYS_open 5
#define SS_SYS_close 6
/* 7 is old: wait */
#define SS_SYS_creat 8
#define SS_SYS_link 9
#define SS_SYS_unlink 10
#define SS_SYS_execv 11
#define SS_SYS_chdir 12
/* 13 is old: time */
#define SS_SYS_mknod 14
#define SS_SYS_chmod 15
#define SS_SYS_chown 16
#define SS_SYS_brk 17 /* 17 is old: sbreak */
/* 18 is old: stat */
#define SS_SYS_lseek 19
#define SS_SYS_getpid 20
#define SS_SYS_mount 21
#define SS_SYS_umount 22
/* 23 is old: setuid */
#define SS_SYS_getuid 24
/* 25 is old: stime */
#define SS_SYS_ptrace 26
/* 27 is old: alarm */
/* 28 is old: fstat */
/* 29 is old: pause */
/* 30 is old: utime */
/* 31 is old: stty */
/* 32 is old: gtty */
#define SS_SYS_access 33
/* 34 is old: nice */
/* 35 is old: ftime */
#define SS_SYS_sync 36
#define SS_SYS_kill 37
#define SS_SYS_stat 38
/* 39 is old: setpgrp */
#define SS_SYS_lstat 40
#define SS_SYS_dup 41
#define SS_SYS_pipe 42
/* 43 is old: times */
#define SS_SYS_profil 44
/* 45 is unused */
/* 46 is old: setgid */
#define SS_SYS_getgid 47
/* 48 is old: sigsys */
/* 49 is unused */
/* 50 is unused */
#define SS_SYS_acct 51
/* 52 is old: phys */
/* 53 is old: syslock */
#define SS_SYS_ioctl 54
#define SS_SYS_reboot 55
/* 56 is old: mpxchan */
#define SS_SYS_symlink 57
#define SS_SYS_readlink 58
#define SS_SYS_execve 59
#define SS_SYS_umask 60
#define SS_SYS_chroot 61
#define SS_SYS_fstat 62
/* 63 is unused */
#define SS_SYS_getpagesize 64
#define SS_SYS_mremap 65
#define SS_SYS_vfork 66 /* 66 is old: vfork */
/* 67 is old: vread */
/* 68 is old: vwrite */
#define SS_SYS_sbrk 69
#define SS_SYS_sstk 70
#define SS_SYS_mmap 71
#define SS_SYS_vadvise 72 /* 72 is old: vadvise */
#define SS_SYS_munmap 73
#define SS_SYS_mprotect 74
#define SS_SYS_madvise 75
#define SS_SYS_vhangup 76
/* 77 is old: vlimit */
#define SS_SYS_mincore 78
#define SS_SYS_getgroups 79
#define SS_SYS_setgroups 80
#define SS_SYS_getpgrp 81
#define SS_SYS_setpgrp 82
#define SS_SYS_setitimer 83
#define SS_SYS_wait3 84
#define SS_SYS_wait SYS_wait3
#define SS_SYS_swapon 85
#define SS_SYS_getitimer 86
#define SS_SYS_gethostname 87
#define SS_SYS_sethostname 88
#define SS_SYS_getdtablesize 89
#define SS_SYS_dup2 90
#define SS_SYS_getdopt 91
#define SS_SYS_fcntl 92
#define SS_SYS_select 93
#define SS_SYS_setdopt 94
#define SS_SYS_fsync 95
#define SS_SYS_setpriority 96
#define SS_SYS_socket 97
#define SS_SYS_connect 98
#define SS_SYS_accept 99
#define SS_SYS_getpriority 100
#define SS_SYS_send 101
#define SS_SYS_recv 102
#define SS_SYS_sigreturn 103 /* new sigreturn */
/* 103 was socketaddr */
#define SS_SYS_bind 104
#define SS_SYS_setsockopt 105
#define SS_SYS_listen 106
/* 107 was vtimes */
#define SS_SYS_sigvec 108
#define SS_SYS_sigblock 109
#define SS_SYS_sigsetmask 110
#define SS_SYS_sigpause 111
#define SS_SYS_sigstack 112
#define SS_SYS_recvmsg 113
#define SS_SYS_sendmsg 114
/* 115 is old vtrace */
#define SS_SYS_gettimeofday 116
#define SS_SYS_getrusage 117
#define SS_SYS_getsockopt 118
/* 119 is old resuba */
#define SS_SYS_readv 120
#define SS_SYS_writev 121
#define SS_SYS_settimeofday 122
#define SS_SYS_fchown 123
#define SS_SYS_fchmod 124
#define SS_SYS_recvfrom 125
#define SS_SYS_setreuid 126
#define SS_SYS_setregid 127
#define SS_SYS_rename 128
#define SS_SYS_truncate 129
#define SS_SYS_ftruncate 130
#define SS_SYS_flock 131
/* 132 is unused */
#define SS_SYS_sendto 133
#define SS_SYS_shutdown 134
#define SS_SYS_socketpair 135
#define SS_SYS_mkdir 136
#define SS_SYS_rmdir 137
#define SS_SYS_utimes 138
#define SS_SYS_sigcleanup 139 /* From 4.2 longjmp */
/* same as SYS_sigreturn */
#define SS_SYS_adjtime 140
#define SS_SYS_getpeername 141
#define SS_SYS_gethostid 142
#define SS_SYS_sethostid 143
#define SS_SYS_getrlimit 144
#define SS_SYS_setrlimit 145
#define SS_SYS_killpg 146
/* 147 is unused */
#define SS_SYS_setquota 148
#define SS_SYS_quota 149
#define SS_SYS_getsockname 150
#define SS_SYS_sysmips 151 /* floating point control */
/* formerly mips local system calls */
#define SS_SYS_cacheflush 152
#define SS_SYS_cachectl 153
#define SS_SYS_atomic_op 155
/* nfs releated system calls */
#define SS_SYS_debug 154
#define SS_SYS_statfs 160
#define SS_SYS_fstatfs 161
#define SS_SYS_unmount 162
#define SS_SYS_quotactl 168
/* #define SS_SYS_mount 170 */
#define SS_SYS_hdwconf 171
/* try to keep binary compatibility with mips */
#define SS_SYS_nfs_svc 158
#define SS_SYS_nfssvc 158 /* cruft - delete when kernel fixed */
#define SS_SYS_nfs_biod 163
#define SS_SYS_async_daemon 163 /* cruft - delete when kernel fixed */
#define SS_SYS_nfs_getfh 164
#define SS_SYS_getfh 164 /* cruft - delete when kernel fixed */
#define SS_SYS_getdirentries 159
#define SS_SYS_getdomainname 165
#define SS_SYS_setdomainname 166
#define SS_SYS_exportfs 169
#define SS_SYS_msgctl 172
#define SS_SYS_msgget 173
#define SS_SYS_msgrcv 174
#define SS_SYS_msgsnd 175
#define SS_SYS_semctl 176
#define SS_SYS_semget 177
#define SS_SYS_semop 178
#define SS_SYS_uname 179
#define SS_SYS_shmsys 180
#define SS_SYS_plock 181
#define SS_SYS_lockf 182
#define SS_SYS_ustat 183
#define SS_SYS_getmnt 184
#define SS_SYS_sigpending 187
#define SS_SYS_setsid 188
#define SS_SYS_waitpid 189
#define SS_SYS_utc_gettime 233 /* 233 -- same as OSF/1 */
#define SS_SYS_utc_adjtime 234 /* 234 -- same as OSF/1 */
#define SS_SYS_audcntl 252
#define SS_SYS_audgen 253
#define SS_SYS_startcpu 254 /* 254 -- Ultrix Private */
#define SS_SYS_stopcpu 255 /* 255 -- Ultrix Private */
#define SS_SYS_getsysinfo 256 /* 256 -- Ultrix Private */
#define SS_SYS_setsysinfo 257 /* 257 -- Ultrix Private */
/* SStrix ioctl values */
#define SS_IOCTL_TIOCGETP 1074164744
#define SS_IOCTL_TIOCSETP -2147060727
#define SS_IOCTL_TCGETP 1076130901
#define SS_IOCTL_TCGETA 1075082331
#define SS_IOCTL_TIOCGLTC 1074164852
#define SS_IOCTL_TIOCSLTC -2147060619
#define SS_IOCTL_TIOCGWINSZ 1074295912
#define SS_IOCTL_TCSETAW -2146143143
#define SS_IOCTL_TIOCGETC 1074164754
#define SS_IOCTL_TIOCSETC -2147060719
#define SS_IOCTL_TIOCLBIC -2147191682
#define SS_IOCTL_TIOCLBIS -2147191681
#define SS_IOCTL_TIOCLGET 0x4004747c
#define SS_IOCTL_TIOCLSET -2147191683
/* internal system call buffer size, used primarily for file name arguments,
argument larger than this will be truncated */
#define MAXBUFSIZE 1024
/* total bytes to copy from a valid pointer argument for ioctl() calls,
syscall.c does not decode ioctl() calls to determine the size of the
arguments that reside in memory, instead, the ioctl() proxy simply copies
NUM_IOCTL_BYTES bytes from the pointer argument to host memory */
#define NUM_IOCTL_BYTES 128
/* target stat() buffer definition, the host stat buffer format is
automagically mapped to/from this format in syscall.c */
struct ss_statbuf
{
shalf_t ss_st_dev;
shalf_t ss_pad;
word_t ss_st_ino;
half_t ss_st_mode;
shalf_t ss_st_nlink;
shalf_t ss_st_uid;
shalf_t ss_st_gid;
shalf_t ss_st_rdev;
shalf_t ss_pad1;
sword_t ss_st_size;
sword_t ss_st_atime;
sword_t ss_st_spare1;
sword_t ss_st_mtime;
sword_t ss_st_spare2;
sword_t ss_st_ctime;
sword_t ss_st_spare3;
sword_t ss_st_blksize;
sword_t ss_st_blocks;
word_t ss_st_gennum;
sword_t ss_st_spare4;
};
struct ss_sgttyb {
byte_t sg_ispeed; /* input speed */
byte_t sg_ospeed; /* output speed */
byte_t sg_erase; /* erase character */
byte_t sg_kill; /* kill character */
shalf_t sg_flags; /* mode flags */
};
struct ss_timeval
{
sword_t ss_tv_sec; /* seconds */
sword_t ss_tv_usec; /* microseconds */
};
/* target getrusage() buffer definition, the host stat buffer format is
automagically mapped to/from this format in syscall.c */
struct ss_rusage
{
struct ss_timeval ss_ru_utime;
struct ss_timeval ss_ru_stime;
sword_t ss_ru_maxrss;
sword_t ss_ru_ixrss;
sword_t ss_ru_idrss;
sword_t ss_ru_isrss;
sword_t ss_ru_minflt;
sword_t ss_ru_majflt;
sword_t ss_ru_nswap;
sword_t ss_ru_inblock;
sword_t ss_ru_oublock;
sword_t ss_ru_msgsnd;
sword_t ss_ru_msgrcv;
sword_t ss_ru_nsignals;
sword_t ss_ru_nvcsw;
sword_t ss_ru_nivcsw;
};
struct ss_timezone
{
sword_t ss_tz_minuteswest; /* minutes west of Greenwich */
sword_t ss_tz_dsttime; /* type of dst correction */
};
struct ss_rlimit
{
int ss_rlim_cur; /* current (soft) limit */
int ss_rlim_max; /* maximum value for rlim_cur */
};
/* open(2) flags for SimpleScalar target, syscall.c automagically maps
between these codes to/from host open(2) flags */
#define SS_O_RDONLY 0
#define SS_O_WRONLY 1
#define SS_O_RDWR 2
#define SS_O_APPEND 0x0008
#define SS_O_CREAT 0x0200
#define SS_O_TRUNC 0x0400
#define SS_O_EXCL 0x0800
#define SS_O_NONBLOCK 0x4000
#define SS_O_NOCTTY 0x8000
#define SS_O_SYNC 0x2000
/* open(2) flags translation table for SimpleScalar target */
struct {
int ss_flag;
int local_flag;
} ss_flag_table[] = {
/* target flag */ /* host flag */
#ifdef _MSC_VER
{ SS_O_RDONLY, _O_RDONLY },
{ SS_O_WRONLY, _O_WRONLY },
{ SS_O_RDWR, _O_RDWR },
{ SS_O_APPEND, _O_APPEND },
{ SS_O_CREAT, _O_CREAT },
{ SS_O_TRUNC, _O_TRUNC },
{ SS_O_EXCL, _O_EXCL },
#ifdef _O_NONBLOCK
{ SS_O_NONBLOCK, _O_NONBLOCK },
#endif
#ifdef _O_NOCTTY
{ SS_O_NOCTTY, _O_NOCTTY },
#endif
#ifdef _O_SYNC
{ SS_O_SYNC, _O_SYNC },
#endif
#else /* !_MSC_VER */
{ SS_O_RDONLY, O_RDONLY },
{ SS_O_WRONLY, O_WRONLY },
{ SS_O_RDWR, O_RDWR },
{ SS_O_APPEND, O_APPEND },
{ SS_O_CREAT, O_CREAT },
{ SS_O_TRUNC, O_TRUNC },
{ SS_O_EXCL, O_EXCL },
{ SS_O_NONBLOCK, O_NONBLOCK },
{ SS_O_NOCTTY, O_NOCTTY },
#ifdef O_SYNC
{ SS_O_SYNC, O_SYNC },
#endif
#endif /* _MSC_VER */
};
#define SS_NFLAGS (sizeof(ss_flag_table)/sizeof(ss_flag_table[0]))
#endif /* !MD_CROSS_ENDIAN */
/* syscall proxy handler, architect registers and memory are assumed to be
precise when this function is called, register and memory are updated with
the results of the sustem call */
void
sys_syscall(struct regs_t *regs, /* registers to access */
mem_access_fn mem_fn, /* generic memory accessor */
struct mem_t *mem, /* memory space to access */
md_inst_t inst, /* system call inst */
int traceable) /* traceable system call? */
{
word_t syscode = regs->regs_R[2];
/* first, check if an EIO trace is being consumed... */
if (traceable && sim_eio_fd != NULL)
{
eio_read_trace(sim_eio_fd, sim_num_insn, regs, mem_fn, mem, inst);
/* fini... */
return;
}
#ifdef MD_CROSS_ENDIAN
else if (syscode == SS_SYS_exit)
{
/* exit jumps to the target set in main() */
longjmp(sim_exit_buf, /* exitcode + fudge */regs->regs_R[4]+1);
}
else
fatal("cannot execute PISA system call on cross-endian host");
#else /* !MD_CROSS_ENDIAN */
/* no, OK execute the live system call... */
switch (syscode)
{
case SS_SYS_exit:
/* exit jumps to the target set in main() */
longjmp(sim_exit_buf, /* exitcode + fudge */regs->regs_R[4]+1);
break;
#if 0
case SS_SYS_fork:
/* FIXME: this is broken... */
regs->regs_R[2] = fork();
if (regs->regs_R[2] != -1)
{
regs->regs_R[7] = 0;
/* parent process */
if (regs->regs_R[2] != 0)
regs->regs_R[3] = 0;
}
else
fatal("SYS_fork failed");
break;
#endif
#if 0
case SS_SYS_vfork:
/* FIXME: this is broken... */
int r31_parent = regs->regs_R[31];
/* pid */regs->regs_R[2] = vfork();
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
fatal("vfork() in SYS_vfork failed");
if (regs->regs_R[2] != 0)
{
regs->regs_R[3] = 0;
regs->regs_R[7] = 0;
regs->regs_R[31] = r31_parent;
}
break;
#endif
case SS_SYS_read:
{
char *buf;
/* allocate same-sized input buffer in host memory */
if (!(buf = (char *)calloc(/*nbytes*/regs->regs_R[6], sizeof(char))))
fatal("out of memory in SYS_read");
/* read data from file */
/*nread*/regs->regs_R[2] =
read(/*fd*/regs->regs_R[4], buf, /*nbytes*/regs->regs_R[6]);
/* check for error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* copy results back into host memory */
mem_bcopy(mem_fn, mem,
Write, /*buf*/regs->regs_R[5],
buf, /*nread*/regs->regs_R[2]);
/* done with input buffer */
free(buf);
}
break;
case SS_SYS_write:
{
char *buf;
/* allocate same-sized output buffer in host memory */
if (!(buf = (char *)calloc(/*nbytes*/regs->regs_R[6], sizeof(char))))
fatal("out of memory in SYS_write");
/* copy inputs into host memory */
mem_bcopy(mem_fn, mem,
Read, /*buf*/regs->regs_R[5],
buf, /*nbytes*/regs->regs_R[6]);
/* write data to file */
if (sim_progfd && MD_OUTPUT_SYSCALL(regs))
{
/* redirect program output to file */
/*nwritten*/regs->regs_R[2] =
fwrite(buf, 1, /*nbytes*/regs->regs_R[6], sim_progfd);
}
else
{
/* perform program output request */
/*nwritten*/regs->regs_R[2] =
write(/*fd*/regs->regs_R[4],
buf, /*nbytes*/regs->regs_R[6]);
}
/* check for an error condition */
if (regs->regs_R[2] == regs->regs_R[6])
/*result*/regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* done with output buffer */
free(buf);
}
break;
case SS_SYS_open:
{
char buf[MAXBUFSIZE];
unsigned int i;
int ss_flags = regs->regs_R[5], local_flags = 0;
/* translate open(2) flags */
for (i=0; i<SS_NFLAGS; i++)
{
if (ss_flags & ss_flag_table[i].ss_flag)
{
ss_flags &= ~ss_flag_table[i].ss_flag;
local_flags |= ss_flag_table[i].local_flag;
}
}
/* any target flags left? */
if (ss_flags != 0)
fatal("syscall: open: cannot decode flags: 0x%08x", ss_flags);
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf);
/* open the file */
/*fd*/regs->regs_R[2] =
open(buf, local_flags, /*mode*/regs->regs_R[6]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_close:
/* don't close stdin, stdout, or stderr as this messes up sim logs */
if (/*fd*/regs->regs_R[4] == 0
|| /*fd*/regs->regs_R[4] == 1
|| /*fd*/regs->regs_R[4] == 2)
{
regs->regs_R[7] = 0;
break;
}
/* close the file */
regs->regs_R[2] = close(/*fd*/regs->regs_R[4]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
break;
case SS_SYS_creat:
{
char buf[MAXBUFSIZE];
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf);
/* create the file */
/*fd*/regs->regs_R[2] = creat(buf, /*mode*/regs->regs_R[5]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_unlink:
{
char buf[MAXBUFSIZE];
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf);
/* delete the file */
/*result*/regs->regs_R[2] = unlink(buf);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_chdir:
{
char buf[MAXBUFSIZE];
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf);
/* change the working directory */
/*result*/regs->regs_R[2] = chdir(buf);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_chmod:
{
char buf[MAXBUFSIZE];
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf);
/* chmod the file */
/*result*/regs->regs_R[2] = chmod(buf, /*mode*/regs->regs_R[5]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_chown:
#ifdef _MSC_VER
warn("syscall chown() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#else /* !_MSC_VER */
{
char buf[MAXBUFSIZE];
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf);
/* chown the file */
/*result*/regs->regs_R[2] = chown(buf, /*owner*/regs->regs_R[5],
/*group*/regs->regs_R[6]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
#endif /* _MSC_VER */
break;
case SS_SYS_brk:
{
md_addr_t addr;
/* round the new heap pointer to the its page boundary */
addr = ROUND_UP(/*base*/regs->regs_R[4], MD_PAGE_SIZE);
/* check whether heap area has merged with stack area */
if (addr >= ld_brk_point && addr < (md_addr_t)regs->regs_R[29])
{
regs->regs_R[2] = 0;
regs->regs_R[7] = 0;
ld_brk_point = addr;
}
else
{
/* out of address space, indicate error */
regs->regs_R[2] = ENOMEM;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_lseek:
/* seek into file */
regs->regs_R[2] =
lseek(/*fd*/regs->regs_R[4],
/*off*/regs->regs_R[5], /*dir*/regs->regs_R[6]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
break;
case SS_SYS_getpid:
/* get the simulator process id */
/*result*/regs->regs_R[2] = getpid();
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
break;
case SS_SYS_getuid:
#ifdef _MSC_VER
warn("syscall getuid() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#else /* !_MSC_VER */
/* get current user id */
/*first result*/regs->regs_R[2] = getuid();
/* get effective user id */
/*second result*/regs->regs_R[3] = geteuid();
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
#endif /* _MSC_VER */
break;
case SS_SYS_access:
{
char buf[MAXBUFSIZE];
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fName*/regs->regs_R[4], buf);
/* check access on the file */
/*result*/regs->regs_R[2] = access(buf, /*mode*/regs->regs_R[5]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_stat:
case SS_SYS_lstat:
{
char buf[MAXBUFSIZE];
struct ss_statbuf ss_sbuf;
#ifdef _MSC_VER
struct _stat sbuf;
#else /* !_MSC_VER */
struct stat sbuf;
#endif /* _MSC_VER */
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fName*/regs->regs_R[4], buf);
/* stat() the file */
if (syscode == SS_SYS_stat)
/*result*/regs->regs_R[2] = stat(buf, &sbuf);
else /* syscode == SS_SYS_lstat */
{
#ifdef _MSC_VER
warn("syscall lstat() not yet implemented for MSC...");
regs->regs_R[7] = 0;
break;
#else /* !_MSC_VER */
/*result*/regs->regs_R[2] = lstat(buf, &sbuf);
#endif /* _MSC_VER */
}
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* translate from host stat structure to target format */
ss_sbuf.ss_st_dev = MD_SWAPH(sbuf.st_dev);
ss_sbuf.ss_pad = 0;
ss_sbuf.ss_st_ino = MD_SWAPW(sbuf.st_ino);
ss_sbuf.ss_st_mode = MD_SWAPH(sbuf.st_mode);
ss_sbuf.ss_st_nlink = MD_SWAPH(sbuf.st_nlink);
ss_sbuf.ss_st_uid = MD_SWAPH(sbuf.st_uid);
ss_sbuf.ss_st_gid = MD_SWAPH(sbuf.st_gid);
ss_sbuf.ss_st_rdev = MD_SWAPH(sbuf.st_rdev);
ss_sbuf.ss_pad1 = 0;
ss_sbuf.ss_st_size = MD_SWAPW(sbuf.st_size);
ss_sbuf.ss_st_atime = MD_SWAPW(sbuf.st_atime);
ss_sbuf.ss_st_spare1 = 0;
ss_sbuf.ss_st_mtime = MD_SWAPW(sbuf.st_mtime);
ss_sbuf.ss_st_spare2 = 0;
ss_sbuf.ss_st_ctime = MD_SWAPW(sbuf.st_ctime);
ss_sbuf.ss_st_spare3 = 0;
#ifndef _MSC_VER
ss_sbuf.ss_st_blksize = MD_SWAPW(sbuf.st_blksize);
ss_sbuf.ss_st_blocks = MD_SWAPW(sbuf.st_blocks);
#endif /* !_MSC_VER */
ss_sbuf.ss_st_gennum = 0;
ss_sbuf.ss_st_spare4 = 0;
/* copy stat() results to simulator memory */
mem_bcopy(mem_fn, mem, Write, /*sbuf*/regs->regs_R[5],
&ss_sbuf, sizeof(struct ss_statbuf));
}
break;
case SS_SYS_dup:
/* dup() the file descriptor */
/*fd*/regs->regs_R[2] = dup(/*fd*/regs->regs_R[4]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
break;
#ifndef _MSC_VER
case SS_SYS_pipe:
{
int fd[2];
/* copy pipe descriptors to host memory */;
mem_bcopy(mem_fn, mem, Read, /*fd's*/regs->regs_R[4], fd, sizeof(fd));
/* create a pipe */
/*result*/regs->regs_R[7] = pipe(fd);
/* copy descriptor results to result registers */
/*pipe1*/regs->regs_R[2] = fd[0];
/*pipe 2*/regs->regs_R[3] = fd[1];
/* check for an error condition */
if (regs->regs_R[7] == -1)
{
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
#endif
case SS_SYS_getgid:
#ifdef _MSC_VER
warn("syscall getgid() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#else /* !_MSC_VER */
/* get current group id */
/*first result*/regs->regs_R[2] = getgid();
/* get current effective group id */
/*second result*/regs->regs_R[3] = getegid();
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
#endif /* _MSC_VER */
break;
case SS_SYS_ioctl:
{
char buf[NUM_IOCTL_BYTES];
int local_req = 0;
/* convert target ioctl() request to host ioctl() request values */
switch (/*req*/regs->regs_R[5]) {
#ifdef TIOCGETP
case SS_IOCTL_TIOCGETP:
local_req = TIOCGETP;
break;
#endif
#ifdef TIOCSETP
case SS_IOCTL_TIOCSETP:
local_req = TIOCSETP;
break;
#endif
#ifdef TIOCGETP
case SS_IOCTL_TCGETP:
local_req = TIOCGETP;
break;
#endif
#ifdef TCGETA
case SS_IOCTL_TCGETA:
local_req = TCGETA;
break;
#endif
#ifdef TIOCGLTC
case SS_IOCTL_TIOCGLTC:
local_req = TIOCGLTC;
break;
#endif
#ifdef TIOCSLTC
case SS_IOCTL_TIOCSLTC:
local_req = TIOCSLTC;
break;
#endif
#ifdef TIOCGWINSZ
case SS_IOCTL_TIOCGWINSZ:
local_req = TIOCGWINSZ;
break;
#endif
#ifdef TCSETAW
case SS_IOCTL_TCSETAW:
local_req = TCSETAW;
break;
#endif
#ifdef TIOCGETC
case SS_IOCTL_TIOCGETC:
local_req = TIOCGETC;
break;
#endif
#ifdef TIOCSETC
case SS_IOCTL_TIOCSETC:
local_req = TIOCSETC;
break;
#endif
#ifdef TIOCLBIC
case SS_IOCTL_TIOCLBIC:
local_req = TIOCLBIC;
break;
#endif
#ifdef TIOCLBIS
case SS_IOCTL_TIOCLBIS:
local_req = TIOCLBIS;
break;
#endif
#ifdef TIOCLGET
case SS_IOCTL_TIOCLGET:
local_req = TIOCLGET;
break;
#endif
#ifdef TIOCLSET
case SS_IOCTL_TIOCLSET:
local_req = TIOCLSET;
break;
#endif
}
#if !defined(TIOCGETP) && (defined(linux) || defined(__CYGWIN32__))
if (!local_req && /*req*/regs->regs_R[5] == SS_IOCTL_TIOCGETP)
{
struct termios lbuf;
struct ss_sgttyb buf;
/* result */regs->regs_R[2] =
tcgetattr(/* fd */(int)regs->regs_R[4], &lbuf);
/* translate results */
buf.sg_ispeed = lbuf.c_ispeed;
buf.sg_ospeed = lbuf.c_ospeed;
buf.sg_erase = lbuf.c_cc[VERASE];
buf.sg_kill = lbuf.c_cc[VKILL];
buf.sg_flags = 0; /* FIXME: this is wrong... */
mem_bcopy(mem_fn, mem, Write,
/* buf */regs->regs_R[6], &buf,
sizeof(struct ss_sgttyb));
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else /* probably not a typewriter, return details */
{
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
else
#endif
if (!local_req)
{
/* FIXME: could not translate the ioctl() request, just warn user
and ignore the request */
warn("syscall: ioctl: ioctl code not supported d=%d, req=%d",
regs->regs_R[4], regs->regs_R[5]);
regs->regs_R[2] = 0;
regs->regs_R[7] = 0;
}
else
{
#ifdef _MSC_VER
warn("syscall getgid() not yet implemented for MSC...");
regs->regs_R[7] = 0;
break;
#else /* !_MSC_VER */
#if 0 /* FIXME: needed? */
#ifdef TIOCGETP
if (local_req == TIOCGETP && sim_progfd)
{
/* program I/O has been redirected to file, make
termios() calls fail... */
/* got an error, return details */
regs->regs_R[2] = ENOTTY;
regs->regs_R[7] = 1;
break;
}
#endif
#endif
/* ioctl() code was successfully translated to a host code */
/* if arg ptr exists, copy NUM_IOCTL_BYTES bytes to host mem */
if (/*argp*/regs->regs_R[6] != 0)
mem_bcopy(mem_fn, mem,
Read, /*argp*/regs->regs_R[6], buf, NUM_IOCTL_BYTES);
/* perform the ioctl() call */
/*result*/regs->regs_R[2] =
ioctl(/*fd*/regs->regs_R[4], local_req, buf);
/* if arg ptr exists, copy NUM_IOCTL_BYTES bytes from host mem */
if (/*argp*/regs->regs_R[6] != 0)
mem_bcopy(mem_fn, mem, Write, regs->regs_R[6],
buf, NUM_IOCTL_BYTES);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
#endif /* _MSC_VER */
}
}
break;
case SS_SYS_fstat:
{
struct ss_statbuf ss_sbuf;
#ifdef _MSC_VER
struct _stat sbuf;
#else /* !_MSC_VER */
struct stat sbuf;
#endif /* _MSC_VER */
/* fstat() the file */
/*result*/regs->regs_R[2] = fstat(/*fd*/regs->regs_R[4], &sbuf);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* translate the stat structure to host format */
ss_sbuf.ss_st_dev = MD_SWAPH(sbuf.st_dev);
ss_sbuf.ss_pad = 0;
ss_sbuf.ss_st_ino = MD_SWAPW(sbuf.st_ino);
ss_sbuf.ss_st_mode = MD_SWAPH(sbuf.st_mode);
ss_sbuf.ss_st_nlink = MD_SWAPH(sbuf.st_nlink);
ss_sbuf.ss_st_uid = MD_SWAPH(sbuf.st_uid);
ss_sbuf.ss_st_gid = MD_SWAPH(sbuf.st_gid);
ss_sbuf.ss_st_rdev = MD_SWAPH(sbuf.st_rdev);
ss_sbuf.ss_pad1 = 0;
ss_sbuf.ss_st_size = MD_SWAPW(sbuf.st_size);
ss_sbuf.ss_st_atime = MD_SWAPW(sbuf.st_atime);
ss_sbuf.ss_st_spare1 = 0;
ss_sbuf.ss_st_mtime = MD_SWAPW(sbuf.st_mtime);
ss_sbuf.ss_st_spare2 = 0;
ss_sbuf.ss_st_ctime = MD_SWAPW(sbuf.st_ctime);
ss_sbuf.ss_st_spare3 = 0;
#ifndef _MSC_VER
ss_sbuf.ss_st_blksize = MD_SWAPW(sbuf.st_blksize);
ss_sbuf.ss_st_blocks = MD_SWAPW(sbuf.st_blocks);
#endif /* !_MSC_VER */
ss_sbuf.ss_st_gennum = 0;
ss_sbuf.ss_st_spare4 = 0;
/* copy fstat() results to simulator memory */
mem_bcopy(mem_fn, mem, Write, /*sbuf*/regs->regs_R[5],
&ss_sbuf, sizeof(struct ss_statbuf));
}
break;
case SS_SYS_getpagesize:
/* get target pagesize */
regs->regs_R[2] = /* was: getpagesize() */MD_PAGE_SIZE;
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
break;
case SS_SYS_setitimer:
/* FIXME: the sigvec system call is ignored */
regs->regs_R[2] = regs->regs_R[7] = 0;
warn("syscall: setitimer ignored");
break;
case SS_SYS_getdtablesize:
#if defined(_AIX)
/* get descriptor table size */
regs->regs_R[2] = getdtablesize();
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
#elif defined(__CYGWIN32__) || defined(ultrix) || defined(_MSC_VER)
{
/* no comparable system call found, try some reasonable defaults */
warn("syscall: called getdtablesize()\n");
regs->regs_R[2] = 16;
regs->regs_R[7] = 0;
}
#else
{
struct rlimit rl;
/* get descriptor table size in rlimit structure */
if (getrlimit(RLIMIT_NOFILE, &rl) != -1)
{
regs->regs_R[2] = rl.rlim_cur;
regs->regs_R[7] = 0;
}
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
#endif
break;
case SS_SYS_dup2:
/* dup2() the file descriptor */
regs->regs_R[2] =
dup2(/* fd1 */regs->regs_R[4], /* fd2 */regs->regs_R[5]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
break;
case SS_SYS_fcntl:
#ifdef _MSC_VER
warn("syscall fcntl() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#else /* !_MSC_VER */
/* get fcntl() information on the file */
regs->regs_R[2] =
fcntl(/*fd*/regs->regs_R[4], /*cmd*/regs->regs_R[5],
/*arg*/regs->regs_R[6]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
#endif /* _MSC_VER */
break;
case SS_SYS_select:
#ifdef _MSC_VER
warn("syscall select() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#else /* !_MSC_VER */
{
fd_set readfd, writefd, exceptfd;
fd_set *readfdp, *writefdp, *exceptfdp;
struct timeval timeout, *timeoutp;
word_t param5;
/* FIXME: swap words? */
/* read the 5th parameter (timeout) from the stack */
mem_bcopy(mem_fn, mem,
Read, regs->regs_R[29]+16, &param5, sizeof(word_t));
/* copy read file descriptor set into host memory */
if (/*readfd*/regs->regs_R[5] != 0)
{
mem_bcopy(mem_fn, mem, Read, /*readfd*/regs->regs_R[5],
&readfd, sizeof(fd_set));
readfdp = &readfd;
}
else
readfdp = NULL;
/* copy write file descriptor set into host memory */
if (/*writefd*/regs->regs_R[6] != 0)
{
mem_bcopy(mem_fn, mem, Read, /*writefd*/regs->regs_R[6],
&writefd, sizeof(fd_set));
writefdp = &writefd;
}
else
writefdp = NULL;
/* copy exception file descriptor set into host memory */
if (/*exceptfd*/regs->regs_R[7] != 0)
{
mem_bcopy(mem_fn, mem, Read, /*exceptfd*/regs->regs_R[7],
&exceptfd, sizeof(fd_set));
exceptfdp = &exceptfd;
}
else
exceptfdp = NULL;
/* copy timeout value into host memory */
if (/*timeout*/param5 != 0)
{
mem_bcopy(mem_fn, mem, Read, /*timeout*/param5,
&timeout, sizeof(struct timeval));
timeoutp = &timeout;
}
else
timeoutp = NULL;
#if defined(hpux) || defined(__hpux)
/* select() on the specified file descriptors */
/*result*/regs->regs_R[2] =
select(/*nfd*/regs->regs_R[4],
(int *)readfdp, (int *)writefdp, (int *)exceptfdp, timeoutp);
#else
/* select() on the specified file descriptors */
/*result*/regs->regs_R[2] =
select(/*nfd*/regs->regs_R[4],
readfdp, writefdp, exceptfdp, timeoutp);
#endif
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, return details */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* copy read file descriptor set to target memory */
if (/*readfd*/regs->regs_R[5] != 0)
mem_bcopy(mem_fn, mem, Write, /*readfd*/regs->regs_R[5],
&readfd, sizeof(fd_set));
/* copy write file descriptor set to target memory */
if (/*writefd*/regs->regs_R[6] != 0)
mem_bcopy(mem_fn, mem, Write, /*writefd*/regs->regs_R[6],
&writefd, sizeof(fd_set));
/* copy exception file descriptor set to target memory */
if (/*exceptfd*/regs->regs_R[7] != 0)
mem_bcopy(mem_fn, mem, Write, /*exceptfd*/regs->regs_R[7],
&exceptfd, sizeof(fd_set));
/* copy timeout value result to target memory */
if (/* timeout */param5 != 0)
mem_bcopy(mem_fn, mem, Write, /*timeout*/param5,
&timeout, sizeof(struct timeval));
}
#endif
break;
case SS_SYS_sigvec:
/* FIXME: the sigvec system call is ignored */
regs->regs_R[2] = regs->regs_R[7] = 0;
warn("syscall: sigvec ignored");
break;
case SS_SYS_sigblock:
/* FIXME: the sigblock system call is ignored */
regs->regs_R[2] = regs->regs_R[7] = 0;
warn("syscall: sigblock ignored");
break;
case SS_SYS_sigsetmask:
/* FIXME: the sigsetmask system call is ignored */
regs->regs_R[2] = regs->regs_R[7] = 0;
warn("syscall: sigsetmask ignored");
break;
#if 0
case SS_SYS_sigstack:
/* FIXME: this is broken... */
/* do not make the system call; instead, modify (the stack
portion of) the simulator's main memory, ignore the 1st
argument (regs->regs_R[4]), as it relates to signal handling */
if (regs->regs_R[5] != 0)
{
(*maf)(Read, regs->regs_R[29]+28, (unsigned char *)&temp, 4);
(*maf)(Write, regs->regs_R[5], (unsigned char *)&temp, 4);
}
regs->regs_R[2] = regs->regs_R[7] = 0;
break;
#endif
case SS_SYS_gettimeofday:
#ifdef _MSC_VER
warn("syscall gettimeofday() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#else /* _MSC_VER */
{
struct ss_timeval ss_tv;
struct timeval tv, *tvp;
struct ss_timezone ss_tz;
struct timezone tz, *tzp;
if (/*timeval*/regs->regs_R[4] != 0)
{
/* copy timeval into host memory */
mem_bcopy(mem_fn, mem, Read, /*timeval*/regs->regs_R[4],
&ss_tv, sizeof(struct ss_timeval));
/* convert target timeval structure to host format */
tv.tv_sec = MD_SWAPW(ss_tv.ss_tv_sec);
tv.tv_usec = MD_SWAPW(ss_tv.ss_tv_usec);
tvp = &tv;
}
else
tvp = NULL;
if (/*timezone*/regs->regs_R[5] != 0)
{
/* copy timezone into host memory */
mem_bcopy(mem_fn, mem, Read, /*timezone*/regs->regs_R[5],
&ss_tz, sizeof(struct ss_timezone));
/* convert target timezone structure to host format */
tz.tz_minuteswest = MD_SWAPW(ss_tz.ss_tz_minuteswest);
tz.tz_dsttime = MD_SWAPW(ss_tz.ss_tz_dsttime);
tzp = &tz;
}
else
tzp = NULL;
/* get time of day */
/*result*/regs->regs_R[2] = gettimeofday(tvp, tzp);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, indicate result */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
if (/*timeval*/regs->regs_R[4] != 0)
{
/* convert host timeval structure to target format */
ss_tv.ss_tv_sec = MD_SWAPW(tv.tv_sec);
ss_tv.ss_tv_usec = MD_SWAPW(tv.tv_usec);
/* copy timeval to target memory */
mem_bcopy(mem_fn, mem, Write, /*timeval*/regs->regs_R[4],
&ss_tv, sizeof(struct ss_timeval));
}
if (/*timezone*/regs->regs_R[5] != 0)
{
/* convert host timezone structure to target format */
ss_tz.ss_tz_minuteswest = MD_SWAPW(tz.tz_minuteswest);
ss_tz.ss_tz_dsttime = MD_SWAPW(tz.tz_dsttime);
/* copy timezone to target memory */
mem_bcopy(mem_fn, mem, Write, /*timezone*/regs->regs_R[5],
&ss_tz, sizeof(struct ss_timezone));
}
}
#endif /* !_MSC_VER */
break;
case SS_SYS_getrusage:
#if defined(__svr4__) || defined(__USLC__) || defined(hpux) || defined(__hpux) || defined(_AIX)
{
struct tms tms_buf;
struct ss_rusage rusage;
/* get user and system times */
if (times(&tms_buf) != -1)
{
/* no error */
regs->regs_R[2] = 0;
regs->regs_R[7] = 0;
}
else
{
/* got an error, indicate result */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* initialize target rusage result structure */
#if defined(__svr4__)
memset(&rusage, '\0', sizeof(struct ss_rusage));
#else /* !defined(__svr4__) */
bzero(&rusage, sizeof(struct ss_rusage));
#endif
/* convert from host rusage structure to target format */
rusage.ss_ru_utime.ss_tv_sec = tms_buf.tms_utime/CLK_TCK;
rusage.ss_ru_utime.ss_tv_sec = MD_SWAPW(rusage.ss_ru_utime.ss_tv_sec);
rusage.ss_ru_utime.ss_tv_usec = 0;
rusage.ss_ru_stime.ss_tv_sec = tms_buf.tms_stime/CLK_TCK;
rusage.ss_ru_stime.ss_tv_sec = MD_SWAPW(rusage.ss_ru_stime.ss_tv_sec);
rusage.ss_ru_stime.ss_tv_usec = 0;
/* copy rusage results into target memory */
mem_bcopy(mem_fn, mem, Write, /*rusage*/regs->regs_R[5],
&rusage, sizeof(struct ss_rusage));
}
#elif defined(__unix__) || defined(unix)
{
struct rusage local_rusage;
struct ss_rusage rusage;
/* get rusage information */
/*result*/regs->regs_R[2] =
getrusage(/*who*/regs->regs_R[4], &local_rusage);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, indicate result */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* convert from host rusage structure to target format */
rusage.ss_ru_utime.ss_tv_sec = local_rusage.ru_utime.tv_sec;
rusage.ss_ru_utime.ss_tv_usec = local_rusage.ru_utime.tv_usec;
rusage.ss_ru_utime.ss_tv_sec = MD_SWAPW(local_rusage.ru_utime.tv_sec);
rusage.ss_ru_utime.ss_tv_usec =
MD_SWAPW(local_rusage.ru_utime.tv_usec);
rusage.ss_ru_stime.ss_tv_sec = local_rusage.ru_stime.tv_sec;
rusage.ss_ru_stime.ss_tv_usec = local_rusage.ru_stime.tv_usec;
rusage.ss_ru_stime.ss_tv_sec =
MD_SWAPW(local_rusage.ru_stime.tv_sec);
rusage.ss_ru_stime.ss_tv_usec =
MD_SWAPW(local_rusage.ru_stime.tv_usec);
rusage.ss_ru_maxrss = MD_SWAPW(local_rusage.ru_maxrss);
rusage.ss_ru_ixrss = MD_SWAPW(local_rusage.ru_ixrss);
rusage.ss_ru_idrss = MD_SWAPW(local_rusage.ru_idrss);
rusage.ss_ru_isrss = MD_SWAPW(local_rusage.ru_isrss);
rusage.ss_ru_minflt = MD_SWAPW(local_rusage.ru_minflt);
rusage.ss_ru_majflt = MD_SWAPW(local_rusage.ru_majflt);
rusage.ss_ru_nswap = MD_SWAPW(local_rusage.ru_nswap);
rusage.ss_ru_inblock = MD_SWAPW(local_rusage.ru_inblock);
rusage.ss_ru_oublock = MD_SWAPW(local_rusage.ru_oublock);
rusage.ss_ru_msgsnd = MD_SWAPW(local_rusage.ru_msgsnd);
rusage.ss_ru_msgrcv = MD_SWAPW(local_rusage.ru_msgrcv);
rusage.ss_ru_nsignals = MD_SWAPW(local_rusage.ru_nsignals);
rusage.ss_ru_nvcsw = MD_SWAPW(local_rusage.ru_nvcsw);
rusage.ss_ru_nivcsw = MD_SWAPW(local_rusage.ru_nivcsw);
/* copy rusage results into target memory */
mem_bcopy(mem_fn, mem, Write, /*rusage*/regs->regs_R[5],
&rusage, sizeof(struct ss_rusage));
}
#elif defined(__CYGWIN32__) || defined(_MSC_VER)
warn("syscall: called getrusage()\n");
regs->regs_R[7] = 0;
#else
#error No getrusage() implementation!
#endif
break;
case SS_SYS_writev:
#ifdef _MSC_VER
warn("syscall writev() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#else /* !_MSC_VER */
{
int i;
char *buf;
struct iovec *iov;
/* allocate host side I/O vectors */
iov =
(struct iovec *)malloc(/*iovcnt*/regs->regs_R[6]
* sizeof(struct iovec));
if (!iov)
fatal("out of virtual memory in SYS_writev");
/* copy target side pointer data into host side vector */
mem_bcopy(mem_fn, mem, Read, /*iov*/regs->regs_R[5],
iov, /*iovcnt*/regs->regs_R[6] * sizeof(struct iovec));
/* copy target side I/O vector buffers to host memory */
for (i=0; i < /*iovcnt*/regs->regs_R[6]; i++)
{
iov[i].iov_base = (char *)MD_SWAPW((unsigned long)iov[i].iov_base);
iov[i].iov_len = MD_SWAPW(iov[i].iov_len);
if (iov[i].iov_base != NULL)
{
buf = (char *)calloc(iov[i].iov_len, sizeof(char));
if (!buf)
fatal("out of virtual memory in SYS_writev");
mem_bcopy(mem_fn, mem, Read, (md_addr_t)iov[i].iov_base,
buf, iov[i].iov_len);
iov[i].iov_base = buf;
}
}
/* perform the vector'ed write */
/*result*/regs->regs_R[2] =
writev(/*fd*/regs->regs_R[4], iov, /*iovcnt*/regs->regs_R[6]);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, indicate results */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* free all the allocated memory */
for (i=0; i < /*iovcnt*/regs->regs_R[6]; i++)
{
if (iov[i].iov_base)
{
free(iov[i].iov_base);
iov[i].iov_base = NULL;
}
}
free(iov);
}
#endif /* !_MSC_VER */
break;
case SS_SYS_utimes:
{
char buf[MAXBUFSIZE];
/* copy filename to host memory */
mem_strcpy(mem_fn, mem, Read, /*fname*/regs->regs_R[4], buf);
if (/*timeval*/regs->regs_R[5] == 0)
{
#if defined(hpux) || defined(__hpux) || defined(linux)
/* no utimes() in hpux, use utime() instead */
/*result*/regs->regs_R[2] = utime(buf, NULL);
#elif defined(_MSC_VER)
/* no utimes() in MSC, use utime() instead */
/*result*/regs->regs_R[2] = utime(buf, NULL);
#elif defined(__svr4__) || defined(__USLC__) || defined(unix) || defined(_AIX) || defined(__alpha)
/*result*/regs->regs_R[2] = utimes(buf, NULL);
#elif defined(__CYGWIN32__)
warn("syscall: called utimes()\n");
#else
#error No utimes() implementation!
#endif
}
else
{
struct ss_timeval ss_tval[2];
#ifndef _MSC_VER
struct timeval tval[2];
#endif /* !_MSC_VER */
/* copy timeval structure to host memory */
mem_bcopy(mem_fn, mem, Read, /*timeout*/regs->regs_R[5],
ss_tval, 2*sizeof(struct ss_timeval));
#ifndef _MSC_VER
/* convert timeval structure to host format */
tval[0].tv_sec = MD_SWAPW(ss_tval[0].ss_tv_sec);
tval[0].tv_usec = MD_SWAPW(ss_tval[0].ss_tv_usec);
tval[1].tv_sec = MD_SWAPW(ss_tval[1].ss_tv_sec);
tval[1].tv_usec = MD_SWAPW(ss_tval[1].ss_tv_usec);
#endif /* !_MSC_VER */
#if defined(hpux) || defined(__hpux) || defined(__svr4__)
/* no utimes() in hpux, use utime() instead */
{
struct utimbuf ubuf;
ubuf.actime = tval[0].tv_sec;
ubuf.modtime = tval[1].tv_sec;
/* result */regs->regs_R[2] = utime(buf, &ubuf);
}
#elif defined(_MSC_VER)
/* no utimes() in MSC, use utime() instead */
{
struct _utimbuf ubuf;
ubuf.actime = ss_tval[0].ss_tv_sec;
ubuf.modtime = ss_tval[1].ss_tv_sec;
/* result */regs->regs_R[2] = utime(buf, &ubuf);
}
#elif defined(__USLC__) || defined(unix) || defined(_AIX) || defined(__alpha)
/* result */regs->regs_R[2] = utimes(buf, tval);
#elif defined(__CYGWIN32__)
warn("syscall: called utimes()\n");
#else
#error No utimes() implementation!
#endif
}
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, indicate results */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
}
break;
case SS_SYS_getrlimit:
case SS_SYS_setrlimit:
#ifdef _MSC_VER
warn("syscall get/setrlimit() not yet implemented for MSC...");
regs->regs_R[7] = 0;
#elif defined(__CYGWIN32__)
warn("syscall: called get/setrlimit()\n");
regs->regs_R[7] = 0;
#else
{
/* FIXME: check this..., was: struct rlimit ss_rl; */
struct ss_rlimit ss_rl;
struct rlimit rl;
/* copy rlimit structure to host memory */
mem_bcopy(mem_fn, mem, Read, /*rlimit*/regs->regs_R[5],
&ss_rl, sizeof(struct ss_rlimit));
/* convert rlimit structure to host format */
rl.rlim_cur = MD_SWAPW(ss_rl.ss_rlim_cur);
rl.rlim_max = MD_SWAPW(ss_rl.ss_rlim_max);
/* get rlimit information */
if (syscode == SS_SYS_getrlimit)
/*result*/regs->regs_R[2] = getrlimit(regs->regs_R[4], &rl);
else /* syscode == SS_SYS_setrlimit */
/*result*/regs->regs_R[2] = setrlimit(regs->regs_R[4], &rl);
/* check for an error condition */
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
/* got an error, indicate results */
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* convert rlimit structure to target format */
ss_rl.ss_rlim_cur = MD_SWAPW(rl.rlim_cur);
ss_rl.ss_rlim_max = MD_SWAPW(rl.rlim_max);
/* copy rlimit structure to target memory */
mem_bcopy(mem_fn, mem, Write, /*rlimit*/regs->regs_R[5],
&ss_rl, sizeof(struct ss_rlimit));
}
#endif
break;
#if 0
case SS_SYS_getdirentries:
/* FIXME: this is currently broken due to incompatabilities in
disk directory formats */
{
unsigned int i;
char *buf;
int base;
buf = (char *)calloc(/* nbytes */regs->regs_R[6] + 1, sizeof(char));
if (!buf)
fatal("out of memory in SYS_getdirentries");
/* copy in */
for (i=0; i</* nbytes */regs->regs_R[6]; i++)
(*maf)(Read, /* buf */regs->regs_R[5]+i,
(unsigned char *)&buf[i], 1);
(*maf)(Read, /* basep */regs->regs_R[7], (unsigned char *)&base, 4);
/*cc*/regs->regs_R[2] =
getdirentries(/*fd*/regs->regs_R[4], buf,
/*nbytes*/regs->regs_R[6], &base);
if (regs->regs_R[2] != -1)
regs->regs_R[7] = 0;
else
{
regs->regs_R[2] = errno;
regs->regs_R[7] = 1;
}
/* copy out */
for (i=0; i</* nbytes */regs->regs_R[6]; i++)
(*maf)(Write, /* buf */regs->regs_R[5]+i,
(unsigned char *)&buf[i], 1);
(*maf)(Write, /* basep */regs->regs_R[7], (unsigned char *)&base, 4);
free(buf);
}
break;
#endif
default:
panic("invalid/unimplemented system call encountered, code %d", syscode);
}
#endif /* MD_CROSS_ENDIAN */
}