diff options
Diffstat (limited to 'linux-user/m68k-sim.c')
-rw-r--r-- | linux-user/m68k-sim.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/linux-user/m68k-sim.c b/linux-user/m68k-sim.c new file mode 100644 index 0000000000..667808e8c8 --- /dev/null +++ b/linux-user/m68k-sim.c @@ -0,0 +1,171 @@ +/* + * m68k simulator syscall interface + * + * Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#include "qemu.h" + +#define SYS_EXIT 1 +#define SYS_READ 3 +#define SYS_WRITE 4 +#define SYS_OPEN 5 +#define SYS_CLOSE 6 +#define SYS_BRK 17 +#define SYS_FSTAT 28 +#define SYS_ISATTY 29 +#define SYS_LSEEK 199 + +struct m86k_sim_stat { + uint16_t sim_st_dev; + uint16_t sim_st_ino; + uint32_t sim_st_mode; + uint16_t sim_st_nlink; + uint16_t sim_st_uid; + uint16_t sim_st_gid; + uint16_t sim_st_rdev; + uint32_t sim_st_size; + uint32_t sim_st_atime; + uint32_t sim_st_mtime; + uint32_t sim_st_ctime; + uint32_t sim_st_blksize; + uint32_t sim_st_blocks; +}; + +static inline uint32_t check_err(CPUM68KState *env, uint32_t code) +{ + env->dregs[0] = code; + if (code == (uint32_t)-1) { + env->dregs[1] = errno; + } else { + env->dregs[1] = 0; + } + return code; +} + +#define SIM_O_APPEND 0x0008 +#define SIM_O_CREAT 0x0200 +#define SIM_O_TRUNC 0x0400 +#define SIM_O_EXCL 0x0800 +#define SIM_O_NONBLOCK 0x4000 +#define SIM_O_NOCTTY 0x8000 +#define SIM_O_SYNC 0x2000 + +static int translate_openflags(int flags) +{ + int hf; + + switch (flags & 3) { + case 0: hf = O_RDONLY; break; + case 1: hf = O_WRONLY; break; + case 2: hf = O_RDWR; break; + default: hf = O_RDWR; break; + } + + if (flags & SIM_O_APPEND) hf |= O_APPEND; + if (flags & SIM_O_CREAT) hf |= O_CREAT; + if (flags & SIM_O_TRUNC) hf |= O_TRUNC; + if (flags & SIM_O_EXCL) hf |= O_EXCL; + if (flags & SIM_O_NONBLOCK) hf |= O_NONBLOCK; + if (flags & SIM_O_NOCTTY) hf |= O_NOCTTY; + if (flags & SIM_O_SYNC) hf |= O_SYNC; + + return hf; +} + +#define ARG(x) tswap32(args[x]) +void do_m68k_simcall(CPUM68KState *env, int nr) +{ + uint32_t *args; + + args = (uint32_t *)(env->aregs[7] + 4); + switch (nr) { + case SYS_EXIT: + exit(ARG(0)); + case SYS_READ: + check_err(env, read(ARG(0), (void *)ARG(1), ARG(2))); + break; + case SYS_WRITE: + check_err(env, write(ARG(0), (void *)ARG(1), ARG(2))); + break; + case SYS_OPEN: + check_err(env, open((char *)ARG(0), translate_openflags(ARG(1)), + ARG(2))); + break; + case SYS_CLOSE: + { + /* Ignore attempts to close stdin/out/err. */ + int fd = ARG(0); + if (fd > 2) + check_err(env, close(fd)); + else + check_err(env, 0); + break; + } + case SYS_BRK: + { + int32_t ret; + + ret = do_brk((void *)ARG(0)); + if (ret == -ENOMEM) + ret = -1; + check_err(env, ret); + } + break; + case SYS_FSTAT: + { + struct stat s; + int rc; + struct m86k_sim_stat *p; + rc = check_err(env, fstat(ARG(0), &s)); + if (rc == 0) { + p = (struct m86k_sim_stat *)ARG(1); + p->sim_st_dev = tswap16(s.st_dev); + p->sim_st_ino = tswap16(s.st_ino); + p->sim_st_mode = tswap32(s.st_mode); + p->sim_st_nlink = tswap16(s.st_nlink); + p->sim_st_uid = tswap16(s.st_uid); + p->sim_st_gid = tswap16(s.st_gid); + p->sim_st_rdev = tswap16(s.st_rdev); + p->sim_st_size = tswap32(s.st_size); + p->sim_st_atime = tswap32(s.st_atime); + p->sim_st_mtime = tswap32(s.st_mtime); + p->sim_st_ctime = tswap32(s.st_ctime); + p->sim_st_blksize = tswap32(s.st_blksize); + p->sim_st_blocks = tswap32(s.st_blocks); + } + } + break; + case SYS_ISATTY: + check_err(env, isatty(ARG(0))); + break; + case SYS_LSEEK: + check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2))); + break; + default: + cpu_abort(env, "Unsupported m68k sim syscall %d\n", nr); + } +} |