qemu/linux-user/m68k-sim.c
<<
>>
Prefs
   1/*
   2 *  m68k simulator syscall interface
   3 *
   4 *  Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook.
   5 *
   6 *  This program is free software; you can redistribute it and/or modify
   7 *  it under the terms of the GNU General Public License as published by
   8 *  the Free Software Foundation; either version 2 of the License, or
   9 *  (at your option) any later version.
  10 *
  11 *  This program is distributed in the hope that it will be useful,
  12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 *  GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <sys/types.h>
  21#include <sys/stat.h>
  22#include <errno.h>
  23#include <fcntl.h>
  24#include <unistd.h>
  25#include <stdlib.h>
  26#include <stdio.h>
  27#include <time.h>
  28
  29#include "qemu.h"
  30
  31#define SYS_EXIT        1
  32#define SYS_READ        3
  33#define SYS_WRITE       4
  34#define SYS_OPEN        5
  35#define SYS_CLOSE       6
  36#define SYS_BRK         17
  37#define SYS_FSTAT       28
  38#define SYS_ISATTY      29
  39#define SYS_LSEEK       199
  40
  41struct m86k_sim_stat {
  42    uint16_t sim_st_dev;
  43    uint16_t sim_st_ino;
  44    uint32_t sim_st_mode;
  45    uint16_t sim_st_nlink;
  46    uint16_t sim_st_uid;
  47    uint16_t sim_st_gid;
  48    uint16_t sim_st_rdev;
  49    uint32_t sim_st_size;
  50    uint32_t sim_st_atime;
  51    uint32_t sim_st_mtime;
  52    uint32_t sim_st_ctime;
  53    uint32_t sim_st_blksize;
  54    uint32_t sim_st_blocks;
  55};
  56
  57static inline uint32_t check_err(CPUM68KState *env, uint32_t code)
  58{
  59  env->dregs[0] = code;
  60  if (code == (uint32_t)-1) {
  61      env->dregs[1] = errno;
  62  } else {
  63      env->dregs[1] = 0;
  64  }
  65  return code;
  66}
  67
  68#define SIM_O_APPEND    0x0008
  69#define SIM_O_CREAT     0x0200
  70#define SIM_O_TRUNC     0x0400
  71#define SIM_O_EXCL      0x0800
  72#define SIM_O_NONBLOCK  0x4000
  73#define SIM_O_NOCTTY    0x8000
  74#define SIM_O_SYNC      0x2000
  75
  76static int translate_openflags(int flags)
  77{
  78    int hf;
  79
  80    switch (flags & 3) {
  81    case 0: hf = O_RDONLY; break;
  82    case 1: hf = O_WRONLY; break;
  83    case 2: hf = O_RDWR; break;
  84    default: hf = O_RDWR; break;
  85    }
  86
  87    if (flags & SIM_O_APPEND) hf |= O_APPEND;
  88    if (flags & SIM_O_CREAT) hf |= O_CREAT;
  89    if (flags & SIM_O_TRUNC) hf |= O_TRUNC;
  90    if (flags & SIM_O_EXCL) hf |= O_EXCL;
  91    if (flags & SIM_O_NONBLOCK) hf |= O_NONBLOCK;
  92    if (flags & SIM_O_NOCTTY) hf |= O_NOCTTY;
  93    if (flags & SIM_O_SYNC) hf |= O_SYNC;
  94
  95    return hf;
  96}
  97
  98#define ARG(x) tswap32(args[x])
  99void do_m68k_simcall(CPUM68KState *env, int nr)
 100{
 101    uint32_t *args;
 102
 103    args = (uint32_t *)(unsigned long)(env->aregs[7] + 4);
 104    switch (nr) {
 105    case SYS_EXIT:
 106        exit(ARG(0));
 107    case SYS_READ:
 108        check_err(env, read(ARG(0), (void *)(unsigned long)ARG(1), ARG(2)));
 109        break;
 110    case SYS_WRITE:
 111        check_err(env, write(ARG(0), (void *)(unsigned long)ARG(1), ARG(2)));
 112        break;
 113    case SYS_OPEN:
 114        check_err(env, open((char *)(unsigned long)ARG(0),
 115                            translate_openflags(ARG(1)), ARG(2)));
 116        break;
 117    case SYS_CLOSE:
 118        {
 119            /* Ignore attempts to close stdin/out/err.  */
 120            int fd = ARG(0);
 121            if (fd > 2)
 122              check_err(env, close(fd));
 123            else
 124              check_err(env, 0);
 125            break;
 126        }
 127    case SYS_BRK:
 128        {
 129            int32_t ret;
 130
 131            ret = do_brk((abi_ulong)ARG(0));
 132            if (ret == -ENOMEM)
 133                ret = -1;
 134            check_err(env, ret);
 135        }
 136        break;
 137    case SYS_FSTAT:
 138        {
 139            struct stat s;
 140            int rc;
 141            struct m86k_sim_stat *p;
 142            rc = check_err(env, fstat(ARG(0), &s));
 143            if (rc == 0) {
 144                p = (struct m86k_sim_stat *)(unsigned long)ARG(1);
 145                p->sim_st_dev = tswap16(s.st_dev);
 146                p->sim_st_ino = tswap16(s.st_ino);
 147                p->sim_st_mode = tswap32(s.st_mode);
 148                p->sim_st_nlink = tswap16(s.st_nlink);
 149                p->sim_st_uid = tswap16(s.st_uid);
 150                p->sim_st_gid = tswap16(s.st_gid);
 151                p->sim_st_rdev = tswap16(s.st_rdev);
 152                p->sim_st_size = tswap32(s.st_size);
 153                p->sim_st_atime = tswap32(s.st_atime);
 154                p->sim_st_mtime = tswap32(s.st_mtime);
 155                p->sim_st_ctime = tswap32(s.st_ctime);
 156                p->sim_st_blksize = tswap32(s.st_blksize);
 157                p->sim_st_blocks = tswap32(s.st_blocks);
 158            }
 159        }
 160        break;
 161    case SYS_ISATTY:
 162        check_err(env, isatty(ARG(0)));
 163        break;
 164    case SYS_LSEEK:
 165        check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2)));
 166        break;
 167    default:
 168        cpu_abort(env, "Unsupported m68k sim syscall %d\n", nr);
 169    }
 170}
 171