From 444cc5745cf01bb012a460d7eb7953c0fbf4e17b Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 19 Dec 2003 11:44:00 +0000 Subject: Add support for m32r-linux target, including a RELA ABI and PIC. --- sim/m32r/ChangeLog | 12 + sim/m32r/Makefile.in | 7 +- sim/m32r/configure | 16 + sim/m32r/configure.in | 14 + sim/m32r/sim-if.c | 7 + sim/m32r/sim-main.h | 4 + sim/m32r/syscall.h | 195 +++++++ sim/m32r/traps-linux.c | 1392 ++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 1645 insertions(+), 2 deletions(-) create mode 100644 sim/m32r/syscall.h create mode 100644 sim/m32r/traps-linux.c (limited to 'sim/m32r') diff --git a/sim/m32r/ChangeLog b/sim/m32r/ChangeLog index 409645242eb..92cbd04b90d 100644 --- a/sim/m32r/ChangeLog +++ b/sim/m32r/ChangeLog @@ -1,3 +1,15 @@ +2003-12-19 Kazuhiro Inaoka + + * configure.in: Changed for dummy simulator of m32r-linux. + * configure: Regenerate. + * Makefile.in: Added traps-linux.o for dummy simulator of m32r-linux. + * traps-linux.c: Added for dummy simulator of m32r-linux. + * syscall.h: Ditto. + * sim-if.c (sim_create_inferior): Changed to setup SP for dummy + simulator for m32r-linux. + * sim-main.h (M32R_DEFAULT_MEM_SIZE): Changed for dummy simulator of + m32r-linux. + 2003-12-11 Kazuhiro Inaoka * Makefile.in: Add support for new machine m32r2. diff --git a/sim/m32r/Makefile.in b/sim/m32r/Makefile.in index ee3f7e890cb..eb29ab188b9 100644 --- a/sim/m32r/Makefile.in +++ b/sim/m32r/Makefile.in @@ -23,6 +23,7 @@ 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@ CONFIG_DEVICES = dv-sockser.o CONFIG_DEVICES = @@ -40,7 +41,8 @@ SIM_OBJS = \ $(M32R_OBJS) \ $(M32RX_OBJS) \ $(M32R2_OBJS) \ - traps.o devices.o \ + $(TRAPS_OBJ) \ + devices.o \ $(CONFIG_DEVICES) # Extra headers included by sim-main.h. @@ -48,7 +50,7 @@ SIM_EXTRA_DEPS = \ $(CGEN_INCLUDE_DEPS) \ arch.h cpuall.h m32r-sim.h $(srcdir)/../../opcodes/m32r-desc.h -SIM_EXTRA_CFLAGS = +SIM_EXTRA_CFLAGS = @sim_extra_cflags@ SIM_RUN_OBJS = nrun.o SIM_EXTRA_CLEAN = m32r-clean @@ -65,6 +67,7 @@ sim-if.o: sim-if.c $(SIM_MAIN_DEPS) $(srcdir)/../common/sim-core.h arch.o: arch.c $(SIM_MAIN_DEPS) traps.o: traps.c targ-vals.h $(SIM_MAIN_DEPS) +traps-linux.o: traps.c syscall.h targ-vals.h $(SIM_MAIN_DEPS) devices.o: devices.c $(SIM_MAIN_DEPS) # M32R objs diff --git a/sim/m32r/configure b/sim/m32r/configure index 4a55bc182a8..6e8b0cd12e0 100755 --- a/sim/m32r/configure +++ b/sim/m32r/configure @@ -3848,6 +3848,20 @@ fi + 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 + + + + trap '' 1 2 15 @@ -4061,6 +4075,8 @@ s%@EXEEXT@%$EXEEXT%g s%@CGEN_MAINT@%$CGEN_MAINT%g s%@cgendir@%$cgendir%g s%@cgen@%$cgen%g +s%@traps_obj@%$traps_obj%g +s%@sim_extra_cflags@%$sim_extra_cflags%g CEOF EOF diff --git a/sim/m32r/configure.in b/sim/m32r/configure.in index f598f29f09b..12857b9a19b 100644 --- a/sim/m32r/configure.in +++ b/sim/m32r/configure.in @@ -14,4 +14,18 @@ SIM_AC_OPTION_ENVIRONMENT SIM_AC_OPTION_INLINE() SIM_AC_OPTION_CGEN_MAINT + 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 749c79e9998..f8bbece7b8e 100644 --- a/sim/m32r/sim-if.c +++ b/sim/m32r/sim-if.c @@ -214,6 +214,13 @@ sim_create_inferior (sd, abfd, argv, envp) 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 0 STATE_ARGV (sd) = sim_copy_argv (argv); STATE_ENVP (sd) = sim_copy_argv (envp); diff --git a/sim/m32r/sim-main.h b/sim/m32r/sim-main.h index becfb62841a..2cbb40b99b4 100644 --- a/sim/m32r/sim-main.h +++ b/sim/m32r/sim-main.h @@ -85,6 +85,10 @@ 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/syscall.h b/sim/m32r/syscall.h new file mode 100644 index 00000000000..7762aca7eab --- /dev/null +++ b/sim/m32r/syscall.h @@ -0,0 +1,195 @@ +/* + * This file contains the system call numbers. + */ + +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_lchown 16 +#define __NR_break 17 +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_umount2 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_oldolduname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_profil 98 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_olduname 109 +#define __NR_iopl 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_vm86old 113 +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_modify_ldt 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +#define __NR_vm86 166 +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread 180 +#define __NR_pwrite 181 +#define __NR_chown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_getpmsg 188 /* some people actually want streams */ +#define __NR_putpmsg 189 /* some people actually want streams */ +#define __NR_vfork 190 + diff --git a/sim/m32r/traps-linux.c b/sim/m32r/traps-linux.c new file mode 100644 index 00000000000..55a97a514d0 --- /dev/null +++ b/sim/m32r/traps-linux.c @@ -0,0 +1,1392 @@ +/* m32r exception, interrupt, and trap (EIT) support + Copyright (C) 1998, 2003 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 2, 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., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "syscall.h" +#include "targ-vals.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} + +/* Read/write functions for system call interface. */ + +static int +syscall_read_mem (host_callback *cb, struct cb_syscall *sc, + unsigned long taddr, char *buf, int bytes) +{ + SIM_DESC sd = (SIM_DESC) sc->p1; + SIM_CPU *cpu = (SIM_CPU *) sc->p2; + + return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes); +} + +static int +syscall_write_mem (host_callback *cb, struct cb_syscall *sc, + unsigned long taddr, const char *buf, int bytes) +{ + SIM_DESC sd = (SIM_DESC) sc->p1; + SIM_CPU *cpu = (SIM_CPU *) sc->p2; + + return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes); +} + +/* Translate target's address to host's address. */ + +static void * +t2h_addr (host_callback *cb, struct cb_syscall *sc, + unsigned long taddr) +{ + extern sim_core_trans_addr (SIM_DESC, sim_cpu *, unsigned, address_word); + 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); +} + +static unsigned int +conv_endian (unsigned int tvalue) +{ + unsigned int hvalue; + unsigned int t1, t2, t3, t4; + + if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) + { + t1 = tvalue & 0xff000000; + t2 = tvalue & 0x00ff0000; + t3 = tvalue & 0x0000ff00; + t4 = tvalue & 0x000000ff; + + hvalue = t1 >> 24; + hvalue += t2 >> 8; + hvalue += t3 << 8; + hvalue += t4 << 24; + } + else + hvalue = tvalue; + + return hvalue; +} + +static unsigned short +conv_endian16 (unsigned short tvalue) +{ + unsigned short hvalue; + unsigned short t1, t2; + + if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) + { + t1 = tvalue & 0xff00; + t2 = tvalue & 0x00ff; + + hvalue = t1 >> 8; + hvalue += t2 << 8; + } + else + hvalue = tvalue; + + return hvalue; +} + +static void +translate_endian(void *addr, size_t size) +{ + unsigned int *p = (unsigned int *) addr; + int i; + + for (i = 0; i <= size - 4; i += 4,p++) + *p = conv_endian(*p); + + if (i <= size - 2) + *((unsigned short *) p) = conv_endian16(*((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); + +#ifdef SIM_HAVE_BREAKPOINTS + /* Check for breakpoints "owned" by the simulator first, regardless + of --environment. */ + if (num == TRAP_BREAKPOINT) + { + /* First try sim-break.c. If it's a breakpoint the simulator "owns" + it doesn't return. Otherwise it returns and let's us try. */ + sim_handle_breakpoint (sd, current_cpu, pc); + /* Fall through. */ + } +#endif + + switch (num) + { + case TRAP_ELF_SYSCALL : + { + CB_SYSCALL s; + + CB_SYSCALL_INIT (&s); + s.func = m32rbf_h_gr_get (current_cpu, 0); + s.arg1 = m32rbf_h_gr_get (current_cpu, 1); + s.arg2 = m32rbf_h_gr_get (current_cpu, 2); + s.arg3 = m32rbf_h_gr_get (current_cpu, 3); + + if (s.func == TARGET_SYS_exit) + { + sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1); + } + + s.p1 = (PTR) sd; + s.p2 = (PTR) current_cpu; + s.read_mem = syscall_read_mem; + s.write_mem = syscall_write_mem; + cb_syscall (cb, &s); + m32rbf_h_gr_set (current_cpu, 2, s.errcode); + m32rbf_h_gr_set (current_cpu, 0, s.result); + m32rbf_h_gr_set (current_cpu, 1, s.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) == 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 = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; + return new_pc; + } + + 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.p1 = (PTR) sd; + s.p2 = (PTR) current_cpu; + s.read_mem = syscall_read_mem; + s.write_mem = syscall_write_mem; + + result = 0; + result2 = 0; + errcode = 0; + + switch (func) + { + case __NR_exit: + sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1); + break; + + case __NR_read: + result = read(arg1, t2h_addr(cb, &s, arg2), arg3); + errcode = errno; + break; + + case __NR_write: + result = write(arg1, t2h_addr(cb, &s, arg2), arg3); + errcode = errno; + break; + + case __NR_open: + result = open((char *) t2h_addr(cb, &s, arg1), arg2, arg3); + errcode = errno; + break; + + case __NR_close: + result = close(arg1); + errcode = errno; + break; + + case __NR_creat: + result = creat((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case __NR_link: + result = link((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case __NR_unlink: + result = unlink((char *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + + case __NR_chdir: + result = chdir((char *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + + case __NR_time: + { + time_t t; + + if (arg1 == 0) + { + result = (int) time(NULL); + errcode = errno; + } + else + { + result = (int) time(&t); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &t, sizeof(t)); + if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) != sizeof(t)) + { + result = -1; + errcode = EINVAL; + } + } + } + break; + + case __NR_mknod: + result = mknod((char *) t2h_addr(cb, &s, arg1), + (mode_t) arg2, (dev_t) arg3); + errcode = errno; + break; + + case __NR_chmod: + result = chmod((char *) t2h_addr(cb, &s, arg1), (mode_t) arg2); + errcode = errno; + break; + + case __NR_lchown: + result = lchown((char *) t2h_addr(cb, &s, arg1), + (uid_t) arg2, (gid_t) arg3); + errcode = errno; + break; + + case __NR_lseek: + result = (int) lseek(arg1, (off_t) arg2, arg3); + errcode = errno; + break; + + case __NR_getpid: + result = getpid(); + errcode = errno; + break; + + case __NR_getuid: + result = getuid(); + errcode = errno; + break; + + case __NR_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((void *) &buf, sizeof(buf)); + result = utime((char *) t2h_addr(cb, &s, arg1), &buf); + errcode = errno; + } + } + break; + + case __NR_access: + result = access((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case __NR_ftime: + { + struct timeb t; + + result = ftime(&t); + errcode = errno; + + if (result != 0) + break; + + t.time = conv_endian(t.time); + t.millitm = conv_endian16(t.millitm); + t.timezone = conv_endian16(t.timezone); + t.dstflag = conv_endian16(t.dstflag); + if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) + != sizeof(t)) + { + result = -1; + errcode = EINVAL; + } + } + + case __NR_sync: + sync(); + result = 0; + break; + + case __NR_rename: + result = rename((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case __NR_mkdir: + result = mkdir((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case __NR_rmdir: + result = rmdir((char *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + + case __NR_dup: + result = dup(arg1); + errcode = errno; + break; + + case __NR_brk: + result = brk((void *) arg1); + errcode = errno; + //result = arg1; + break; + + case __NR_getgid: + result = getgid(); + errcode = errno; + break; + + case __NR_geteuid: + result = geteuid(); + errcode = errno; + break; + + case __NR_getegid: + result = getegid(); + errcode = errno; + break; + + case __NR_ioctl: + result = ioctl(arg1, arg2, arg3); + errcode = errno; + break; + + case __NR_fcntl: + result = fcntl(arg1, arg2, arg3); + errcode = errno; + break; + + case __NR_ustat: + { + struct ustat ubuf; + + result = ustat(arg1, &ubuf); + errcode = errno; + + if (result != 0) + break; + + ubuf.f_tfree = conv_endian(ubuf.f_tfree); + ubuf.f_tinode = conv_endian(ubuf.f_tinode); + if ((s.write_mem) (cb, &s, arg2, (char *) &ubuf, sizeof(ubuf)) + != sizeof(ubuf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_dup2: + result = dup2(arg1, arg2); + errcode = errno; + break; + + case __NR_getppid: + result = getppid(); + errcode = errno; + break; + + case __NR_getpgrp: + result = getpgrp(); + errcode = errno; + break; + + case __NR_getrlimit: + { + struct rlimit rlim; + + result = getrlimit(arg1, &rlim); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &rlim, sizeof(rlim)); + if ((s.write_mem) (cb, &s, arg2, (char *) &rlim, sizeof(rlim)) + != sizeof(rlim)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_getrusage: + { + struct rusage usage; + + result = getrusage(arg1, &usage); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &usage, sizeof(usage)); + if ((s.write_mem) (cb, &s, arg2, (char *) &usage, sizeof(usage)) + != sizeof(usage)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_gettimeofday: + { + struct timeval tv; + struct timezone tz; + + result = gettimeofday(&tv, &tz); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &tv, sizeof(tv)); + if ((s.write_mem) (cb, &s, arg1, (char *) &tv, sizeof(tv)) + != sizeof(tv)) + { + result = -1; + errcode = EINVAL; + } + + translate_endian((void *) &tz, sizeof(tz)); + if ((s.write_mem) (cb, &s, arg2, (char *) &tz, sizeof(tz)) + != sizeof(tz)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_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((void *) 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 __NR_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((void *) &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((void *) &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((void *) &exceptfds, sizeof(exceptfds)); + hexceptfdsp = &exceptfds; + } + else + hexceptfdsp = NULL; + + ttimeoutp = (struct timeval *) arg5; + timeout = *((struct timeval *) t2h_addr(cb, &s, (unsigned int) ttimeoutp)); + translate_endian((void *) &timeout, sizeof(timeout)); + + result = select(n, hreadfdsp, hwritefdsp, hexceptfdsp, &timeout); + errcode = errno; + + if (result != 0) + break; + + if (treadfdsp != NULL) + { + translate_endian((void *) &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((void *) &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((void *) &exceptfds, sizeof(exceptfds)); + if ((s.write_mem) (cb, &s, (unsigned long) texceptfdsp, + (char *) &exceptfds, sizeof(exceptfds)) != sizeof(exceptfds)) + { + result = -1; + errcode = EINVAL; + } + } + + translate_endian((void *) &timeout, sizeof(timeout)); + if ((s.write_mem) (cb, &s, (unsigned long) ttimeoutp, + (char *) &timeout, sizeof(timeout)) != sizeof(timeout)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_symlink: + result = symlink((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case __NR_readlink: + result = readlink((char *) t2h_addr(cb, &s, arg1), + (char *) t2h_addr(cb, &s, arg2), + arg3); + errcode = errno; + break; + + case __NR_readdir: + result = (int) readdir((DIR *) t2h_addr(cb, &s, arg1)); + errcode = errno; + break; + +#if 0 + case __NR_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 __NR_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 *) conv_endian((unsigned int) addr); + len = conv_endian(len); + prot = conv_endian(prot); + flags = conv_endian(flags); + fildes = conv_endian(fildes); + off = conv_endian(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 __NR_munmap: + { + result = munmap((void *)arg1, arg2); + errcode = errno; + if (result != -1) + { + sim_core_detach (sd, NULL, 0, arg2, result); + } + } + break; + + case __NR_truncate: + result = truncate((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case __NR_ftruncate: + result = ftruncate(arg1, arg2); + errcode = errno; + break; + + case __NR_fchmod: + result = fchmod(arg1, arg2); + errcode = errno; + break; + + case __NR_fchown: + result = fchown(arg1, arg2, arg3); + errcode = errno; + break; + + case __NR_statfs: + { + struct statfs statbuf; + + result = statfs((char *) t2h_addr(cb, &s, arg1), &statbuf); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &statbuf, sizeof(statbuf)); + if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) + != sizeof(statbuf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_fstatfs: + { + struct statfs statbuf; + + result = fstatfs(arg1, &statbuf); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &statbuf, sizeof(statbuf)); + if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) + != sizeof(statbuf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_syslog: + result = syslog(arg1, (char *) t2h_addr(cb, &s, arg2)); + errcode = errno; + break; + + case __NR_setitimer: + { + struct itimerval value, ovalue; + + value = *((struct itimerval *) t2h_addr(cb, &s, arg2)); + translate_endian((void *) &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((void *) &ovalue, sizeof(ovalue)); + if ((s.write_mem) (cb, &s, arg3, (char *) &ovalue, sizeof(ovalue)) + != sizeof(ovalue)) + { + result = -1; + errcode = EINVAL; + } + } + } + break; + + case __NR_getitimer: + { + struct itimerval value; + + result = getitimer(arg1, &value); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &value, sizeof(value)); + if ((s.write_mem) (cb, &s, arg2, (char *) &value, sizeof(value)) + != sizeof(value)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_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 __NR_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 __NR_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 __NR_sysinfo: + { + struct sysinfo info; + + result = sysinfo(&info); + errcode = errno; + + if (result != 0) + break; + + info.uptime = conv_endian(info.uptime); + info.loads[0] = conv_endian(info.loads[0]); + info.loads[1] = conv_endian(info.loads[1]); + info.loads[2] = conv_endian(info.loads[2]); + info.totalram = conv_endian(info.totalram); + info.freeram = conv_endian(info.freeram); + info.sharedram = conv_endian(info.sharedram); + info.bufferram = conv_endian(info.bufferram); + info.totalswap = conv_endian(info.totalswap); + info.freeswap = conv_endian(info.freeswap); + info.procs = conv_endian16(info.procs); +#if LINUX_VERSION_CODE >= 0x20400 + info.totalhigh = conv_endian(info.totalhigh); + info.freehigh = conv_endian(info.freehigh); + info.mem_unit = conv_endian(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 __NR_ipc: + { + result = ipc(arg1, arg2, arg3, arg4, + (void *) t2h_addr(cb, &s, arg5), arg6); + errcode = errno; + } + break; +#endif + + case __NR_fsync: + result = fsync(arg1); + errcode = errno; + break; + + case __NR_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 __NR_adjtimex: + { + struct timex buf; + + result = adjtimex(&buf); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &buf, sizeof(buf)); + if ((s.write_mem) (cb, &s, arg1, (char *) &buf, sizeof(buf)) + != sizeof(buf)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_mprotect: + result = mprotect((void *) arg1, arg2, arg3); + errcode = errno; + break; + + case __NR_get_kernel_syms: + { + struct kernel_sym table; + + result = get_kernel_syms(&table); + errcode = errno; + + if (result != 0) + break; + + table.value = conv_endian(table.value); + if ((s.write_mem) (cb, &s, arg1, (char *) &table, sizeof(table)) + != sizeof(table)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_fchdir: + result = fchdir(arg1); + errcode = errno; + break; + + case __NR_setfsuid: + result = setfsuid(arg1); + errcode = errno; + break; + + case __NR_setfsgid: + result = setfsgid(arg1); + errcode = errno; + break; + +#if 0 + case __NR__llseek: + { + loff_t buf; + + result = _llseek(arg1, arg2, arg3, &buf, arg5); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &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 __NR_getdents: + { + struct dirent dir; + + result = getdents(arg1, &dir, arg3); + errcode = errno; + + if (result != 0) + break; + + dir.d_ino = conv_endian(dir.d_ino); + dir.d_off = conv_endian(dir.d_off); + dir.d_reclen = conv_endian16(dir.d_reclen); + if ((s.write_mem) (cb, &s, arg2, (char *) &dir, sizeof(dir)) + != sizeof(dir)) + { + result = -1; + errcode = EINVAL; + } + } + break; +#endif + + case __NR_flock: + result = flock(arg1, arg2); + errcode = errno; + break; + + case __NR_msync: + result = msync((void *) arg1, arg2, arg3); + errcode = errno; + break; + + case __NR_readv: + { + struct iovec vector; + + vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); + translate_endian((void *) &vector, sizeof(vector)); + + result = readv(arg1, &vector, arg3); + errcode = errno; + } + break; + + case __NR_writev: + { + struct iovec vector; + + vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); + translate_endian((void *) &vector, sizeof(vector)); + + result = writev(arg1, &vector, arg3); + errcode = errno; + } + break; + + case __NR_fdatasync: + result = fdatasync(arg1); + errcode = errno; + break; + + case __NR_mlock: + result = mlock((void *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case __NR_munlock: + result = munlock((void *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case __NR_nanosleep: + { + struct timespec req, rem; + + req = *((struct timespec *) t2h_addr(cb, &s, arg2)); + translate_endian((void *) &req, sizeof(req)); + + result = nanosleep(&req, &rem); + errcode = errno; + + if (result != 0) + break; + + translate_endian((void *) &rem, sizeof(rem)); + if ((s.write_mem) (cb, &s, arg2, (char *) &rem, sizeof(rem)) + != sizeof(rem)) + { + result = -1; + errcode = EINVAL; + } + } + break; + + case __NR_mremap: /* FIXME */ + result = (int) mremap((void *) t2h_addr(cb, &s, arg1), arg2, arg3, arg4); + errcode = errno; + break; + + case __NR_getresuid: + { + uid_t ruid, euid, suid; + + result = getresuid(&ruid, &euid, &suid); + errcode = errno; + + if (result != 0) + break; + + *((uid_t *) t2h_addr(cb, &s, arg1)) = conv_endian(ruid); + *((uid_t *) t2h_addr(cb, &s, arg2)) = conv_endian(euid); + *((uid_t *) t2h_addr(cb, &s, arg3)) = conv_endian(suid); + } + break; + + case __NR_poll: + { + struct pollfd ufds; + + ufds = *((struct pollfd *) t2h_addr(cb, &s, arg1)); + ufds.fd = conv_endian(ufds.fd); + ufds.events = conv_endian16(ufds.events); + ufds.revents = conv_endian16(ufds.revents); + + result = poll(&ufds, arg2, arg3); + errcode = errno; + } + break; + + case __NR_getresgid: + { + uid_t rgid, egid, sgid; + + result = getresgid(&rgid, &egid, &sgid); + errcode = errno; + + if (result != 0) + break; + + *((uid_t *) t2h_addr(cb, &s, arg1)) = conv_endian(rgid); + *((uid_t *) t2h_addr(cb, &s, arg2)) = conv_endian(egid); + *((uid_t *) t2h_addr(cb, &s, arg3)) = conv_endian(sgid); + } + break; + + case __NR_pread: + result = pread(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); + errcode = errno; + break; + + case __NR_pwrite: + result = pwrite(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); + errcode = errno; + break; + + case __NR_chown: + result = chown((char *) t2h_addr(cb, &s, arg1), arg2, arg3); + errcode = errno; + break; + + case __NR_getcwd: + result = (int) getcwd((char *) t2h_addr(cb, &s, arg1), arg2); + errcode = errno; + break; + + case __NR_sendfile: + { + off_t offset; + + offset = *((off_t *) t2h_addr(cb, &s, arg3)); + offset = conv_endian(offset); + + result = sendfile(arg1, arg2, &offset, arg3); + errcode = errno; + + if (result != 0) + break; + + *((off_t *) t2h_addr(cb, &s, arg3)) = conv_endian(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; + + 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; +} -- cgit v1.2.1