diff options
author | Mike Frysinger <vapier@gentoo.org> | 2021-07-01 00:28:10 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2021-07-01 20:46:11 -0400 |
commit | fe41f7211abb7d50c172588fa0d5e45feb067590 (patch) | |
tree | 46618318325249c61fc839b589b54d8c70a2bed9 | |
parent | sim: m32r: replace custom endian helpers with sim-endian (diff) | |
download | binutils-gdb-fe41f7211abb7d50c172588fa0d5e45feb067590.tar.gz binutils-gdb-fe41f7211abb7d50c172588fa0d5e45feb067590.tar.bz2 binutils-gdb-fe41f7211abb7d50c172588fa0d5e45feb067590.zip |
sim: m32r: unify ELF & Linux traps logic
This makes the simulator work the same regardless of the target (bare
metal m32r-elf or Linux m32r-linux-gnu) by unifying the traps code.
It was mostly already the same with the only difference being support
for trap #2 reserved for Linux syscalls. We can move that logic to
runtime by checking the current environment operating mode instead.
-rw-r--r-- | sim/m32r/ChangeLog | 12 | ||||
-rw-r--r-- | sim/m32r/Makefile.in | 5 | ||||
-rwxr-xr-x | sim/m32r/configure | 15 | ||||
-rw-r--r-- | sim/m32r/configure.ac | 13 | ||||
-rw-r--r-- | sim/m32r/sim-if.c | 15 | ||||
-rw-r--r-- | sim/m32r/sim-main.h | 7 | ||||
-rw-r--r-- | sim/m32r/traps-linux.c | 1326 | ||||
-rw-r--r-- | sim/m32r/traps.c | 1199 |
8 files changed, 1207 insertions, 1385 deletions
diff --git a/sim/m32r/ChangeLog b/sim/m32r/ChangeLog index 1a5f772274b..6b80e6a904f 100644 --- a/sim/m32r/ChangeLog +++ b/sim/m32r/ChangeLog @@ -1,5 +1,17 @@ 2021-07-01 Mike Frysinger <vapier@gentoo.org> + * Makefile.in (TRAPS_OBJ, SIM_EXTRA_CFLAGS): Delete. + * configure.ac (traps_obj, sim_extra_cflags): Delete. + * sim-if.c (M32R_DEFAULT_MEM_SIZE): New define. + (sim_create_inferior): Replace M32R_LINUX with STATE_ENVIRONMENT + check. + * sim-main.h (M32R_DEFAULT_MEM_SIZE): Delete. + * traps-linux.c: Merge with ... + * traps.c: ... this file. + * configure: Regenerate. + +2021-07-01 Mike Frysinger <vapier@gentoo.org> + * traps-linux.c (conv_endian, conv_endian16, translate_endian): Delete. (translate_endian_h2t): New host-to-target function. diff --git a/sim/m32r/Makefile.in b/sim/m32r/Makefile.in index eb9641ee8e6..8877edcf4ae 100644 --- a/sim/m32r/Makefile.in +++ b/sim/m32r/Makefile.in @@ -22,7 +22,6 @@ M32R_OBJS = m32r.o cpu.o decode.o sem.o model.o mloop.o M32RX_OBJS = m32rx.o cpux.o decodex.o modelx.o mloopx.o M32R2_OBJS = m32r2.o cpu2.o decode2.o model2.o mloop2.o -TRAPS_OBJ = @traps_obj@ SIM_OBJS = \ $(SIM_NEW_COMMON_OBJS) \ @@ -32,7 +31,7 @@ SIM_OBJS = \ $(M32R_OBJS) \ $(M32RX_OBJS) \ $(M32R2_OBJS) \ - $(TRAPS_OBJ) + traps.o SIM_EXTRA_HW_DEVICES = m32r_cache m32r_uart @@ -42,8 +41,6 @@ SIM_EXTRA_DEPS = \ arch.h cpuall.h m32r-sim.h $(srcdir)/../../opcodes/m32r-desc.h \ eng.h engx.h eng2.h -SIM_EXTRA_CFLAGS = @sim_extra_cflags@ - SIM_EXTRA_CLEAN = m32r-clean # Code doesn't build cleanly yet. diff --git a/sim/m32r/configure b/sim/m32r/configure index d3dbc725a38..38fa43dc998 100755 --- a/sim/m32r/configure +++ b/sim/m32r/configure @@ -590,8 +590,6 @@ sim_reserved_bits sim_float sim_bitsize cgen_breaks -sim_extra_cflags -traps_obj target_alias host_alias build_alias @@ -1670,19 +1668,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu - case "${target_alias}" in - m32r*-linux*) - traps_obj=traps-linux.o - sim_extra_cflags="-DM32R_LINUX" - ;; - *) - traps_obj=traps.o - sim_extra_cflags="-DM32R_ELF" - ;; - esac - - - cgen_breaks="" if grep CGEN_MAINT $srcdir/Makefile.in >/dev/null; then cgen_breaks="break cgen_rtx_error"; diff --git a/sim/m32r/configure.ac b/sim/m32r/configure.ac index d8054034abc..99370b3a577 100644 --- a/sim/m32r/configure.ac +++ b/sim/m32r/configure.ac @@ -2,17 +2,4 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(Makefile.in) AC_CONFIG_MACRO_DIRS([../m4 ../.. ../../config]) - case "${target_alias}" in - m32r*-linux*) - traps_obj=traps-linux.o - sim_extra_cflags="-DM32R_LINUX" - ;; - *) - traps_obj=traps.o - sim_extra_cflags="-DM32R_ELF" - ;; - esac -AC_SUBST(traps_obj) -AC_SUBST(sim_extra_cflags) - SIM_AC_OUTPUT diff --git a/sim/m32r/sim-if.c b/sim/m32r/sim-if.c index 8957e83bf33..e05b1630ace 100644 --- a/sim/m32r/sim-if.c +++ b/sim/m32r/sim-if.c @@ -30,6 +30,8 @@ #include "dv-m32r_uart.h" +#define M32R_DEFAULT_MEM_SIZE 0x2000000 /* 32M */ + static void free_state (SIM_DESC); static void print_m32r_misc_cpu (SIM_CPU *cpu, int verbose); @@ -158,12 +160,13 @@ sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char * const *argv, addr = 0; sim_pc_set (current_cpu, addr); -#ifdef M32R_LINUX - m32rbf_h_cr_set (current_cpu, - m32r_decode_gdb_ctrl_regnum(SPI_REGNUM), 0x1f00000); - m32rbf_h_cr_set (current_cpu, - m32r_decode_gdb_ctrl_regnum(SPU_REGNUM), 0x1f00000); -#endif + if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT) + { + m32rbf_h_cr_set (current_cpu, + m32r_decode_gdb_ctrl_regnum(SPI_REGNUM), 0x1f00000); + m32rbf_h_cr_set (current_cpu, + m32r_decode_gdb_ctrl_regnum(SPU_REGNUM), 0x1f00000); + } /* Standalone mode (i.e. `run`) will take care of the argv for us in sim_open() -> sim_parse_args(). But in debug mode (i.e. 'target sim' diff --git a/sim/m32r/sim-main.h b/sim/m32r/sim-main.h index f89db483c8c..2ce989a897a 100644 --- a/sim/m32r/sim-main.h +++ b/sim/m32r/sim-main.h @@ -56,11 +56,4 @@ extern SIM_CORE_SIGNAL_FN m32r_core_signal; m32r_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), \ (TRANSFER), (ERROR)) -/* Default memory size. */ -#ifdef M32R_LINUX -#define M32R_DEFAULT_MEM_SIZE 0x2000000 /* 32M */ -#else -#define M32R_DEFAULT_MEM_SIZE 0x800000 /* 8M */ -#endif - #endif /* SIM_MAIN_H */ diff --git a/sim/m32r/traps-linux.c b/sim/m32r/traps-linux.c deleted file mode 100644 index 4d86a0a4e36..00000000000 --- a/sim/m32r/traps-linux.c +++ /dev/null @@ -1,1326 +0,0 @@ -/* m32r exception, interrupt, and trap (EIT) support - Copyright (C) 1998-2021 Free Software Foundation, Inc. - Contributed by Renesas. - - This file is part of GDB, the GNU debugger. - - 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 3 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, see <http://www.gnu.org/licenses/>. */ - -/* This must come before any other includes. */ -#include "defs.h" - -#include "portability.h" -#include "sim-main.h" -#include "sim-signal.h" -#include "sim-syscall.h" -#include "sim/callback.h" -#include "syscall.h" -#include "targ-vals.h" -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> -#include <utime.h> -#include <sys/mman.h> -#include <sys/poll.h> -#include <sys/resource.h> -#include <sys/sysinfo.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/timeb.h> -#include <sys/timex.h> -#include <sys/types.h> -#include <sys/uio.h> -#include <sys/utsname.h> -#include <sys/vfs.h> -#include <linux/sysctl.h> -#include <linux/types.h> -#include <linux/unistd.h> - -#define TRAP_ELF_SYSCALL 0 -#define TRAP_LINUX_SYSCALL 2 -#define TRAP_FLUSH_CACHE 12 - -/* The semantic code invokes this for invalid (unrecognized) instructions. */ - -SEM_PC -sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) -{ - SIM_DESC sd = CPU_STATE (current_cpu); - -#if 0 - if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) - { - h_bsm_set (current_cpu, h_sm_get (current_cpu)); - h_bie_set (current_cpu, h_ie_get (current_cpu)); - h_bcond_set (current_cpu, h_cond_get (current_cpu)); - /* sm not changed */ - h_ie_set (current_cpu, 0); - h_cond_set (current_cpu, 0); - - h_bpc_set (current_cpu, cia); - - sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, - EIT_RSVD_INSN_ADDR); - } - else -#endif - sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); - return vpc; -} - -/* Process an address exception. */ - -void -m32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, - unsigned int map, int nr_bytes, address_word addr, - transfer_type transfer, sim_core_signals sig) -{ - if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) - { - m32rbf_h_cr_set (current_cpu, H_CR_BBPC, - m32rbf_h_cr_get (current_cpu, H_CR_BPC)); - if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32R) - { - m32rbf_h_bpsw_set (current_cpu, m32rbf_h_psw_get (current_cpu)); - /* sm not changed */ - m32rbf_h_psw_set (current_cpu, m32rbf_h_psw_get (current_cpu) & 0x80); - } - else if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32RX) - { - m32rxf_h_bpsw_set (current_cpu, m32rxf_h_psw_get (current_cpu)); - /* sm not changed */ - m32rxf_h_psw_set (current_cpu, m32rxf_h_psw_get (current_cpu) & 0x80); - } - else - { - m32r2f_h_bpsw_set (current_cpu, m32r2f_h_psw_get (current_cpu)); - /* sm not changed */ - m32r2f_h_psw_set (current_cpu, m32r2f_h_psw_get (current_cpu) & 0x80); - } - m32rbf_h_cr_set (current_cpu, H_CR_BPC, cia); - - sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, - EIT_ADDR_EXCP_ADDR); - } - else - sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, - transfer, sig); -} - -/* Translate target's address to host's address. */ - -static void * -t2h_addr (host_callback *cb, struct cb_syscall *sc, - unsigned long taddr) -{ - void *addr; - SIM_DESC sd = (SIM_DESC) sc->p1; - SIM_CPU *cpu = (SIM_CPU *) sc->p2; - - if (taddr == 0) - return NULL; - - return sim_core_trans_addr (sd, cpu, read_map, taddr); -} - -/* TODO: These functions are a big hack and assume that the host runtime has - type sizes and struct layouts that match the target. So the Linux emulation - probaly only really works in 32-bit runtimes. */ - -static void -translate_endian_h2t (void *addr, size_t size) -{ - unsigned int *p = (unsigned int *) addr; - int i; - - for (i = 0; i <= size - 4; i += 4,p++) - *p = H2T_4 (*p); - - if (i <= size - 2) - *((unsigned short *) p) = H2T_2 (*((unsigned short *) p)); -} - -static void -translate_endian_t2h (void *addr, size_t size) -{ - unsigned int *p = (unsigned int *) addr; - int i; - - for (i = 0; i <= size - 4; i += 4,p++) - *p = T2H_4 (*p); - - if (i <= size - 2) - *((unsigned short *) p) = T2H_2 (*((unsigned short *) p)); -} - -/* Trap support. - The result is the pc address to continue at. - Preprocessing like saving the various registers has already been done. */ - -USI -m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) -{ - SIM_DESC sd = CPU_STATE (current_cpu); - host_callback *cb = STATE_CALLBACK (sd); - - switch (num) - { - case TRAP_ELF_SYSCALL : - { - long result, result2; - int errcode; - - sim_syscall_multi (current_cpu, - m32rbf_h_gr_get (current_cpu, 0), - m32rbf_h_gr_get (current_cpu, 1), - m32rbf_h_gr_get (current_cpu, 2), - m32rbf_h_gr_get (current_cpu, 3), - m32rbf_h_gr_get (current_cpu, 4), - &result, &result2, &errcode); - - m32rbf_h_gr_set (current_cpu, 2, errcode); - m32rbf_h_gr_set (current_cpu, 0, result); - m32rbf_h_gr_set (current_cpu, 1, result2); - break; - } - - case TRAP_LINUX_SYSCALL : - { - CB_SYSCALL s; - unsigned int func, arg1, arg2, arg3, arg4, arg5, arg6, arg7; - int result, result2, errcode; - - if (STATE_ENVIRONMENT (sd) != USER_ENVIRONMENT) - goto case_default; - - func = m32rbf_h_gr_get (current_cpu, 7); - arg1 = m32rbf_h_gr_get (current_cpu, 0); - arg2 = m32rbf_h_gr_get (current_cpu, 1); - arg3 = m32rbf_h_gr_get (current_cpu, 2); - arg4 = m32rbf_h_gr_get (current_cpu, 3); - arg5 = m32rbf_h_gr_get (current_cpu, 4); - arg6 = m32rbf_h_gr_get (current_cpu, 5); - arg7 = m32rbf_h_gr_get (current_cpu, 6); - - CB_SYSCALL_INIT (&s); - s.func = func; - s.arg1 = arg1; - s.arg2 = arg2; - s.arg3 = arg3; - s.arg4 = arg4; - s.arg5 = arg5; - s.arg6 = arg6; - s.arg7 = arg7; - - s.p1 = (PTR) sd; - s.p2 = (PTR) current_cpu; - s.read_mem = sim_syscall_read_mem; - s.write_mem = sim_syscall_write_mem; - - result = 0; - result2 = 0; - errcode = 0; - - switch (func) - { - case TARGET_LINUX_SYS_exit: - sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1); - break; - - case TARGET_LINUX_SYS_read: - result = read(arg1, t2h_addr(cb, &s, arg2), arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_write: - result = write(arg1, t2h_addr(cb, &s, arg2), arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_open: - result = open((char *) t2h_addr(cb, &s, arg1), arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_close: - result = close(arg1); - errcode = errno; - break; - - case TARGET_LINUX_SYS_creat: - result = creat((char *) t2h_addr(cb, &s, arg1), arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_link: - result = link((char *) t2h_addr(cb, &s, arg1), - (char *) t2h_addr(cb, &s, arg2)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_unlink: - result = unlink((char *) t2h_addr(cb, &s, arg1)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_chdir: - result = chdir((char *) t2h_addr(cb, &s, arg1)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_time: - { - time_t t; - - if (arg1 == 0) - { - result = (int) time(NULL); - errcode = errno; - } - else - { - result = (int) time(&t); - errcode = errno; - - if (result != 0) - break; - - t = H2T_4 (t); - if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) != sizeof(t)) - { - result = -1; - errcode = EINVAL; - } - } - } - break; - - case TARGET_LINUX_SYS_mknod: - result = mknod((char *) t2h_addr(cb, &s, arg1), - (mode_t) arg2, (dev_t) arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_chmod: - result = chmod((char *) t2h_addr(cb, &s, arg1), (mode_t) arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_lchown32: - case TARGET_LINUX_SYS_lchown: - result = lchown((char *) t2h_addr(cb, &s, arg1), - (uid_t) arg2, (gid_t) arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_lseek: - result = (int) lseek(arg1, (off_t) arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getpid: - result = getpid(); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getuid32: - case TARGET_LINUX_SYS_getuid: - result = getuid(); - errcode = errno; - break; - - case TARGET_LINUX_SYS_utime: - { - struct utimbuf buf; - - if (arg2 == 0) - { - result = utime((char *) t2h_addr(cb, &s, arg1), NULL); - errcode = errno; - } - else - { - buf = *((struct utimbuf *) t2h_addr(cb, &s, arg2)); - translate_endian_t2h (&buf, sizeof(buf)); - result = utime((char *) t2h_addr(cb, &s, arg1), &buf); - errcode = errno; - } - } - break; - - case TARGET_LINUX_SYS_access: - result = access((char *) t2h_addr(cb, &s, arg1), arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_ftime: - { - struct timeb t; - - result = ftime(&t); - errcode = errno; - - if (result != 0) - break; - - t.time = H2T_4 (t.time); - t.millitm = H2T_2 (t.millitm); - t.timezone = H2T_2 (t.timezone); - t.dstflag = H2T_2 (t.dstflag); - if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) - != sizeof(t)) - { - result = -1; - errcode = EINVAL; - } - } - - case TARGET_LINUX_SYS_sync: - sync(); - result = 0; - break; - - case TARGET_LINUX_SYS_rename: - result = rename((char *) t2h_addr(cb, &s, arg1), - (char *) t2h_addr(cb, &s, arg2)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_mkdir: - result = mkdir((char *) t2h_addr(cb, &s, arg1), arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_rmdir: - result = rmdir((char *) t2h_addr(cb, &s, arg1)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_dup: - result = dup(arg1); - errcode = errno; - break; - - case TARGET_LINUX_SYS_brk: - result = brk((void *) arg1); - errcode = errno; - //result = arg1; - break; - - case TARGET_LINUX_SYS_getgid32: - case TARGET_LINUX_SYS_getgid: - result = getgid(); - errcode = errno; - break; - - case TARGET_LINUX_SYS_geteuid32: - case TARGET_LINUX_SYS_geteuid: - result = geteuid(); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getegid32: - case TARGET_LINUX_SYS_getegid: - result = getegid(); - errcode = errno; - break; - - case TARGET_LINUX_SYS_ioctl: - result = ioctl(arg1, arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_fcntl: - result = fcntl(arg1, arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_dup2: - result = dup2(arg1, arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getppid: - result = getppid(); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getpgrp: - result = getpgrp(); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getrlimit: - { - struct rlimit rlim; - - result = getrlimit(arg1, &rlim); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&rlim, sizeof(rlim)); - if ((s.write_mem) (cb, &s, arg2, (char *) &rlim, sizeof(rlim)) - != sizeof(rlim)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_getrusage: - { - struct rusage usage; - - result = getrusage(arg1, &usage); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&usage, sizeof(usage)); - if ((s.write_mem) (cb, &s, arg2, (char *) &usage, sizeof(usage)) - != sizeof(usage)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_gettimeofday: - { - struct timeval tv; - struct timezone tz; - - result = gettimeofday(&tv, &tz); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&tv, sizeof(tv)); - if ((s.write_mem) (cb, &s, arg1, (char *) &tv, sizeof(tv)) - != sizeof(tv)) - { - result = -1; - errcode = EINVAL; - } - - translate_endian_h2t (&tz, sizeof(tz)); - if ((s.write_mem) (cb, &s, arg2, (char *) &tz, sizeof(tz)) - != sizeof(tz)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_getgroups32: - case TARGET_LINUX_SYS_getgroups: - { - gid_t *list; - - if (arg1 > 0) - list = (gid_t *) malloc(arg1 * sizeof(gid_t)); - - result = getgroups(arg1, list); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (list, arg1 * sizeof(gid_t)); - if (arg1 > 0) - if ((s.write_mem) (cb, &s, arg2, (char *) list, arg1 * sizeof(gid_t)) - != arg1 * sizeof(gid_t)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_select: - { - int n; - fd_set readfds; - fd_set *treadfdsp; - fd_set *hreadfdsp; - fd_set writefds; - fd_set *twritefdsp; - fd_set *hwritefdsp; - fd_set exceptfds; - fd_set *texceptfdsp; - fd_set *hexceptfdsp; - struct timeval *ttimeoutp; - struct timeval timeout; - - n = arg1; - - treadfdsp = (fd_set *) arg2; - if (treadfdsp != NULL) - { - readfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) treadfdsp)); - translate_endian_t2h (&readfds, sizeof(readfds)); - hreadfdsp = &readfds; - } - else - hreadfdsp = NULL; - - twritefdsp = (fd_set *) arg3; - if (twritefdsp != NULL) - { - writefds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) twritefdsp)); - translate_endian_t2h (&writefds, sizeof(writefds)); - hwritefdsp = &writefds; - } - else - hwritefdsp = NULL; - - texceptfdsp = (fd_set *) arg4; - if (texceptfdsp != NULL) - { - exceptfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) texceptfdsp)); - translate_endian_t2h (&exceptfds, sizeof(exceptfds)); - hexceptfdsp = &exceptfds; - } - else - hexceptfdsp = NULL; - - ttimeoutp = (struct timeval *) arg5; - timeout = *((struct timeval *) t2h_addr(cb, &s, (unsigned int) ttimeoutp)); - translate_endian_t2h (&timeout, sizeof(timeout)); - - result = select(n, hreadfdsp, hwritefdsp, hexceptfdsp, &timeout); - errcode = errno; - - if (result != 0) - break; - - if (treadfdsp != NULL) - { - translate_endian_h2t (&readfds, sizeof(readfds)); - if ((s.write_mem) (cb, &s, (unsigned long) treadfdsp, - (char *) &readfds, sizeof(readfds)) != sizeof(readfds)) - { - result = -1; - errcode = EINVAL; - } - } - - if (twritefdsp != NULL) - { - translate_endian_h2t (&writefds, sizeof(writefds)); - if ((s.write_mem) (cb, &s, (unsigned long) twritefdsp, - (char *) &writefds, sizeof(writefds)) != sizeof(writefds)) - { - result = -1; - errcode = EINVAL; - } - } - - if (texceptfdsp != NULL) - { - translate_endian_h2t (&exceptfds, sizeof(exceptfds)); - if ((s.write_mem) (cb, &s, (unsigned long) texceptfdsp, - (char *) &exceptfds, sizeof(exceptfds)) != sizeof(exceptfds)) - { - result = -1; - errcode = EINVAL; - } - } - - translate_endian_h2t (&timeout, sizeof(timeout)); - if ((s.write_mem) (cb, &s, (unsigned long) ttimeoutp, - (char *) &timeout, sizeof(timeout)) != sizeof(timeout)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_symlink: - result = symlink((char *) t2h_addr(cb, &s, arg1), - (char *) t2h_addr(cb, &s, arg2)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_readlink: - result = readlink((char *) t2h_addr(cb, &s, arg1), - (char *) t2h_addr(cb, &s, arg2), - arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_readdir: - result = (int) readdir((DIR *) t2h_addr(cb, &s, arg1)); - errcode = errno; - break; - -#if 0 - case TARGET_LINUX_SYS_mmap: - { - result = (int) mmap((void *) t2h_addr(cb, &s, arg1), - arg2, arg3, arg4, arg5, arg6); - errcode = errno; - - if (errno == 0) - { - sim_core_attach (sd, NULL, - 0, access_read_write_exec, 0, - result, arg2, 0, NULL, NULL); - } - } - break; -#endif - case TARGET_LINUX_SYS_mmap2: - { - void *addr; - size_t len; - int prot, flags, fildes; - off_t off; - - addr = (void *) t2h_addr(cb, &s, arg1); - len = arg2; - prot = arg3; - flags = arg4; - fildes = arg5; - off = arg6 << 12; - - result = (int) mmap(addr, len, prot, flags, fildes, off); - errcode = errno; - if (result != -1) - { - char c; - if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0) - sim_core_attach (sd, NULL, - 0, access_read_write_exec, 0, - result, len, 0, NULL, NULL); - } - } - break; - - case TARGET_LINUX_SYS_mmap: - { - void *addr; - size_t len; - int prot, flags, fildes; - off_t off; - - addr = *((void **) t2h_addr(cb, &s, arg1)); - len = *((size_t *) t2h_addr(cb, &s, arg1 + 4)); - prot = *((int *) t2h_addr(cb, &s, arg1 + 8)); - flags = *((int *) t2h_addr(cb, &s, arg1 + 12)); - fildes = *((int *) t2h_addr(cb, &s, arg1 + 16)); - off = *((off_t *) t2h_addr(cb, &s, arg1 + 20)); - - addr = (void *) T2H_4 ((unsigned int) addr); - len = T2H_4 (len); - prot = T2H_4 (prot); - flags = T2H_4 (flags); - fildes = T2H_4 (fildes); - off = T2H_4 (off); - - //addr = (void *) t2h_addr(cb, &s, (unsigned int) addr); - result = (int) mmap(addr, len, prot, flags, fildes, off); - errcode = errno; - - //if (errno == 0) - if (result != -1) - { - char c; - if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0) - sim_core_attach (sd, NULL, - 0, access_read_write_exec, 0, - result, len, 0, NULL, NULL); - } - } - break; - - case TARGET_LINUX_SYS_munmap: - { - result = munmap((void *)arg1, arg2); - errcode = errno; - if (result != -1) - { - sim_core_detach (sd, NULL, 0, arg2, result); - } - } - break; - - case TARGET_LINUX_SYS_truncate: - result = truncate((char *) t2h_addr(cb, &s, arg1), arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_ftruncate: - result = ftruncate(arg1, arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_fchmod: - result = fchmod(arg1, arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_fchown32: - case TARGET_LINUX_SYS_fchown: - result = fchown(arg1, arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_statfs: - { - struct statfs statbuf; - - result = statfs((char *) t2h_addr(cb, &s, arg1), &statbuf); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&statbuf, sizeof(statbuf)); - if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) - != sizeof(statbuf)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_fstatfs: - { - struct statfs statbuf; - - result = fstatfs(arg1, &statbuf); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&statbuf, sizeof(statbuf)); - if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) - != sizeof(statbuf)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_syslog: - result = syslog(arg1, (char *) t2h_addr(cb, &s, arg2)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_setitimer: - { - struct itimerval value, ovalue; - - value = *((struct itimerval *) t2h_addr(cb, &s, arg2)); - translate_endian_t2h (&value, sizeof(value)); - - if (arg2 == 0) - { - result = setitimer(arg1, &value, NULL); - errcode = errno; - } - else - { - result = setitimer(arg1, &value, &ovalue); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&ovalue, sizeof(ovalue)); - if ((s.write_mem) (cb, &s, arg3, (char *) &ovalue, sizeof(ovalue)) - != sizeof(ovalue)) - { - result = -1; - errcode = EINVAL; - } - } - } - break; - - case TARGET_LINUX_SYS_getitimer: - { - struct itimerval value; - - result = getitimer(arg1, &value); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&value, sizeof(value)); - if ((s.write_mem) (cb, &s, arg2, (char *) &value, sizeof(value)) - != sizeof(value)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_stat: - { - char *buf; - int buflen; - struct stat statbuf; - - result = stat((char *) t2h_addr(cb, &s, arg1), &statbuf); - errcode = errno; - if (result < 0) - break; - - buflen = cb_host_to_target_stat (cb, NULL, NULL); - buf = xmalloc (buflen); - if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) - { - /* The translation failed. This is due to an internal - host program error, not the target's fault. */ - free (buf); - result = -1; - errcode = ENOSYS; - break; - } - if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) - { - free (buf); - result = -1; - errcode = EINVAL; - break; - } - free (buf); - } - break; - - case TARGET_LINUX_SYS_lstat: - { - char *buf; - int buflen; - struct stat statbuf; - - result = lstat((char *) t2h_addr(cb, &s, arg1), &statbuf); - errcode = errno; - if (result < 0) - break; - - buflen = cb_host_to_target_stat (cb, NULL, NULL); - buf = xmalloc (buflen); - if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) - { - /* The translation failed. This is due to an internal - host program error, not the target's fault. */ - free (buf); - result = -1; - errcode = ENOSYS; - break; - } - if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) - { - free (buf); - result = -1; - errcode = EINVAL; - break; - } - free (buf); - } - break; - - case TARGET_LINUX_SYS_fstat: - { - char *buf; - int buflen; - struct stat statbuf; - - result = fstat(arg1, &statbuf); - errcode = errno; - if (result < 0) - break; - - buflen = cb_host_to_target_stat (cb, NULL, NULL); - buf = xmalloc (buflen); - if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) - { - /* The translation failed. This is due to an internal - host program error, not the target's fault. */ - free (buf); - result = -1; - errcode = ENOSYS; - break; - } - if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) - { - free (buf); - result = -1; - errcode = EINVAL; - break; - } - free (buf); - } - break; - - case TARGET_LINUX_SYS_sysinfo: - { - struct sysinfo info; - - result = sysinfo(&info); - errcode = errno; - - if (result != 0) - break; - - info.uptime = H2T_4 (info.uptime); - info.loads[0] = H2T_4 (info.loads[0]); - info.loads[1] = H2T_4 (info.loads[1]); - info.loads[2] = H2T_4 (info.loads[2]); - info.totalram = H2T_4 (info.totalram); - info.freeram = H2T_4 (info.freeram); - info.sharedram = H2T_4 (info.sharedram); - info.bufferram = H2T_4 (info.bufferram); - info.totalswap = H2T_4 (info.totalswap); - info.freeswap = H2T_4 (info.freeswap); - info.procs = H2T_2 (info.procs); -#if LINUX_VERSION_CODE >= 0x20400 - info.totalhigh = H2T_4 (info.totalhigh); - info.freehigh = H2T_4 (info.freehigh); - info.mem_unit = H2T_4 (info.mem_unit); -#endif - if ((s.write_mem) (cb, &s, arg1, (char *) &info, sizeof(info)) - != sizeof(info)) - { - result = -1; - errcode = EINVAL; - } - } - break; - -#if 0 - case TARGET_LINUX_SYS_ipc: - { - result = ipc(arg1, arg2, arg3, arg4, - (void *) t2h_addr(cb, &s, arg5), arg6); - errcode = errno; - } - break; -#endif - - case TARGET_LINUX_SYS_fsync: - result = fsync(arg1); - errcode = errno; - break; - - case TARGET_LINUX_SYS_uname: - /* utsname contains only arrays of char, so it is not necessary - to translate endian. */ - result = uname((struct utsname *) t2h_addr(cb, &s, arg1)); - errcode = errno; - break; - - case TARGET_LINUX_SYS_adjtimex: - { - struct timex buf; - - result = adjtimex(&buf); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&buf, sizeof(buf)); - if ((s.write_mem) (cb, &s, arg1, (char *) &buf, sizeof(buf)) - != sizeof(buf)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_mprotect: - result = mprotect((void *) arg1, arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_fchdir: - result = fchdir(arg1); - errcode = errno; - break; - - case TARGET_LINUX_SYS_setfsuid32: - case TARGET_LINUX_SYS_setfsuid: - result = setfsuid(arg1); - errcode = errno; - break; - - case TARGET_LINUX_SYS_setfsgid32: - case TARGET_LINUX_SYS_setfsgid: - result = setfsgid(arg1); - errcode = errno; - break; - -#if 0 - case TARGET_LINUX_SYS__llseek: - { - loff_t buf; - - result = _llseek(arg1, arg2, arg3, &buf, arg5); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&buf, sizeof(buf)); - if ((s.write_mem) (cb, &s, t2h_addr(cb, &s, arg4), - (char *) &buf, sizeof(buf)) != sizeof(buf)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_getdents: - { - struct dirent dir; - - result = getdents(arg1, &dir, arg3); - errcode = errno; - - if (result != 0) - break; - - dir.d_ino = H2T_4 (dir.d_ino); - dir.d_off = H2T_4 (dir.d_off); - dir.d_reclen = H2T_2 (dir.d_reclen); - if ((s.write_mem) (cb, &s, arg2, (char *) &dir, sizeof(dir)) - != sizeof(dir)) - { - result = -1; - errcode = EINVAL; - } - } - break; -#endif - - case TARGET_LINUX_SYS_flock: - result = flock(arg1, arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_msync: - result = msync((void *) arg1, arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_readv: - { - struct iovec vector; - - vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); - translate_endian_t2h (&vector, sizeof(vector)); - - result = readv(arg1, &vector, arg3); - errcode = errno; - } - break; - - case TARGET_LINUX_SYS_writev: - { - struct iovec vector; - - vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); - translate_endian_t2h (&vector, sizeof(vector)); - - result = writev(arg1, &vector, arg3); - errcode = errno; - } - break; - - case TARGET_LINUX_SYS_fdatasync: - result = fdatasync(arg1); - errcode = errno; - break; - - case TARGET_LINUX_SYS_mlock: - result = mlock((void *) t2h_addr(cb, &s, arg1), arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_munlock: - result = munlock((void *) t2h_addr(cb, &s, arg1), arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_nanosleep: - { - struct timespec req, rem; - - req = *((struct timespec *) t2h_addr(cb, &s, arg2)); - translate_endian_t2h (&req, sizeof(req)); - - result = nanosleep(&req, &rem); - errcode = errno; - - if (result != 0) - break; - - translate_endian_h2t (&rem, sizeof(rem)); - if ((s.write_mem) (cb, &s, arg2, (char *) &rem, sizeof(rem)) - != sizeof(rem)) - { - result = -1; - errcode = EINVAL; - } - } - break; - - case TARGET_LINUX_SYS_mremap: /* FIXME */ - result = (int) mremap((void *) t2h_addr(cb, &s, arg1), arg2, arg3, arg4); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getresuid32: - case TARGET_LINUX_SYS_getresuid: - { - uid_t ruid, euid, suid; - - result = getresuid(&ruid, &euid, &suid); - errcode = errno; - - if (result != 0) - break; - - *((uid_t *) t2h_addr(cb, &s, arg1)) = H2T_4 (ruid); - *((uid_t *) t2h_addr(cb, &s, arg2)) = H2T_4 (euid); - *((uid_t *) t2h_addr(cb, &s, arg3)) = H2T_4 (suid); - } - break; - - case TARGET_LINUX_SYS_poll: - { - struct pollfd ufds; - - ufds = *((struct pollfd *) t2h_addr(cb, &s, arg1)); - ufds.fd = T2H_4 (ufds.fd); - ufds.events = T2H_2 (ufds.events); - ufds.revents = T2H_2 (ufds.revents); - - result = poll(&ufds, arg2, arg3); - errcode = errno; - } - break; - - case TARGET_LINUX_SYS_getresgid32: - case TARGET_LINUX_SYS_getresgid: - { - uid_t rgid, egid, sgid; - - result = getresgid(&rgid, &egid, &sgid); - errcode = errno; - - if (result != 0) - break; - - *((uid_t *) t2h_addr(cb, &s, arg1)) = H2T_4 (rgid); - *((uid_t *) t2h_addr(cb, &s, arg2)) = H2T_4 (egid); - *((uid_t *) t2h_addr(cb, &s, arg3)) = H2T_4 (sgid); - } - break; - - case TARGET_LINUX_SYS_pread: - result = pread(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); - errcode = errno; - break; - - case TARGET_LINUX_SYS_pwrite: - result = pwrite(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); - errcode = errno; - break; - - case TARGET_LINUX_SYS_chown32: - case TARGET_LINUX_SYS_chown: - result = chown((char *) t2h_addr(cb, &s, arg1), arg2, arg3); - errcode = errno; - break; - - case TARGET_LINUX_SYS_getcwd: - result = (int) getcwd((char *) t2h_addr(cb, &s, arg1), arg2); - errcode = errno; - break; - - case TARGET_LINUX_SYS_sendfile: - { - off_t offset; - - offset = *((off_t *) t2h_addr(cb, &s, arg3)); - offset = T2H_4 (offset); - - result = sendfile(arg1, arg2, &offset, arg3); - errcode = errno; - - if (result != 0) - break; - - *((off_t *) t2h_addr(cb, &s, arg3)) = H2T_4 (offset); - } - break; - - default: - result = -1; - errcode = ENOSYS; - break; - } - - if (result == -1) - m32rbf_h_gr_set (current_cpu, 0, -errcode); - else - m32rbf_h_gr_set (current_cpu, 0, result); - break; - } - - case TRAP_BREAKPOINT: - sim_engine_halt (sd, current_cpu, NULL, pc, - sim_stopped, SIM_SIGTRAP); - break; - - case TRAP_FLUSH_CACHE: - /* Do nothing. */ - break; - - case_default: - default : - { - /* Use cr5 as EVB (EIT Vector Base) register. */ - USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; - return new_pc; - } - } - - /* Fake an "rte" insn. */ - /* FIXME: Should duplicate all of rte processing. */ - return (pc & -4) + 4; -} diff --git a/sim/m32r/traps.c b/sim/m32r/traps.c index 4cec5c0d45c..c4c1224ad27 100644 --- a/sim/m32r/traps.c +++ b/sim/m32r/traps.c @@ -1,6 +1,6 @@ /* m32r exception, interrupt, and trap (EIT) support Copyright (C) 1998-2021 Free Software Foundation, Inc. - Contributed by Cygnus Solutions. + Contributed by Cygnus Solutions & Renesas. This file is part of GDB, the GNU debugger. @@ -20,12 +20,37 @@ /* This must come before any other includes. */ #include "defs.h" +#include "portability.h" #include "sim-main.h" #include "sim-signal.h" #include "sim-syscall.h" +#include "sim/callback.h" +#include "syscall.h" #include "targ-vals.h" +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> #include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> +#include <sys/mman.h> +#include <sys/poll.h> +#include <sys/resource.h> +#include <sys/sysinfo.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/timeb.h> +#include <sys/timex.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/utsname.h> +#include <sys/vfs.h> +#include <linux/sysctl.h> +#include <linux/types.h> +#include <linux/unistd.h> +#define TRAP_LINUX_SYSCALL 2 #define TRAP_FLUSH_CACHE 12 /* The semantic code invokes this for invalid (unrecognized) instructions. */ @@ -87,7 +112,7 @@ m32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, default: abort (); } - + m32rbf_h_cr_set (current_cpu, H_CR_BPC, cia); sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, @@ -98,6 +123,52 @@ m32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, transfer, sig); } +/* Translate target's address to host's address. */ + +static void * +t2h_addr (host_callback *cb, struct cb_syscall *sc, + unsigned long taddr) +{ + void *addr; + SIM_DESC sd = (SIM_DESC) sc->p1; + SIM_CPU *cpu = (SIM_CPU *) sc->p2; + + if (taddr == 0) + return NULL; + + return sim_core_trans_addr (sd, cpu, read_map, taddr); +} + +/* TODO: These functions are a big hack and assume that the host runtime has + type sizes and struct layouts that match the target. So the Linux emulation + probaly only really works in 32-bit runtimes. */ + +static void +translate_endian_h2t (void *addr, size_t size) +{ + unsigned int *p = (unsigned int *) addr; + int i; + + for (i = 0; i <= size - 4; i += 4,p++) + *p = H2T_4 (*p); + + if (i <= size - 2) + *((unsigned short *) p) = H2T_2 (*((unsigned short *) p)); +} + +static void +translate_endian_t2h (void *addr, size_t size) +{ + unsigned int *p = (unsigned int *) addr; + int i; + + for (i = 0; i <= size - 4; i += 4,p++) + *p = T2H_4 (*p); + + if (i <= size - 2) + *((unsigned short *) p) = T2H_2 (*((unsigned short *) p)); +} + /* Trap support. The result is the pc address to continue at. Preprocessing like saving the various registers has already been done. */ @@ -109,18 +180,11 @@ m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) host_callback *cb = STATE_CALLBACK (sd); if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) - { - /* The new pc is the trap vector entry. - We assume there's a branch there to some handler. - Use cr5 as EVB (EIT Vector Base) register. */ - /* USI new_pc = EIT_TRAP_BASE_ADDR + num * 4; */ - USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; - return new_pc; - } + goto case_default; switch (num) { - case TRAP_SYSCALL : + case TRAP_SYSCALL: { long result, result2; int errcode; @@ -139,6 +203,1110 @@ m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) break; } + case TRAP_LINUX_SYSCALL: + { + CB_SYSCALL s; + unsigned int func, arg1, arg2, arg3, arg4, arg5, arg6, arg7; + int result, result2, errcode; + + if (STATE_ENVIRONMENT (sd) != USER_ENVIRONMENT) + goto case_default; + + func = m32rbf_h_gr_get (current_cpu, 7); + arg1 = m32rbf_h_gr_get (current_cpu, 0); + arg2 = m32rbf_h_gr_get (current_cpu, 1); + arg3 = m32rbf_h_gr_get (current_cpu, 2); + arg4 = m32rbf_h_gr_get (current_cpu, 3); + arg5 = m32rbf_h_gr_get (current_cpu, 4); + arg6 = m32rbf_h_gr_get (current_cpu, 5); + arg7 = m32rbf_h_gr_get (current_cpu, 6); + + CB_SYSCALL_INIT (&s); + s.func = func; + s.arg1 = arg1; + s.arg2 = arg2; + s.arg3 = arg3; + s.arg4 = arg4; + s.arg5 = arg5; + s.arg6 = arg6; + s.arg7 = arg7; + + s.p1 = (PTR) sd; + s.p2 = (PTR) current_cpu; + s.read_mem = sim_syscall_read_mem; + s.write_mem = sim_syscall_write_mem; + + result = 0; + result2 = 0; + errcode = 0; + + switch (func) + { + case TARGET_LINUX_SYS_exit: + sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1); + break; + + case TARGET_LINUX_SYS_read: + result = read(arg1, t2h_addr(cb, &s, arg2), arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_write: + result = write(arg1, t2h_addr(cb, &s, arg2), arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_open: + result = open((char *) t2h_addr(cb, &s, arg1), arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_close: + result = close(arg1); + errcode = errno; + break; + + case TARGET_LINUX_SYS_creat: + result = creat((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_link: + result = link((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_unlink: + result = unlink((char *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_chdir: + result = chdir((char *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_time: + { + time_t t; + + if (arg1 == 0) + { + result = (int) time(NULL); + errcode = errno; + } + else + { + result = (int) time(&t); + errcode = errno; + + if (result != 0) + break; + + t = H2T_4 (t); + if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) != sizeof(t)) + { + result = -1; + errcode = EINVAL; + } + } + } + break; + + case TARGET_LINUX_SYS_mknod: + result = mknod((char *) t2h_addr(cb, &s, arg1), + (mode_t) arg2, (dev_t) arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_chmod: + result = chmod((char *) t2h_addr(cb, &s, arg1), (mode_t) arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_lchown32: + case TARGET_LINUX_SYS_lchown: + result = lchown((char *) t2h_addr(cb, &s, arg1), + (uid_t) arg2, (gid_t) arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_lseek: + result = (int) lseek(arg1, (off_t) arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getpid: + result = getpid(); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getuid32: + case TARGET_LINUX_SYS_getuid: + result = getuid(); + errcode = errno; + break; + + case TARGET_LINUX_SYS_utime: + { + struct utimbuf buf; + + if (arg2 == 0) + { + result = utime((char *) t2h_addr(cb, &s, arg1), NULL); + errcode = errno; + } + else + { + buf = *((struct utimbuf *) t2h_addr(cb, &s, arg2)); + translate_endian_t2h (&buf, sizeof(buf)); + result = utime((char *) t2h_addr(cb, &s, arg1), &buf); + errcode = errno; + } + } + break; + + case TARGET_LINUX_SYS_access: + result = access((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_ftime: + { + struct timeb t; + + result = ftime(&t); + errcode = errno; + + if (result != 0) + break; + + t.time = H2T_4 (t.time); + t.millitm = H2T_2 (t.millitm); + t.timezone = H2T_2 (t.timezone); + t.dstflag = H2T_2 (t.dstflag); + if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) + != sizeof(t)) + { + result = -1; + errcode = EINVAL; + } + } + + case TARGET_LINUX_SYS_sync: + sync(); + result = 0; + break; + + case TARGET_LINUX_SYS_rename: + result = rename((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_mkdir: + result = mkdir((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_rmdir: + result = rmdir((char *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_dup: + result = dup(arg1); + errcode = errno; + break; + + case TARGET_LINUX_SYS_brk: + result = brk((void *) arg1); + errcode = errno; + //result = arg1; + break; + + case TARGET_LINUX_SYS_getgid32: + case TARGET_LINUX_SYS_getgid: + result = getgid(); + errcode = errno; + break; + + case TARGET_LINUX_SYS_geteuid32: + case TARGET_LINUX_SYS_geteuid: + result = geteuid(); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getegid32: + case TARGET_LINUX_SYS_getegid: + result = getegid(); + errcode = errno; + break; + + case TARGET_LINUX_SYS_ioctl: + result = ioctl(arg1, arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_fcntl: + result = fcntl(arg1, arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_dup2: + result = dup2(arg1, arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getppid: + result = getppid(); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getpgrp: + result = getpgrp(); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getrlimit: + { + struct rlimit rlim; + + result = getrlimit(arg1, &rlim); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&rlim, sizeof(rlim)); + if ((s.write_mem) (cb, &s, arg2, (char *) &rlim, sizeof(rlim)) + != sizeof(rlim)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_getrusage: + { + struct rusage usage; + + result = getrusage(arg1, &usage); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&usage, sizeof(usage)); + if ((s.write_mem) (cb, &s, arg2, (char *) &usage, sizeof(usage)) + != sizeof(usage)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_gettimeofday: + { + struct timeval tv; + struct timezone tz; + + result = gettimeofday(&tv, &tz); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&tv, sizeof(tv)); + if ((s.write_mem) (cb, &s, arg1, (char *) &tv, sizeof(tv)) + != sizeof(tv)) + { + result = -1; + errcode = EINVAL; + } + + translate_endian_h2t (&tz, sizeof(tz)); + if ((s.write_mem) (cb, &s, arg2, (char *) &tz, sizeof(tz)) + != sizeof(tz)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_getgroups32: + case TARGET_LINUX_SYS_getgroups: + { + gid_t *list; + + if (arg1 > 0) + list = (gid_t *) malloc(arg1 * sizeof(gid_t)); + + result = getgroups(arg1, list); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (list, arg1 * sizeof(gid_t)); + if (arg1 > 0) + if ((s.write_mem) (cb, &s, arg2, (char *) list, arg1 * sizeof(gid_t)) + != arg1 * sizeof(gid_t)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_select: + { + int n; + fd_set readfds; + fd_set *treadfdsp; + fd_set *hreadfdsp; + fd_set writefds; + fd_set *twritefdsp; + fd_set *hwritefdsp; + fd_set exceptfds; + fd_set *texceptfdsp; + fd_set *hexceptfdsp; + struct timeval *ttimeoutp; + struct timeval timeout; + + n = arg1; + + treadfdsp = (fd_set *) arg2; + if (treadfdsp != NULL) + { + readfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) treadfdsp)); + translate_endian_t2h (&readfds, sizeof(readfds)); + hreadfdsp = &readfds; + } + else + hreadfdsp = NULL; + + twritefdsp = (fd_set *) arg3; + if (twritefdsp != NULL) + { + writefds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) twritefdsp)); + translate_endian_t2h (&writefds, sizeof(writefds)); + hwritefdsp = &writefds; + } + else + hwritefdsp = NULL; + + texceptfdsp = (fd_set *) arg4; + if (texceptfdsp != NULL) + { + exceptfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) texceptfdsp)); + translate_endian_t2h (&exceptfds, sizeof(exceptfds)); + hexceptfdsp = &exceptfds; + } + else + hexceptfdsp = NULL; + + ttimeoutp = (struct timeval *) arg5; + timeout = *((struct timeval *) t2h_addr(cb, &s, (unsigned int) ttimeoutp)); + translate_endian_t2h (&timeout, sizeof(timeout)); + + result = select(n, hreadfdsp, hwritefdsp, hexceptfdsp, &timeout); + errcode = errno; + + if (result != 0) + break; + + if (treadfdsp != NULL) + { + translate_endian_h2t (&readfds, sizeof(readfds)); + if ((s.write_mem) (cb, &s, (unsigned long) treadfdsp, + (char *) &readfds, sizeof(readfds)) != sizeof(readfds)) + { + result = -1; + errcode = EINVAL; + } + } + + if (twritefdsp != NULL) + { + translate_endian_h2t (&writefds, sizeof(writefds)); + if ((s.write_mem) (cb, &s, (unsigned long) twritefdsp, + (char *) &writefds, sizeof(writefds)) != sizeof(writefds)) + { + result = -1; + errcode = EINVAL; + } + } + + if (texceptfdsp != NULL) + { + translate_endian_h2t (&exceptfds, sizeof(exceptfds)); + if ((s.write_mem) (cb, &s, (unsigned long) texceptfdsp, + (char *) &exceptfds, sizeof(exceptfds)) != sizeof(exceptfds)) + { + result = -1; + errcode = EINVAL; + } + } + + translate_endian_h2t (&timeout, sizeof(timeout)); + if ((s.write_mem) (cb, &s, (unsigned long) ttimeoutp, + (char *) &timeout, sizeof(timeout)) != sizeof(timeout)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_symlink: + result = symlink((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_readlink: + result = readlink((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2), + arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_readdir: + result = (int) readdir((DIR *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + +#if 0 + case TARGET_LINUX_SYS_mmap: + { + result = (int) mmap((void *) t2h_addr(cb, &s, arg1), + arg2, arg3, arg4, arg5, arg6); + errcode = errno; + + if (errno == 0) + { + sim_core_attach (sd, NULL, + 0, access_read_write_exec, 0, + result, arg2, 0, NULL, NULL); + } + } + break; +#endif + case TARGET_LINUX_SYS_mmap2: + { + void *addr; + size_t len; + int prot, flags, fildes; + off_t off; + + addr = (void *) t2h_addr(cb, &s, arg1); + len = arg2; + prot = arg3; + flags = arg4; + fildes = arg5; + off = arg6 << 12; + + result = (int) mmap(addr, len, prot, flags, fildes, off); + errcode = errno; + if (result != -1) + { + char c; + if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0) + sim_core_attach (sd, NULL, + 0, access_read_write_exec, 0, + result, len, 0, NULL, NULL); + } + } + break; + + case TARGET_LINUX_SYS_mmap: + { + void *addr; + size_t len; + int prot, flags, fildes; + off_t off; + + addr = *((void **) t2h_addr(cb, &s, arg1)); + len = *((size_t *) t2h_addr(cb, &s, arg1 + 4)); + prot = *((int *) t2h_addr(cb, &s, arg1 + 8)); + flags = *((int *) t2h_addr(cb, &s, arg1 + 12)); + fildes = *((int *) t2h_addr(cb, &s, arg1 + 16)); + off = *((off_t *) t2h_addr(cb, &s, arg1 + 20)); + + addr = (void *) T2H_4 ((unsigned int) addr); + len = T2H_4 (len); + prot = T2H_4 (prot); + flags = T2H_4 (flags); + fildes = T2H_4 (fildes); + off = T2H_4 (off); + + //addr = (void *) t2h_addr(cb, &s, (unsigned int) addr); + result = (int) mmap(addr, len, prot, flags, fildes, off); + errcode = errno; + + //if (errno == 0) + if (result != -1) + { + char c; + if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0) + sim_core_attach (sd, NULL, + 0, access_read_write_exec, 0, + result, len, 0, NULL, NULL); + } + } + break; + + case TARGET_LINUX_SYS_munmap: + { + result = munmap((void *)arg1, arg2); + errcode = errno; + if (result != -1) + { + sim_core_detach (sd, NULL, 0, arg2, result); + } + } + break; + + case TARGET_LINUX_SYS_truncate: + result = truncate((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_ftruncate: + result = ftruncate(arg1, arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_fchmod: + result = fchmod(arg1, arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_fchown32: + case TARGET_LINUX_SYS_fchown: + result = fchown(arg1, arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_statfs: + { + struct statfs statbuf; + + result = statfs((char *) t2h_addr(cb, &s, arg1), &statbuf); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&statbuf, sizeof(statbuf)); + if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) + != sizeof(statbuf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_fstatfs: + { + struct statfs statbuf; + + result = fstatfs(arg1, &statbuf); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&statbuf, sizeof(statbuf)); + if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) + != sizeof(statbuf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_syslog: + result = syslog(arg1, (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_setitimer: + { + struct itimerval value, ovalue; + + value = *((struct itimerval *) t2h_addr(cb, &s, arg2)); + translate_endian_t2h (&value, sizeof(value)); + + if (arg2 == 0) + { + result = setitimer(arg1, &value, NULL); + errcode = errno; + } + else + { + result = setitimer(arg1, &value, &ovalue); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&ovalue, sizeof(ovalue)); + if ((s.write_mem) (cb, &s, arg3, (char *) &ovalue, sizeof(ovalue)) + != sizeof(ovalue)) + { + result = -1; + errcode = EINVAL; + } + } + } + break; + + case TARGET_LINUX_SYS_getitimer: + { + struct itimerval value; + + result = getitimer(arg1, &value); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&value, sizeof(value)); + if ((s.write_mem) (cb, &s, arg2, (char *) &value, sizeof(value)) + != sizeof(value)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_stat: + { + char *buf; + int buflen; + struct stat statbuf; + + result = stat((char *) t2h_addr(cb, &s, arg1), &statbuf); + errcode = errno; + if (result < 0) + break; + + buflen = cb_host_to_target_stat (cb, NULL, NULL); + buf = xmalloc (buflen); + if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) + { + /* The translation failed. This is due to an internal + host program error, not the target's fault. */ + free (buf); + result = -1; + errcode = ENOSYS; + break; + } + if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) + { + free (buf); + result = -1; + errcode = EINVAL; + break; + } + free (buf); + } + break; + + case TARGET_LINUX_SYS_lstat: + { + char *buf; + int buflen; + struct stat statbuf; + + result = lstat((char *) t2h_addr(cb, &s, arg1), &statbuf); + errcode = errno; + if (result < 0) + break; + + buflen = cb_host_to_target_stat (cb, NULL, NULL); + buf = xmalloc (buflen); + if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) + { + /* The translation failed. This is due to an internal + host program error, not the target's fault. */ + free (buf); + result = -1; + errcode = ENOSYS; + break; + } + if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) + { + free (buf); + result = -1; + errcode = EINVAL; + break; + } + free (buf); + } + break; + + case TARGET_LINUX_SYS_fstat: + { + char *buf; + int buflen; + struct stat statbuf; + + result = fstat(arg1, &statbuf); + errcode = errno; + if (result < 0) + break; + + buflen = cb_host_to_target_stat (cb, NULL, NULL); + buf = xmalloc (buflen); + if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) + { + /* The translation failed. This is due to an internal + host program error, not the target's fault. */ + free (buf); + result = -1; + errcode = ENOSYS; + break; + } + if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) + { + free (buf); + result = -1; + errcode = EINVAL; + break; + } + free (buf); + } + break; + + case TARGET_LINUX_SYS_sysinfo: + { + struct sysinfo info; + + result = sysinfo(&info); + errcode = errno; + + if (result != 0) + break; + + info.uptime = H2T_4 (info.uptime); + info.loads[0] = H2T_4 (info.loads[0]); + info.loads[1] = H2T_4 (info.loads[1]); + info.loads[2] = H2T_4 (info.loads[2]); + info.totalram = H2T_4 (info.totalram); + info.freeram = H2T_4 (info.freeram); + info.sharedram = H2T_4 (info.sharedram); + info.bufferram = H2T_4 (info.bufferram); + info.totalswap = H2T_4 (info.totalswap); + info.freeswap = H2T_4 (info.freeswap); + info.procs = H2T_2 (info.procs); +#if LINUX_VERSION_CODE >= 0x20400 + info.totalhigh = H2T_4 (info.totalhigh); + info.freehigh = H2T_4 (info.freehigh); + info.mem_unit = H2T_4 (info.mem_unit); +#endif + if ((s.write_mem) (cb, &s, arg1, (char *) &info, sizeof(info)) + != sizeof(info)) + { + result = -1; + errcode = EINVAL; + } + } + break; + +#if 0 + case TARGET_LINUX_SYS_ipc: + { + result = ipc(arg1, arg2, arg3, arg4, + (void *) t2h_addr(cb, &s, arg5), arg6); + errcode = errno; + } + break; +#endif + + case TARGET_LINUX_SYS_fsync: + result = fsync(arg1); + errcode = errno; + break; + + case TARGET_LINUX_SYS_uname: + /* utsname contains only arrays of char, so it is not necessary + to translate endian. */ + result = uname((struct utsname *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + + case TARGET_LINUX_SYS_adjtimex: + { + struct timex buf; + + result = adjtimex(&buf); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&buf, sizeof(buf)); + if ((s.write_mem) (cb, &s, arg1, (char *) &buf, sizeof(buf)) + != sizeof(buf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_mprotect: + result = mprotect((void *) arg1, arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_fchdir: + result = fchdir(arg1); + errcode = errno; + break; + + case TARGET_LINUX_SYS_setfsuid32: + case TARGET_LINUX_SYS_setfsuid: + result = setfsuid(arg1); + errcode = errno; + break; + + case TARGET_LINUX_SYS_setfsgid32: + case TARGET_LINUX_SYS_setfsgid: + result = setfsgid(arg1); + errcode = errno; + break; + +#if 0 + case TARGET_LINUX_SYS__llseek: + { + loff_t buf; + + result = _llseek(arg1, arg2, arg3, &buf, arg5); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&buf, sizeof(buf)); + if ((s.write_mem) (cb, &s, t2h_addr(cb, &s, arg4), + (char *) &buf, sizeof(buf)) != sizeof(buf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_getdents: + { + struct dirent dir; + + result = getdents(arg1, &dir, arg3); + errcode = errno; + + if (result != 0) + break; + + dir.d_ino = H2T_4 (dir.d_ino); + dir.d_off = H2T_4 (dir.d_off); + dir.d_reclen = H2T_2 (dir.d_reclen); + if ((s.write_mem) (cb, &s, arg2, (char *) &dir, sizeof(dir)) + != sizeof(dir)) + { + result = -1; + errcode = EINVAL; + } + } + break; +#endif + + case TARGET_LINUX_SYS_flock: + result = flock(arg1, arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_msync: + result = msync((void *) arg1, arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_readv: + { + struct iovec vector; + + vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); + translate_endian_t2h (&vector, sizeof(vector)); + + result = readv(arg1, &vector, arg3); + errcode = errno; + } + break; + + case TARGET_LINUX_SYS_writev: + { + struct iovec vector; + + vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); + translate_endian_t2h (&vector, sizeof(vector)); + + result = writev(arg1, &vector, arg3); + errcode = errno; + } + break; + + case TARGET_LINUX_SYS_fdatasync: + result = fdatasync(arg1); + errcode = errno; + break; + + case TARGET_LINUX_SYS_mlock: + result = mlock((void *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_munlock: + result = munlock((void *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_nanosleep: + { + struct timespec req, rem; + + req = *((struct timespec *) t2h_addr(cb, &s, arg2)); + translate_endian_t2h (&req, sizeof(req)); + + result = nanosleep(&req, &rem); + errcode = errno; + + if (result != 0) + break; + + translate_endian_h2t (&rem, sizeof(rem)); + if ((s.write_mem) (cb, &s, arg2, (char *) &rem, sizeof(rem)) + != sizeof(rem)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case TARGET_LINUX_SYS_mremap: /* FIXME */ + result = (int) mremap((void *) t2h_addr(cb, &s, arg1), arg2, arg3, arg4); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getresuid32: + case TARGET_LINUX_SYS_getresuid: + { + uid_t ruid, euid, suid; + + result = getresuid(&ruid, &euid, &suid); + errcode = errno; + + if (result != 0) + break; + + *((uid_t *) t2h_addr(cb, &s, arg1)) = H2T_4 (ruid); + *((uid_t *) t2h_addr(cb, &s, arg2)) = H2T_4 (euid); + *((uid_t *) t2h_addr(cb, &s, arg3)) = H2T_4 (suid); + } + break; + + case TARGET_LINUX_SYS_poll: + { + struct pollfd ufds; + + ufds = *((struct pollfd *) t2h_addr(cb, &s, arg1)); + ufds.fd = T2H_4 (ufds.fd); + ufds.events = T2H_2 (ufds.events); + ufds.revents = T2H_2 (ufds.revents); + + result = poll(&ufds, arg2, arg3); + errcode = errno; + } + break; + + case TARGET_LINUX_SYS_getresgid32: + case TARGET_LINUX_SYS_getresgid: + { + uid_t rgid, egid, sgid; + + result = getresgid(&rgid, &egid, &sgid); + errcode = errno; + + if (result != 0) + break; + + *((uid_t *) t2h_addr(cb, &s, arg1)) = H2T_4 (rgid); + *((uid_t *) t2h_addr(cb, &s, arg2)) = H2T_4 (egid); + *((uid_t *) t2h_addr(cb, &s, arg3)) = H2T_4 (sgid); + } + break; + + case TARGET_LINUX_SYS_pread: + result = pread(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); + errcode = errno; + break; + + case TARGET_LINUX_SYS_pwrite: + result = pwrite(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); + errcode = errno; + break; + + case TARGET_LINUX_SYS_chown32: + case TARGET_LINUX_SYS_chown: + result = chown((char *) t2h_addr(cb, &s, arg1), arg2, arg3); + errcode = errno; + break; + + case TARGET_LINUX_SYS_getcwd: + result = (int) getcwd((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case TARGET_LINUX_SYS_sendfile: + { + off_t offset; + + offset = *((off_t *) t2h_addr(cb, &s, arg3)); + offset = T2H_4 (offset); + + result = sendfile(arg1, arg2, &offset, arg3); + errcode = errno; + + if (result != 0) + break; + + *((off_t *) t2h_addr(cb, &s, arg3)) = H2T_4 (offset); + } + break; + + default: + result = -1; + errcode = ENOSYS; + break; + } + + if (result == -1) + m32rbf_h_gr_set (current_cpu, 0, -errcode); + else + m32rbf_h_gr_set (current_cpu, 0, result); + break; + } + case TRAP_BREAKPOINT: sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); @@ -148,11 +1316,14 @@ m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) /* Do nothing. */ break; - default : + case_default: + default: { + /* The new pc is the trap vector entry. + We assume there's a branch there to some handler. + Use cr5 as EVB (EIT Vector Base) register. */ /* USI new_pc = EIT_TRAP_BASE_ADDR + num * 4; */ - /* Use cr5 as EVB (EIT Vector Base) register. */ - USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; + USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; return new_pc; } } |