diff options
Diffstat (limited to 'sim/m32c/syscalls.c')
-rw-r--r-- | sim/m32c/syscalls.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/sim/m32c/syscalls.c b/sim/m32c/syscalls.c new file mode 100644 index 0000000..bf33c1d --- /dev/null +++ b/sim/m32c/syscalls.c @@ -0,0 +1,336 @@ +/* syscalls.c --- implement system calls for the M32C simulator. + +Copyright (C) 2005 Free Software Foundation, Inc. +Contributed by Red Hat, Inc. + +This file is part of the GNU simulators. + +The GNU simulators are free software; you can redistribute them and/or +modify them 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. + +The GNU simulators are distributed in the hope that they 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 the GNU simulators; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA */ + + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/time.h> + +#include "gdb/callback.h" + +#include "cpu.h" +#include "mem.h" +#include "syscalls.h" + +#include "../../libgloss/syscall.h" + +/* The current syscall callbacks we're using. */ +static struct host_callback_struct *callbacks; + +void +set_callbacks (struct host_callback_struct *cb) +{ + callbacks = cb; +} + + +/* A16 ABI: arg1 in r1l (QI) or r1 (HI) or stack + arg2 in r2 (HI) or stack + arg3..N on stack + padding: none + + A24 ABI: arg1 in r0l (QI) or r0 (HI) or stack + arg2..N on stack + padding: qi->hi + + return value in r0l (QI) r0 (HI) r2r0 (SI) + structs: pointer pushed on stack last + +*/ + +int argp, stackp; + +static int +arg (int bytes) +{ + int rv = 0; + argp++; + if (A16) + { + switch (argp) + { + case 1: + if (bytes == 1) + return get_reg (r1l); + if (bytes == 2) + return get_reg (r1); + break; + case 2: + if (bytes == 2) + return get_reg (r2); + break; + } + } + else + { + switch (argp) + { + case 1: + if (bytes == 1) + return get_reg (r0l); + if (bytes == 2) + return get_reg (r0); + break; + } + } + if (bytes == 0) + bytes = 2; + switch (bytes) + { + case 1: + rv = mem_get_qi (get_reg (sp) + stackp); + if (A24) + stackp++; + break; + case 2: + rv = mem_get_hi (get_reg (sp) + stackp); + break; + case 3: + rv = mem_get_psi (get_reg (sp) + stackp); + if (A24) + stackp++; + break; + case 4: + rv = mem_get_si (get_reg (sp) + stackp); + break; + } + stackp += bytes; + return rv; +} + +static void +read_target (char *buffer, int address, int count, int asciiz) +{ + char byte; + while (count > 0) + { + byte = mem_get_qi (address++); + *buffer++ = byte; + if (asciiz && (byte == 0)) + return; + count--; + } +} + +static void +write_target (char *buffer, int address, int count, int asciiz) +{ + char byte; + while (count > 0) + { + byte = *buffer++; + mem_put_qi (address++, byte); + if (asciiz && (byte == 0)) + return; + count--; + } +} + +#define PTRSZ (A16 ? 2 : 3) + +static char *callnames[] = { + "SYS_zero", + "SYS_exit", + "SYS_open", + "SYS_close", + "SYS_read", + "SYS_write", + "SYS_lseek", + "SYS_unlink", + "SYS_getpid", + "SYS_kill", + "SYS_fstat", + "SYS_sbrk", + "SYS_argvlen", + "SYS_argv", + "SYS_chdir", + "SYS_stat", + "SYS_chmod", + "SYS_utime", + "SYS_time", + "SYS_gettimeofday", + "SYS_times", + "SYS_link" +}; + +void +m32c_syscall (int id) +{ + static char buf[256]; + int rv; + + argp = 0; + stackp = A16 ? 3 : 4; + if (trace) + printf ("\033[31m/* SYSCALL(%d) = %s */\033[0m\n", id, callnames[id]); + switch (id) + { + case SYS_exit: + { + int ec = arg (2); + if (verbose) + printf ("[exit %d]\n", ec); + step_result = M32C_MAKE_EXITED (ec); + } + break; + + case SYS_open: + { + int path = arg (PTRSZ); + int oflags = arg (2); + int cflags = arg (2); + + read_target (buf, path, 256, 1); + if (trace) + printf ("open(\"%s\",0x%x,%#o) = ", buf, oflags, cflags); + + if (callbacks) + /* The callback vector ignores CFLAGS. */ + rv = callbacks->open (callbacks, buf, oflags); + else + { + int h_oflags = 0; + + if (oflags & 0x0001) + h_oflags |= O_WRONLY; + if (oflags & 0x0002) + h_oflags |= O_RDWR; + if (oflags & 0x0200) + h_oflags |= O_CREAT; + if (oflags & 0x0008) + h_oflags |= O_APPEND; + if (oflags & 0x0400) + h_oflags |= O_TRUNC; + rv = open (buf, h_oflags, cflags); + } + if (trace) + printf ("%d\n", rv); + put_reg (r0, rv); + } + break; + + case SYS_close: + { + int fd = arg (2); + + if (callbacks) + rv = callbacks->close (callbacks, fd); + else if (fd > 2) + rv = close (fd); + else + rv = 0; + if (trace) + printf ("close(%d) = %d\n", fd, rv); + put_reg (r0, rv); + } + break; + + case SYS_read: + { + int fd = arg (2); + int addr = arg (PTRSZ); + int count = arg (2); + + if (count > sizeof (buf)) + count = sizeof (buf); + if (callbacks) + rv = callbacks->read (callbacks, fd, buf, count); + else + rv = read (fd, buf, count); + if (trace) + printf ("read(%d,%d) = %d\n", fd, count, rv); + if (rv > 0) + write_target (buf, addr, rv, 0); + put_reg (r0, rv); + } + break; + + case SYS_write: + { + int fd = arg (2); + int addr = arg (PTRSZ); + int count = arg (2); + + if (count > sizeof (buf)) + count = sizeof (buf); + if (trace) + printf ("write(%d,0x%x,%d)\n", fd, addr, count); + read_target (buf, addr, count, 0); + if (trace) + fflush (stdout); + if (callbacks) + rv = callbacks->write (callbacks, fd, buf, count); + else + rv = write (fd, buf, count); + if (trace) + printf ("write(%d,%d) = %d\n", fd, count, rv); + put_reg (r0, rv); + } + break; + + case SYS_getpid: + put_reg (r0, 42); + break; + + case SYS_gettimeofday: + { + int tvaddr = arg (PTRSZ); + struct timeval tv; + + rv = gettimeofday (&tv, 0); + if (trace) + printf ("gettimeofday: %ld sec %ld usec to 0x%x\n", tv.tv_sec, + tv.tv_usec, tvaddr); + mem_put_si (tvaddr, tv.tv_sec); + mem_put_si (tvaddr + 4, tv.tv_usec); + put_reg (r0, rv); + } + break; + + case SYS_kill: + { + int pid = arg (2); + int sig = arg (2); + if (pid == 42) + { + if (verbose) + printf ("[signal %d]\n", sig); + step_result = M32C_MAKE_STOPPED (sig); + } + } + break; + + case 11: + { + int heaptop_arg = arg (PTRSZ); + if (trace) + printf ("sbrk: heap top set to %x\n", heaptop_arg); + heaptop = heaptop_arg; + if (heapbottom == 0) + heapbottom = heaptop_arg; + } + break; + + } +} |