diff options
Diffstat (limited to 'sim')
-rw-r--r-- | sim/ChangeLog | 5 | ||||
-rw-r--r-- | sim/arm/ChangeLog | 11 | ||||
-rw-r--r-- | sim/arm/Makefile.in | 2 | ||||
-rw-r--r-- | sim/arm/armos.c | 41 | ||||
-rw-r--r-- | sim/common/ChangeLog | 8 | ||||
-rw-r--r-- | sim/common/Makefile.in | 1 | ||||
-rw-r--r-- | sim/common/sim-core.c | 19 | ||||
-rwxr-xr-x | sim/configure | 8 | ||||
-rw-r--r-- | sim/configure.in | 2 | ||||
-rw-r--r-- | sim/h8300/ChangeLog | 9 | ||||
-rw-r--r-- | sim/h8300/compile.c | 2 | ||||
-rw-r--r-- | sim/h8300/sim-main.h | 2 | ||||
-rw-r--r-- | sim/m32r/ChangeLog | 12 | ||||
-rw-r--r-- | sim/m32r/Makefile.in | 7 | ||||
-rwxr-xr-x | sim/m32r/configure | 16 | ||||
-rw-r--r-- | sim/m32r/configure.in | 14 | ||||
-rw-r--r-- | sim/m32r/sim-if.c | 7 | ||||
-rw-r--r-- | sim/m32r/sim-main.h | 4 | ||||
-rw-r--r-- | sim/m32r/syscall.h | 195 | ||||
-rw-r--r-- | sim/m32r/traps-linux.c | 1392 | ||||
-rw-r--r-- | sim/mips/ChangeLog | 8 | ||||
-rw-r--r-- | sim/mips/mips.igen | 72 | ||||
-rw-r--r-- | sim/sh/ChangeLog | 34 | ||||
-rw-r--r-- | sim/sh/gencode.c | 892 | ||||
-rw-r--r-- | sim/sh/interp.c | 164 | ||||
-rw-r--r-- | sim/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | sim/testsuite/lib/sim-defs.exp | 2 | ||||
-rw-r--r-- | sim/v850/ChangeLog | 4 | ||||
-rw-r--r-- | sim/v850/simops.c | 2 |
29 files changed, 2585 insertions, 359 deletions
diff --git a/sim/ChangeLog b/sim/ChangeLog index 97fecf2e10d..dec01dabdfe 100644 --- a/sim/ChangeLog +++ b/sim/ChangeLog @@ -1,3 +1,8 @@ +2004-01-26 Chris Demetriou <cgd@broadcom.com> + + * configure.in (mips*-*-*): Configure in testsuite. + * configure: Regenerate. + 2003-10-08 Dave Brolley <brolley@redhat.com> * configure.in: Move frv handling to alphabetically correct placement. diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog index a3cd7f2248a..6447e219679 100644 --- a/sim/arm/ChangeLog +++ b/sim/arm/ChangeLog @@ -1,3 +1,14 @@ +2003-12-29 Mark Mitchell <mark@codesourcery.com> + + * armos.c (fcntl.h): Do not include it. + (O_RDONLY): Do not define. + (O_WRONLY): Likewise. + (O_RDWR): Likewise. + (targ-vals.h): Include it. + (translate_open_mode): Use TARGET_O_* instead of O_*. + (SWIopen): Likewise. + * Makefile.in (armos.o): Depend on targ-vals.h. + 2003-04-13 Nick Clifton <nickc@redhat.com> * armvirt.c (GetWord): Only call XScale_check_memacc if in XScale diff --git a/sim/arm/Makefile.in b/sim/arm/Makefile.in index 7def0f967bb..1214a4a335c 100644 --- a/sim/arm/Makefile.in +++ b/sim/arm/Makefile.in @@ -28,7 +28,7 @@ SIM_OBJS = armemu26.o armemu32.o arminit.o armos.o armsupp.o \ ## COMMON_POST_CONFIG_FRAG -armos.o: armos.c armdefs.h armos.h armfpe.h +armos.o: armos.c armdefs.h armos.h armfpe.h targ-vals.h armcopro.o: armcopro.c armdefs.h maverick.o: maverick.c armdefs.h diff --git a/sim/arm/armos.c b/sim/arm/armos.c index 613d07eda17..5c26b2b0b9a 100644 --- a/sim/arm/armos.c +++ b/sim/arm/armos.c @@ -28,19 +28,10 @@ #include <time.h> #include <errno.h> #include <string.h> -#include <fcntl.h> +#include "targ-vals.h" -#ifndef O_RDONLY -#define O_RDONLY 0 -#endif -#ifndef O_WRONLY -#define O_WRONLY 1 -#endif -#ifndef O_RDWR -#define O_RDWR 2 -#endif -#ifndef O_BINARY -#define O_BINARY 0 +#ifndef TARGET_O_BINARY +#define TARGET_O_BINARY 0 #endif #ifdef __STDC__ @@ -260,18 +251,18 @@ ARMword ARMul_OSLastErrorP (ARMul_State * state) static int translate_open_mode[] = { - O_RDONLY, /* "r" */ - O_RDONLY + O_BINARY, /* "rb" */ - O_RDWR, /* "r+" */ - O_RDWR + O_BINARY, /* "r+b" */ - O_WRONLY + O_CREAT + O_TRUNC, /* "w" */ - O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */ - O_RDWR + O_CREAT + O_TRUNC, /* "w+" */ - O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */ - O_WRONLY + O_APPEND + O_CREAT, /* "a" */ - O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */ - O_RDWR + O_APPEND + O_CREAT, /* "a+" */ - O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */ + TARGET_O_RDONLY, /* "r" */ + TARGET_O_RDONLY + TARGET_O_BINARY, /* "rb" */ + TARGET_O_RDWR, /* "r+" */ + TARGET_O_RDWR + TARGET_O_BINARY, /* "r+b" */ + TARGET_O_WRONLY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w" */ + TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "wb" */ + TARGET_O_RDWR + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w+" */ + TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w+b" */ + TARGET_O_WRONLY + TARGET_O_APPEND + TARGET_O_CREAT, /* "a" */ + TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT, /* "ab" */ + TARGET_O_RDWR + TARGET_O_APPEND + TARGET_O_CREAT, /* "a+" */ + TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT /* "a+b" */ }; static void @@ -325,7 +316,7 @@ SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags) /* Filename ":tt" is special: it denotes stdin/out. */ if (strcmp (dummy, ":tt") == 0) { - if (flags == O_RDONLY) /* opening tty "r" */ + if (flags == TARGET_O_RDONLY) /* opening tty "r" */ state->Reg[0] = 0; /* stdin */ else state->Reg[0] = 1; /* stdout */ diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index f95071fdf5a..d287cdfe245 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,11 @@ +2004-01-16 Ben Elliston <bje@wasabisystems.com> + + * Makefile.in (clean): Remove rm -f $(ALL), as $(ALL) is empty. + +2003-12-19 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com> + + * sim-core.c (sim_core_trans_addr): Added for m32r-linux-run. + 2003-11-22 Kazu Hirata <kazu@cs.umass.edu> * sim-options.c (standard_options): Fix the names of H8 diff --git a/sim/common/Makefile.in b/sim/common/Makefile.in index d021566ea7c..915598c9c43 100644 --- a/sim/common/Makefile.in +++ b/sim/common/Makefile.in @@ -105,7 +105,6 @@ TAGS: force clean: rm -f *.[oa] *~ core - rm -f $(ALL) distclean mostlyclean maintainer-clean realclean: clean rm -f TAGS diff --git a/sim/common/sim-core.c b/sim/common/sim-core.c index 586c25e4fa7..65c28d733b1 100644 --- a/sim/common/sim-core.c +++ b/sim/common/sim-core.c @@ -801,6 +801,25 @@ sim_core_xor_write_buffer (SIM_DESC sd, } #endif +#if EXTERN_SIM_CORE_P +void * +sim_core_trans_addr (SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + address_word addr) +{ + sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common); + sim_core_mapping *mapping = + sim_core_find_mapping (core, map, + addr, /*nr-bytes*/1, + write_transfer, + 0 /*dont-abort*/, NULL, NULL_CIA); + if (mapping == NULL) + return NULL; + return sim_core_translate(mapping, addr); +} +#endif + /* define the read/write 1/2/4/8/16/word functions */ diff --git a/sim/configure b/sim/configure index b342d3917fa..d09adab68fc 100755 --- a/sim/configure +++ b/sim/configure @@ -1426,11 +1426,11 @@ case "${target}" in # OBSOLETE extra_subdirs="${extra_subdirs} igen" # OBSOLETE ;; # OBSOLETE fr30-*-*) sim_target=fr30 ;; - h8300*-*-*) - sim_target=h8300 + frv-*-*) sim_target=frv extra_subdirs="${extra_subdirs} testsuite" ;; - frv-*-*) sim_target=frv + h8300*-*-*) + sim_target=h8300 extra_subdirs="${extra_subdirs} testsuite" ;; h8500-*-*) sim_target=h8500 ;; @@ -1442,7 +1442,7 @@ case "${target}" in # The MIPS simulator can only be compiled by gcc. sim_target=mips only_if_gcc=yes - extra_subdirs="${extra_subdirs} igen" + extra_subdirs="${extra_subdirs} igen testsuite" ;; mn10300*-*-*) # The mn10300 simulator can only be compiled by gcc. diff --git a/sim/configure.in b/sim/configure.in index d9924700412..c66a41384ee 100644 --- a/sim/configure.in +++ b/sim/configure.in @@ -81,7 +81,7 @@ case "${target}" in # The MIPS simulator can only be compiled by gcc. sim_target=mips only_if_gcc=yes - extra_subdirs="${extra_subdirs} igen" + extra_subdirs="${extra_subdirs} igen testsuite" ;; mn10300*-*-*) # The mn10300 simulator can only be compiled by gcc. diff --git a/sim/h8300/ChangeLog b/sim/h8300/ChangeLog index 7aa1a75af30..9938196d7b6 100644 --- a/sim/h8300/ChangeLog +++ b/sim/h8300/ChangeLog @@ -1,3 +1,12 @@ +2004-01-05 Michael Snyder <msnyder@redhat.com> + + * compile.c (sim_load): Don't pass a type to bfd_openr. + +2003-12-16 Michael Snyder <msnyder@redhat.com> + + Patch submitted by Anil Paranjape <AnilP1@KPITCummins.com> + * sim-main.h (H8300H_MSIZE): Increase from 18 bits to 24 bits. + 2003-12-11 Dhananjay Deshpande <dhananjayd@kpitcummins.com> * compile.c (set_h8300h): Initialize globals to zero. diff --git a/sim/h8300/compile.c b/sim/h8300/compile.c index 462240ce145..ec5f974c7b3 100644 --- a/sim/h8300/compile.c +++ b/sim/h8300/compile.c @@ -5052,7 +5052,7 @@ sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty) if (abfd != NULL) prog_bfd = abfd; else - prog_bfd = bfd_openr (prog, "coff-h8300"); + prog_bfd = bfd_openr (prog, NULL); if (prog_bfd != NULL) { /* Set the cpu type. We ignore failure from bfd_check_format diff --git a/sim/h8300/sim-main.h b/sim/h8300/sim-main.h index 284a5586d16..65cc9995dc9 100644 --- a/sim/h8300/sim-main.h +++ b/sim/h8300/sim-main.h @@ -27,7 +27,7 @@ /* avolkov: Next 2 macros are ugly for any workstation, but while they're work. Memory size MUST be configurable. */ -#define H8300H_MSIZE (1 << 18) +#define H8300H_MSIZE (1 << 24) #define H8300S_MSIZE (1 << 24) #define CSIZE 1024 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 <inaoka.kazuhiro@renesas.com> + + * 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 <inaoka.kazuhiro@renesas.com> * 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 <dirent.h> +#include <errno.h> +#include <fcntl.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/module.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); +} + +/* 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; +} diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index e5b5216f0d1..fab4c6e2969 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,11 @@ +2004-01-19 Chris Demetriou <cgd@broadcom.com> + + * mips.igen (check_mf_cycles, check_mt_hilo, check_mf_hilo) + (check_mult_hilo): Improve comments. + (check_div_hilo): Likewise. Also, fork off a new version + to handle mips32/mips64 (since there are no hazards to check + in MIPS32/MIPS64). + 2003-06-17 Richard Sandiford <rsandifo@redhat.com> * mips.igen (do_dmultx): Fix check for negative operands. diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen index 358c8ab1750..cfc2d6da739 100644 --- a/sim/mips/mips.igen +++ b/sim/mips/mips.igen @@ -218,18 +218,39 @@ } -// Helper: +// Helpers: // // Check that an access to a HI/LO register meets timing requirements // -// The following requirements exist: +// In all MIPS ISAs, // -// - A MT {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read -// - A OP {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read -// - A MF {HI,LO} read was not corrupted by a preceeding MT{LO,HI} update -// corruption occures when MT{LO,HI} is preceeded by a OP {HI,LO}. +// OP {HI and LO} followed by MT{LO or HI} (and not MT{HI or LO}) +// makes subsequent MF{HI or LO} UNPREDICTABLE. (1) +// +// The following restrictions exist for MIPS I - MIPS III: +// +// MF{HI or LO} followed by MT{HI or LO} w/ less than 2 instructions +// in between makes MF UNPREDICTABLE. (2) +// +// MF{HI or LO} followed by OP {HI and LO} w/ less than 2 instructions +// in between makes MF UNPREDICTABLE. (3) +// +// On the r3900, restriction (2) is not present, and restriction (3) is not +// present for multiplication. +// +// For now this code is paranoid. Historically the simulator +// enforced restrictions (2) and (3) for more ISAs and CPU types than +// necessary. Unfortunately, at least some MIPS IV and later parts' +// documentation describes them as having these hazards (e.g. vr5000), +// so they can't be removed for at leats MIPS IV. MIPS V hasn't been +// checked (since there are no known hardware implementations). +// + +// check_mf_cycles: +// +// Helper used by check_mt_hilo, check_mult_hilo, and check_div_hilo +// to check for restrictions (2) and (3) above. // - :function:::int:check_mf_cycles:hilo_history *history, signed64 time, const char *new { if (history->mf.timestamp + 3 > time) @@ -243,6 +264,12 @@ return 1; } + +// check_mt_hilo: +// +// Check for restriction (2) above (for ISAs/processors that have it), +// and record timestamps for restriction (1) above. +// :function:::int:check_mt_hilo:hilo_history *history *mipsI: *mipsII: @@ -271,6 +298,11 @@ } +// check_mf_hilo: +// +// Check for restriction (1) above, and record timestamps for +// restriction (2) and (3) above. +// :function:::int:check_mf_hilo:hilo_history *history, hilo_history *peer *mipsI: *mipsII: @@ -309,6 +341,11 @@ +// check_mult_hilo: +// +// Check for restriction (3) above (for ISAs/processors that have it) +// for MULT ops, and record timestamps for restriction (1) above. +// :function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo *mipsI: *mipsII: @@ -328,8 +365,6 @@ return ok; } -// The r3900 mult and multu insns _can_ be exectuted immediatly after -// a mf{hi,lo} :function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo *mips32: *mips64: @@ -345,14 +380,17 @@ } +// check_div_hilo: +// +// Check for restriction (3) above (for ISAs/processors that have it) +// for DIV ops, and record timestamps for restriction (1) above. +// :function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo *mipsI: *mipsII: *mipsIII: *mipsIV: *mipsV: -*mips32: -*mips64: *vr4100: *vr5000: *r3900: @@ -367,6 +405,18 @@ return ok; } +:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo +*mips32: +*mips64: +{ + signed64 time = sim_events_time (SD); + hi->op.timestamp = time; + lo->op.timestamp = time; + hi->op.cia = CIA; + lo->op.cia = CIA; + return 1; +} + // Helper: // diff --git a/sim/sh/ChangeLog b/sim/sh/ChangeLog index faa6ebc4f9a..9659f953aa1 100644 --- a/sim/sh/ChangeLog +++ b/sim/sh/ChangeLog @@ -1,3 +1,37 @@ +2004-01-07 Michael Snyder <msnyder@redhat.com> + + * gencode.c: Whitespace cleanup. + * interp.c: Ditto. + + * gencode.c: Replace 'Hitachi' with 'Renesas'. + (op tab): Add new instructions for sh4a, DBR, SBR. + (expand_opcode): Add handling for new movxy combinations. + (gensym_caselist): Ditto. + (expand_ppi_movxy): Remove movx/movy expansions, + now handled in expand_opcode. + (gensym): Add some helpful macros. + (expand_ppi_code): Flatten loop for simplicity, tweak for 12-bit + instead of 8-bit table (some insns are ambiguous to 8 bits). + (ppi_gensim, main): Generate 12-bit instead of 8-bit ppi table. + + * interp.c: Replace 'Hitachi' with 'Renesas'. + (union saved_state_type): Add dbr, sgr, ldst. + (get_loop_bounds_ext): New function. + (init_dsp): Add bfd_mach_sh4al_dsp. + (sim_resume): Handle extended loop bounds. + +2003-12-18 Michael Snyder <msnyder@redhat.com> + + * gencode.c (expand_opcode): Simplify and reorganize. + Eliminate "shift" parameter. Eliminate "4 bits at a time" + assumption. Flatten switch statement to a single level. + Add "eeee" token for even-numbered registers. + (bton): Delete. + (fsca): Use "eeee" token. + (ppi_moves): Rename to "expand_ppi_movxy". Do the ddt + [movx/movy] expansion here, as well as the ppi expansion. + (gensim_caselist): Accept 'eeee' along with 'nnnn'. + 2003-11-03 J"orn Rennecke <joern.rennecke@superh.com> * interp.c (fsca_s, fsrra_s): New functions. diff --git a/sim/sh/gencode.c b/sim/sh/gencode.c index 07d62a98c5a..52e611f3698 100644 --- a/sim/sh/gencode.c +++ b/sim/sh/gencode.c @@ -1,4 +1,5 @@ -/* Simulator/Opcode generator for the Hitachi Super-H architecture. +/* Simulator/Opcode generator for the Renesas + (formerly Hitachi) / SuperH Inc. Super-H architecture. Written by Steve Chamberlain of Cygnus Support. sac@cygnus.com @@ -48,7 +49,7 @@ op tab[] = { { "n", "", "add #<imm>,<REG_N>", "0111nnnni8*1....", - "R[n] += SEXT(i);", + "R[n] += SEXT (i);", "if (i == 0) {", " UNDEF(n); /* see #ifdef PARANOID */", " break;", @@ -84,7 +85,7 @@ op tab[] = { "", "", "bf <bdisp8>", "10001011i8p1....", "if (!T) {", - " SET_NIP (PC + 4 + (SEXT(i) * 2));", + " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", "}", }, @@ -151,6 +152,11 @@ op tab[] = "SET_SR_T (0);", }, + /* sh4a */ + { "", "", "clrdmxy", "0000000010001000", + "saved_state.asregs.cregs.named.sr &= ~(SR_MASK_DMX | SR_MASK_DMY);" + }, + { "", "0", "cmp/eq #<imm>,R0", "10001000i8*1....", "SET_SR_T (R0 == SEXT (i));", }, @@ -195,7 +201,7 @@ op tab[] = "SET_SR_T (0);", }, - { "", "nm", "div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100", /* ? MVS */ + { "", "nm", "div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100", "div1 (R, m, n/*, T*/);", }, @@ -229,7 +235,7 @@ op tab[] = /* sh2e */ { "", "", "fabs <FREG_N>", "1111nnnn01011101", "FP_UNARY (n, fabs);", - "/* FIXME: FR(n) &= 0x7fffffff; */", + "/* FIXME: FR (n) &= 0x7fffffff; */", }, /* sh2e */ @@ -257,7 +263,7 @@ op tab[] = " int i;", " float f;", " } u;", - " u.f = DR(n);", + " u.f = DR (n);", " FPUL = u.i;", "}", }, @@ -274,7 +280,7 @@ op tab[] = " float f;", " } u;", " u.i = FPUL;", - " SET_DR(n, u.f);", + " SET_DR (n, u.f);", "}", }, @@ -285,21 +291,30 @@ op tab[] = }, /* sh4 */ - { "", "", "fipr <FV_M>,<FV_N>", "1111nnmm11101101", - "/* FIXME: not implemented */", - "RAISE_EXCEPTION (SIGILL);", - "/* FIXME: check for DP and (n & 1) == 0? */", + { "", "", "fipr <FV_M>,<FV_N>", "1111vvVV11101101", + "if (FPSCR_PR)", + " RAISE_EXCEPTION (SIGILL);", + "else", + "{", + " double fsum = 0;", + " /* FIXME: check for nans and infinities. */", + " fsum += FR (v1+0) * FR (v2+0);", + " fsum += FR (v1+1) * FR (v2+1);", + " fsum += FR (v1+2) * FR (v2+2);", + " fsum += FR (v1+3) * FR (v2+3);", + " SET_FR (v1+3, fsum);", + "}", }, /* sh2e */ { "", "", "fldi0 <FREG_N>", "1111nnnn10001101", - "SET_FR (n, (float)0.0);", + "SET_FR (n, (float) 0.0);", "/* FIXME: check for DP and (n & 1) == 0? */", }, /* sh2e */ { "", "", "fldi1 <FREG_N>", "1111nnnn10011101", - "SET_FR (n, (float)1.0);", + "SET_FR (n, (float) 1.0);", "/* FIXME: check for DP and (n & 1) == 0? */", }, @@ -310,7 +325,7 @@ op tab[] = " int i;", " float f;", " } u;", - " u.f = FR(n);", + " u.f = FR (n);", " FPUL = u.i;", }, @@ -318,16 +333,16 @@ op tab[] = { "", "", "float FPUL,<FREG_N>", "1111nnnn00101101", /* sh4 */ "if (FPSCR_PR)", - " SET_DR (n, (double)FPUL);", + " SET_DR (n, (double) FPUL);", "else", "{", - " SET_FR (n, (float)FPUL);", + " SET_FR (n, (float) FPUL);", "}", }, /* sh2e */ { "", "", "fmac <FREG_0>,<FREG_M>,<FREG_N>", "1111nnnnmmmm1110", - "SET_FR (n, FR(m) * FR(0) + FR(n));", + "SET_FR (n, FR (m) * FR (0) + FR (n));", "/* FIXME: check for DP and (n & 1) == 0? */", }, @@ -355,7 +370,7 @@ op tab[] = "else", "{", " MA (1);", - " WLAT (R[n], FI(m));", + " WLAT (R[n], FI (m));", "}", }, /* sh2e */ @@ -368,7 +383,7 @@ op tab[] = "else", "{", " MA (1);", - " SET_FI(n, RLAT(R[m]));", + " SET_FI (n, RLAT (R[m]));", "}", }, /* sh2e */ @@ -398,7 +413,7 @@ op tab[] = "{", " MA (1);", " R[n] -= 4;", - " WLAT (R[n], FI(m));", + " WLAT (R[n], FI (m));", "}", }, /* sh2e */ @@ -411,7 +426,7 @@ op tab[] = "else", "{", " MA (1);", - " SET_FI(n, RLAT(R[0] + R[m]));", + " SET_FI (n, RLAT (R[0] + R[m]));", "}", }, /* sh2e */ @@ -424,7 +439,7 @@ op tab[] = "else", "{", " MA (1);", - " WLAT((R[0]+R[n]), FI(m));", + " WLAT ((R[0]+R[n]), FI (m));", "}", }, @@ -432,12 +447,17 @@ op tab[] = /* sh2e */ { "", "", "fmul <FREG_M>,<FREG_N>", "1111nnnnmmmm0010", - "FP_OP(n, *, m);", + "FP_OP (n, *, m);", }, /* sh2e */ { "", "", "fneg <FREG_N>", "1111nnnn01001101", - "FP_UNARY(n, -);", + "FP_UNARY (n, -);", + }, + + /* sh4a */ + { "", "", "fpchg", "1111011111111101", + "SET_FPSCR (GET_FPSCR () ^ FPSCR_MASK_PR);", }, /* sh4 */ @@ -445,11 +465,11 @@ op tab[] = "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", "else", - " SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_FR);", + " SET_FPSCR (GET_FPSCR () ^ FPSCR_MASK_FR);", }, /* sh4 */ - { "", "", "fsca", "1111nnn011111101", + { "", "", "fsca", "1111eeee11111101", "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", "else", @@ -461,12 +481,12 @@ op tab[] = /* sh4 */ { "", "", "fschg", "1111001111111101", - "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_SZ);", + "SET_FPSCR (GET_FPSCR () ^ FPSCR_MASK_SZ);", }, /* sh3e */ { "", "", "fsqrt <FREG_N>", "1111nnnn01101101", - "FP_UNARY(n, sqrt);", + "FP_UNARY (n, sqrt);", }, /* sh4 */ @@ -479,23 +499,34 @@ op tab[] = /* sh2e */ { "", "", "fsub <FREG_M>,<FREG_N>", "1111nnnnmmmm0001", - "FP_OP(n, -, m);", + "FP_OP (n, -, m);", }, /* sh2e */ { "", "", "ftrc <FREG_N>, FPUL", "1111nnnn00111101", /* sh4 */ "if (FPSCR_PR) {", - " if (DR(n) != DR(n)) /* NaN */", + " if (DR (n) != DR (n)) /* NaN */", " FPUL = 0x80000000;", " else", - " FPUL = (int)DR(n);", + " FPUL = (int) DR (n);", "}", "else", - "if (FR(n) != FR(n)) /* NaN */", + "if (FR (n) != FR (n)) /* NaN */", " FPUL = 0x80000000;", "else", - " FPUL = (int)FR(n);", + " FPUL = (int) FR (n);", + }, + + /* sh4 */ + { "", "", "ftrv <FV_N>", "1111vv0111111101", + "if (FPSCR_PR)", + " RAISE_EXCEPTION (SIGILL);", + "else", + "{", + " /* FIXME not implemented. */", + " printf (\"ftrv xmtrx, FV%d\\n\", v1);", + "}", }, /* sh2e */ @@ -535,12 +566,18 @@ op tab[] = { "", "n", "ldc <REG_N>,MOD", "0100nnnn01011110", "SET_MOD (R[n]);", }, -#if 0 { "", "n", "ldc <REG_N>,DBR", "0100nnnn11111010", - "DBR = R[n];", - "/* FIXME: user mode */", + "if (SR_MD)", + " DBR = R[n]; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, + { "", "n", "ldc <REG_N>,SGR", "0100nnnn00111010", + "if (SR_MD)", + " SGR = R[n]; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, -#endif { "n", "n", "ldc.l @<REG_N>+,<CREG_M>", "0100nnnnmmmm0111", "MA (1);", "CREG (m) = RLAT (R[n]);", @@ -558,14 +595,26 @@ op tab[] = "SET_MOD (RLAT (R[n]));", "R[n] += 4;", }, -#if 0 { "n", "n", "ldc.l @<REG_N>+,DBR", "0100nnnn11110110", - "MA (1);", - "DBR = RLAT (R[n]);", - "R[n] += 4;", - "/* FIXME: user mode */", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " DBR = RLAT (R[n]);", + " R[n] += 4;", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, + { "n", "n", "ldc.l @<REG_N>+,SGR", "0100nnnn00110110", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " SGR = RLAT (R[n]);", + " R[n] += 4;", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, -#endif /* sh-dsp */ { "", "", "ldre @(<disp>,PC)", "10001110i8p1....", @@ -575,22 +624,36 @@ op tab[] = "RS = SEXT (i) * 2 + 4 + PH2T (PC);", }, + /* sh4a */ + { "", "n", "ldrc <REG_N>", "0100nnnn00110100", + "SET_RC (R[n]);", + "loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);", + "CHECK_INSN_PTR (insn_ptr);", + "RE |= 1;", + }, + { "", "", "ldrc #<imm>", "10001010i8*1....", + "SET_RC (i);", + "loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);", + "CHECK_INSN_PTR (insn_ptr);", + "RE |= 1;", + }, + { "", "n", "lds <REG_N>,<SREG_M>", "0100nnnnssss1010", "SREG (m) = R[n];", }, { "n", "n", "lds.l @<REG_N>+,<SREG_M>", "0100nnnnssss0110", "MA (1);", - "SREG (m) = RLAT(R[n]);", + "SREG (m) = RLAT (R[n]);", "R[n] += 4;", }, /* sh2e / sh-dsp (lds <REG_N>,DSR) */ { "", "n", "lds <REG_N>,FPSCR", "0100nnnn01101010", - "SET_FPSCR(R[n]);", + "SET_FPSCR (R[n]);", }, /* sh2e / sh-dsp (lds.l @<REG_N>+,DSR) */ { "n", "n", "lds.l @<REG_N>+,FPSCR", "0100nnnn01100110", "MA (1);", - "SET_FPSCR (RLAT(R[n]));", + "SET_FPSCR (RLAT (R[n]));", "R[n] += 4;", }, @@ -599,15 +662,15 @@ op tab[] = }, { "nm", "nm", "mac.l @<REG_M>+,@<REG_N>+", "0000nnnnmmmm1111", - "macl(&R0,memory,n,m);", + "macl (&R0,memory,n,m);", }, { "nm", "nm", "mac.w @<REG_M>+,@<REG_N>+", "0100nnnnmmmm1111", - "macw(&R0,memory,n,m,endianw);", + "macw (&R0,memory,n,m,endianw);", }, { "n", "", "mov #<imm>,<REG_N>", "1110nnnni8*1....", - "R[n] = SEXT(i);", + "R[n] = SEXT (i);", }, { "n", "m", "mov <REG_M>,<REG_N>", "0110nnnnmmmm0011", "R[n] = R[m];", @@ -777,14 +840,49 @@ op tab[] = "WLAT (R[n], R[0]);", }, + { "n", "0", "movco.l R0, @<REG_N>", "0000nnnn01110011", + "/* LDST -> T */", + "SET_SR_T (LDST);", + "/* if (T) R0 -> (Rn) */", + "if (T)", + " WLAT (R[n], R[0]);", + "/* 0 -> LDST */", + "SET_LDST (0);", + }, + + { "0", "n", "movli.l @<REG_N>, R0", "0000nnnn01100011", + "/* 1 -> LDST */", + "SET_LDST (1);", + "/* (Rn) -> R0 */", + "R[0] = RLAT (R[n]);", + "/* if (interrupt/exception) 0 -> LDST */", + "/* (we don't simulate asynchronous interrupts/exceptions) */", + }, + { "n", "", "movt <REG_N>", "0000nnnn00101001", "R[n] = T;", }, + { "0", "n", "movua.l @<REG_N>,R0", "0100nnnn10101001", + "int regn = R[n];", + "MA (1);", + "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ", + " (RBAT (regn + 2) << 8) + RBAT (regn + 3);", + "L (n);", + }, + { "0n", "n", "movua.l @<REG_N>+,R0", "0100nnnn11101001", + "int regn = R[n];", + "MA (1);", + "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ", + " (RBAT (regn + 2) << 8) + RBAT (regn + 3);", + "R[n] += 4;", + "L (n);", + }, { "", "mn", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111", - "MACL = ((int)R[n]) * ((int)R[m]);", + "MACL = ((int) R[n]) * ((int) R[m]);", }, -#if 0 +#if 0 /* FIXME: The above cast to int is not really portable. + It should be replaced by a SEXT32 macro. */ { "", "nm", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111", "MACL = R[n] * R[m];", }, @@ -792,13 +890,13 @@ op tab[] = /* muls.w - see muls */ { "", "mn", "muls <REG_M>,<REG_N>", "0010nnnnmmmm1111", - "MACL = ((int)(short)R[n]) * ((int)(short)R[m]);", + "MACL = ((int) (short) R[n]) * ((int) (short) R[m]);", }, /* mulu.w - see mulu */ { "", "mn", "mulu <REG_M>,<REG_N>", "0010nnnnmmmm1110", - "MACL = (((unsigned int)(unsigned short)R[n])", - " * ((unsigned int)(unsigned short)R[m]));", + "MACL = (((unsigned int) (unsigned short) R[n])", + " * ((unsigned int) (unsigned short) R[m]));", }, { "n", "m", "neg <REG_M>,<REG_N>", "0110nnnnmmmm1011", @@ -820,6 +918,12 @@ op tab[] = "R[n] = ~R[m];", }, + /* sh4a */ + { "", "n", "icbi @<REG_N>", "0000nnnn11100011", + "/* Except for the effect on the cache - which is not simulated -", + " this is like a nop. */", + }, + { "", "n", "ocbi @<REG_N>", "0000nnnn10010011", "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", "/* FIXME: Cache not implemented */", @@ -851,6 +955,18 @@ op tab[] = " this is like a nop. */", }, + /* sh4a */ + { "", "n", "prefi @<REG_N>", "0000nnnn11010011", + "/* Except for the effect on the cache - which is not simulated -", + " this is like a nop. */", + }, + + /* sh4a */ + { "", "", "synco", "0000000010101011", + "/* Except for the effect on the pipeline - which is not simulated -", + " this is like a nop. */", + }, + { "n", "n", "rotcl <REG_N>", "0100nnnn00100100", "ult = R[n] < 0;", "R[n] = (R[n] << 1) | T;", @@ -898,6 +1014,18 @@ op tab[] = "Delay_Slot (PC + 2);", }, + /* sh4a */ + { "", "", "setdmx", "0000000010011000", + "saved_state.asregs.cregs.named.sr |= SR_MASK_DMX;" + "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMY;" + }, + + /* sh4a */ + { "", "", "setdmy", "0000000011001000", + "saved_state.asregs.cregs.named.sr |= SR_MASK_DMY;" + "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMX;" + }, + /* sh-dsp */ { "", "n", "setrc <REG_N>", "0100nnnn00010100", "SET_RC (R[n]);", @@ -980,31 +1108,43 @@ op tab[] = "R[n] = CREG (m);", }, -#if 0 { "n", "", "stc SGR,<REG_N>", "0000nnnn00111010", - "R[n] = SGR;", + "if (SR_MD)", + " R[n] = SGR; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, { "n", "", "stc DBR,<REG_N>", "0000nnnn11111010", - "R[n] = DBR;", + "if (SR_MD)", + " R[n] = DBR; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, -#endif { "n", "n", "stc.l <CREG_M>,@-<REG_N>", "0100nnnnmmmm0011", "MA (1);", "R[n] -= 4;", "WLAT (R[n], CREG (m));", }, -#if 0 { "n", "n", "stc.l SGR,@-<REG_N>", "0100nnnn00110010", - "MA (1);", - "R[n] -= 4;", - "WLAT (R[n], SGR);", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " R[n] -= 4;", + " WLAT (R[n], SGR);", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, { "n", "n", "stc.l DBR,@-<REG_N>", "0100nnnn11110010", - "MA (1);", - "R[n] -= 4;", - "WLAT (R[n], DBR);", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " R[n] -= 4;", + " WLAT (R[n], DBR);", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, -#endif { "n", "", "sts <SREG_M>,<REG_N>", "0000nnnnssss1010", "R[n] = SREG (m);", @@ -1044,9 +1184,9 @@ op tab[] = { "", "n", "tas.b @<REG_N>", "0100nnnn00011011", "MA (1);", - "ult = RBAT(R[n]);", + "ult = RBAT (R[n]);", "SET_SR_T (ult == 0);", - "WBAT(R[n],ult|0x80);", + "WBAT (R[n],ult|0x80);", }, { "0", "", "trapa #<imm>", "11000011i8*1....", @@ -1056,15 +1196,15 @@ op tab[] = #if 0 "else {", /* SH-[12] */ - " R[15]-=4;", - " WLAT (R[15], GET_SR());", - " R[15]-=4;", + " R[15] -= 4;", + " WLAT (R[15], GET_SR ());", + " R[15] -= 4;", " WLAT (R[15], PH2T (PC + 2));", #else "else if (!SR_BL) {", - " SSR = GET_SR();", + " SSR = GET_SR ();", " SPC = PH2T (PC + 2);", - " SET_SR (GET_SR() | SR_MASK_MD | SR_MASK_BL | SR_MASK_RB);", + " SET_SR (GET_SR () | SR_MASK_MD | SR_MASK_BL | SR_MASK_RB);", " /* FIXME: EXPEVT = 0x00000160; */", #endif " SET_NIP (PT2H (RLAT (VBR + (imm<<2))));", @@ -1102,10 +1242,10 @@ op tab[] = #if 0 { "divs.l <REG_M>,<REG_N>", "0100nnnnmmmm1110", - "divl(0,R[n],R[m]);", + "divl (0,R[n],R[m]);", }, { "divu.l <REG_M>,<REG_N>", "0100nnnnmmmm1101", - "divl(0,R[n],R[m]);", + "divl (0,R[n],R[m]);", }, #endif @@ -1258,56 +1398,118 @@ op movsxy_tab[] = "WLAT (R[n], SEXT (DSP_R (m)));", "R[n] += R[8];", }, - { "", "n", "movx.w @<REG_x>,<DSP_XX>", "111100xxXX000100", + { "", "n", "movx.w @<REG_xy>,<DSP_XY>", "111100xyXY0001??", "DSP_R (m) = RSWAT (R[n]) << 16;", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", + }, + { "", "n", "movx.l @<REG_xy>,<DSP_XY>", "111100xyXY010100", + "DSP_R (m) = RLAT (R[n]);", }, - { "n", "n", "movx.w @<REG_x>+,<DSP_XX>", "111100xxXX001000", + { "n", "n", "movx.w @<REG_xy>+,<DSP_XY>", "111100xyXY0010??", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", + }, + { "n", "n", "movx.l @<REG_xy>+,<DSP_XY>", "111100xyXY011000", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;", }, - { "n", "n8","movx.w @<REG_x>+REG_8,<DSP_XX>", "111100xxXX001100", + { "n", "n8","movx.w @<REG_xy>+REG_8,<DSP_XY>", "111100xyXY0011??", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", }, - { "", "n", "movx.w <DSP_Aa>,@<REG_x>", "111100xxaa100100", + { "n", "n8","movx.l @<REG_xy>+REG_8,<DSP_XY>", "111100xyXY011100", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", + }, + { "", "n", "movx.w <DSP_Ax>,@<REG_xy>", "111100xyax1001??", "WWAT (R[n], DSP_R (m) >> 16);", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", + }, + { "", "n", "movx.l <DSP_Ax>,@<REG_xy>", "111100xyax110100", + "WLAT (R[n], DSP_R (m));", }, - { "n", "n", "movx.w <DSP_Aa>,@<REG_x>+", "111100xxaa101000", + { "n", "n", "movx.w <DSP_Ax>,@<REG_xy>+", "111100xyax1010??", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", }, - { "n", "n8","movx.w <DSP_Aa>,@<REG_x>+REG_8","111100xxaa101100", + { "n", "n", "movx.l <DSP_Ax>,@<REG_xy>+", "111100xyax111000", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;", + }, + { "n", "n8","movx.w <DSP_Ax>,@<REG_xy>+REG_8","111100xyax1011??", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", }, - { "", "n", "movy.w @<REG_y>,<DSP_YY>", "111100yyYY000001", + { "n", "n8","movx.l <DSP_Ax>,@<REG_xy>+REG_8","111100xyax111100", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", + }, + { "", "n", "movy.w @<REG_yx>,<DSP_YX>", "111100yxYX000001", "DSP_R (m) = RSWAT (R[n]) << 16;", }, - { "n", "n", "movy.w @<REG_y>+,<DSP_YY>", "111100yyYY000010", + { "n", "n", "movy.w @<REG_yx>+,<DSP_YX>", "111100yxYX000010", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;", }, - { "n", "n9","movy.w @<REG_y>+REG_9,<DSP_YY>", "111100yyYY000011", + { "n", "n9","movy.w @<REG_yx>+REG_9,<DSP_YX>", "111100yxYX000011", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", }, - { "", "n", "movy.w <DSP_Aa>,@<REG_y>", "111100yyAA010001", + { "", "n", "movy.w <DSP_Ay>,@<REG_yx>", "111100yxAY010001", "WWAT (R[n], DSP_R (m) >> 16);", }, - { "n", "n", "movy.w <DSP_Aa>,@<REG_y>+", "111100yyAA010010", + { "n", "n", "movy.w <DSP_Ay>,@<REG_yx>+", "111100yxAY010010", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;", }, - { "n", "n9", "movy.w <DSP_Aa>,@<REG_y>+REG_9", "111100yyAA010011", + { "n", "n9", "movy.w <DSP_Ay>,@<REG_yx>+REG_9", "111100yxAY010011", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", }, + { "", "n", "movy.l @<REG_yx>,<DSP_YX>", "111100yxYX100001", + "DSP_R (m) = RLAT (R[n]);", + }, + { "n", "n", "movy.l @<REG_yx>+,<DSP_YX>", "111100yxYX100010", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;", + }, + { "n", "n9","movy.l @<REG_yx>+REG_9,<DSP_YX>", "111100yxYX100011", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", + }, + { "", "n", "movy.l <DSP_Ay>,@<REG_yx>", "111100yxAY110001", + "WLAT (R[n], DSP_R (m));", + }, + { "n", "n", "movy.l <DSP_Ay>,@<REG_yx>+", "111100yxAY110010", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;", + }, + { "n", "n9", "movy.l <DSP_Ay>,@<REG_yx>+REG_9", "111100yxAY110011", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", + }, { "", "", "nopx nopy", "1111000000000000", "/* nop */", }, @@ -1462,7 +1664,7 @@ op ppi_tab[] = "DSR |= carry;\n", "goto assign_z;\n", }, - { "","", "pcmp Sx,Sy", "10000100xxyy....", + { "","", "pcmp Sx,Sy", "10000100xxyyzzzz", "int Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", "int Sy = DSP_R (y);", @@ -1479,6 +1681,24 @@ op ppi_tab[] = }, { "","", "pwad Sx,Sy,Dz", "10110100xxyyzzzz", }, + { "","", "(if cc) pabs Sx,Dz", "100010ccxx01zzzz", + "/* FIXME: duplicate code pabs. */", + "res = DSP_R (x);", + "res_grd = GET_DSP_GRD (x);", + "if (res >= 0)", + " carry = 0;", + "else", + " {", + " res = -res;", + " carry = (res != 0); /* The manual has a bug here. */", + " res_grd = -res_grd - carry;", + " }", + "COMPUTE_OVERFLOW;", + "/* ??? The re-computing of overflow after", + " saturation processing is specific to pabs. */", + "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;", + "ADD_SUB_GE;", + }, { "","", "pabs Sx,Dz", "10001000xx..zzzz", "res = DSP_R (x);", "res_grd = GET_DSP_GRD (x);", @@ -1496,6 +1716,18 @@ op ppi_tab[] = "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;", "ADD_SUB_GE;", }, + + { "","", "(if cc) prnd Sx,Dz", "100110ccxx01zzzz", + "/* FIXME: duplicate code prnd. */", + "int Sx = DSP_R (x);", + "int Sx_grd = GET_DSP_GRD (x);", + "", + "res = (Sx + 0x8000) & 0xffff0000;", + "carry = (unsigned) res < (unsigned) Sx;", + "res_grd = Sx_grd + carry;", + "COMPUTE_OVERFLOW;", + "ADD_SUB_GE;", + }, { "","", "prnd Sx,Dz", "10011000xx..zzzz", "int Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", @@ -1506,6 +1738,31 @@ op ppi_tab[] = "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", }, + + { "","", "(if cc) pabs Sy,Dz", "101010cc01yyzzzz", + "/* FIXME: duplicate code pabs. */", + "res = DSP_R (y);", + "res_grd = 0;", + "overflow = 0;", + "greater_equal = DSR_MASK_G;", + "if (res >= 0)", + " carry = 0;", + "else", + " {", + " res = -res;", + " carry = 1;", + " if (res < 0)", + " {", + " if (S)", + " res = 0x7fffffff;", + " else", + " {", + " overflow = DSR_MASK_V;", + " greater_equal = 0;", + " }", + " }", + " }", + }, { "","", "pabs Sy,Dz", "10101000..yyzzzz", "res = DSP_R (y);", "res_grd = 0;", @@ -1529,6 +1786,17 @@ op ppi_tab[] = " }", " }", }, + { "","", "(if cc) prnd Sy,Dz", "101110cc01yyzzzz", + "/* FIXME: duplicate code prnd. */", + "int Sy = DSP_R (y);", + "int Sy_grd = SIGN32 (Sy);", + "", + "res = (Sy + 0x8000) & 0xffff0000;", + "carry = (unsigned) res < (unsigned) Sy;", + "res_grd = Sy_grd + carry;", + "COMPUTE_OVERFLOW;", + "ADD_SUB_GE;", + }, { "","", "prnd Sy,Dz", "10111000..yyzzzz", "int Sy = DSP_R (y);", "int Sy_grd = SIGN32 (Sy);", @@ -1609,6 +1877,18 @@ op ppi_tab[] = "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", }, + { "","", "(if cc) psub Sy,Sx,Dz", "100001ccxxyyzzzz", + "int Sx = DSP_R (x);", + "int Sx_grd = GET_DSP_GRD (x);", + "int Sy = DSP_R (y);", + "int Sy_grd = SIGN32 (Sy);", + "", + "res = Sy - Sx;", + "carry = (unsigned) res > (unsigned) Sy;", + "res_grd = Sy_grd - Sx_grd - carry;", + "COMPUTE_OVERFLOW;", + "ADD_SUB_GE;", + }, { "","", "(if cc) padd Sx,Sy,Dz", "101100ccxxyyzzzz", "int Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", @@ -1698,6 +1978,21 @@ op ppi_tab[] = "overflow = 0;", "greater_equal = 1;", }, + { "","", "pclr Du pmuls Se,Sf,Dg", "0100eeff0001gguu", + "/* Do multiply. */", + "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;", + "if (res == 0x80000000)", + " res = 0x7fffffff;", + "DSP_R (g) = res;", + "DSP_GRD (g) = SIGN32 (res);", + "/* FIXME: update DSR based on results of multiply! */", + "", + "/* Do clr. */", + "z = u;", + "res = 0;", + "res_grd = 0;", + "goto assign_z;", + }, { "","", "(if cc) pdmsb Sx,Dz", "100111ccxx..zzzz", "unsigned Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", @@ -1813,6 +2108,27 @@ op ppi_tab[] = " MACL = DSP_R (z) = res;", "return;", }, + /* sh4a */ + { "","", "(if cc) pswap Sx,Dz", "100111ccxx01zzzz", + "int Sx = DSP_R (x);", + "", + "res = ((Sx & 0xffff) * 65536) + ((Sx >> 16) & 0xffff);", + "res_grd = GET_DSP_GRD (x);", + "carry = 0;", + "overflow = 0;", + "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;", + }, + /* sh4a */ + { "","", "(if cc) pswap Sy,Dz", "101111cc01yyzzzz", + "int Sy = DSP_R (y);", + "", + "res = ((Sy & 0xffff) * 65536) + ((Sy >> 16) & 0xffff);", + "res_grd = SIGN32 (Sy);", + "carry = 0;", + "overflow = 0;", + "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;", + }, + {0, 0} }; @@ -1950,128 +2266,130 @@ gengastab () } -/* Convert a string of 4 binary digits into an int */ - -static -int -bton (s) - char *s; - -{ - int n = 0; - int v = 8; - while (v) - { - if (*s == '1') - n |= v; - v >>= 1; - s++; - } - return n; -} - static unsigned char table[1 << 16]; -/* Take an opcode expand all varying fields in it out and fill all the - right entries in 'table' with the opcode index*/ +/* Take an opcode, expand all varying fields in it out and fill all the + right entries in 'table' with the opcode index. */ static void -expand_opcode (shift, val, i, s) - int shift; +expand_opcode (val, i, s) int val; int i; char *s; { - int j; - if (*s == 0) { table[val] = i; } else { + int j = 0, m = 0; + switch (s[0]) { - + default: + fprintf (stderr, "expand_opcode: illegal char '%c'\n", s[0]); + exit (1); case '0': case '1': - { - int m, mv; - - if (s[1] - '0' > 1U || !s[2] || ! s[3]) - expand_opcode (shift - 1, val + s[0] - '0', i, s + 1); - val |= bton (s) << shift; - if (s[2] == '0' || s[2] == '1') - expand_opcode (shift - 4, val, i, s + 4); - else if (s[2] == 'N') - for (j = 0; j < 4; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); - else if (s[2] == 'x') - for (j = 0; j < 4; j += 2) - for (m = 0; m < 32; m++) - { - /* Ignore illegal nopy */ - if ((m & 7) == 0 && m != 0) - continue; - mv = m & 3 | (m & 4) << 2 | (m & 8) << 3 | (m & 16) << 4; - expand_opcode (shift - 4, val | mv | (j << shift), i, - s + 4); - } - else if (s[2] == 'y') - for (j = 0; j < 2; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); - break; - } + /* Consume an arbitrary number of ones and zeros. */ + do { + j = (j << 1) + (s[m++] - '0'); + } while (s[m] == '0' || s[m] == '1'); + expand_opcode ((val << m) | j, i, s + m); + break; + case 'N': /* NN -- four-way fork */ + for (j = 0; j < 4; j++) + expand_opcode ((val << 2) | j, i, s + 2); + break; + case 'x': /* xx or xy -- two-way or four-way fork */ + for (j = 0; j < 4; j += (s[1] == 'x' ? 2 : 1)) + expand_opcode ((val << 2) | j, i, s + 2); + break; + case 'y': /* yy or yx -- two-way or four-way fork */ + for (j = 0; j < (s[1] == 'x' ? 4 : 2); j++) + expand_opcode ((val << 2) | j, i, s + 2); + break; + case '?': /* Seven-way "wildcard" fork for movxy */ + expand_opcode ((val << 2), i, s + 2); + for (j = 1; j < 4; j++) + { + expand_opcode ((val << 2) | j, i, s + 2); + expand_opcode ((val << 2) | (j + 16), i, s + 2); + } + break; + case 'i': /* eg. "i8*1" */ + case '.': /* "...." is a wildcard */ case 'n': case 'm': - { - int digits = 1; - while (s[digits] == s[0]) - digits++; - for (j = 0; j < (1 << digits); j++) - { - expand_opcode (shift - digits, val | (j << shift), i, - s + digits); - } - break; - } + /* nnnn, mmmm, i#*#, .... -- 16-way fork. */ + for (j = 0; j < 16; j++) + expand_opcode ((val << 4) | j, i, s + 4); + break; + case 'e': + /* eeee -- even numbered register: + 8 way fork. */ + for (j = 0; j < 15; j += 2) + expand_opcode ((val << 4) | j, i, s + 4); + break; case 'M': - /* A1, A0,X0,X1,Y0,Y1,M0,A1G,M1,M1G */ - for (j = 5; j < 16; j++) - if (j != 6) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + /* A0, A1, X0, X1, Y0, Y1, M0, M1, A0G, A1G: + MMMM -- 10-way fork */ + expand_opcode ((val << 4) | 5, i, s + 4); + for (j = 7; j < 16; j++) + expand_opcode ((val << 4) | j, i, s + 4); break; case 'G': - /* A1G, A0G: */ + /* A1G, A0G: + GGGG -- two-way fork */ for (j = 13; j <= 15; j +=2) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + expand_opcode ((val << 4) | j, i, s + 4); break; case 's': + /* ssss -- 10-way fork */ /* System registers mach, macl, pr: */ for (j = 0; j < 3; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + expand_opcode ((val << 4) | j, i, s + 4); /* System registers fpul, fpscr/dsr, a0, x0, x1, y0, y1: */ for (j = 5; j < 12; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + expand_opcode ((val << 4) | j, i, s + 4); break; case 'X': + /* XX/XY -- 2/4 way fork. */ + for (j = 0; j < 4; j += (s[1] == 'X' ? 2 : 1)) + expand_opcode ((val << 2) | j, i, s + 2); + break; case 'a': - val |= bton (s) << shift; - for (j = 0; j < 16; j += 8) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + /* aa/ax -- 2/4 way fork. */ + for (j = 0; j < 4; j += (s[1] == 'a' ? 2 : 1)) + expand_opcode ((val << 2) | j, i, s + 2); break; case 'Y': + /* YY/YX -- 2/4 way fork. */ + for (j = 0; j < (s[1] == 'Y' ? 2 : 4); j += 1) + expand_opcode ((val << 2) | j, i, s + 2); + break; case 'A': - val |= bton (s) << shift; - for (j = 0; j < 8; j += 4) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + /* AA/AY: 2/4 way fork. */ + for (j = 0; j < (s[1] == 'A' ? 2 : 4); j += 1) + expand_opcode ((val << 2) | j, i, s + 2); break; - - default: - for (j = 0; j < (1 << (shift + 4)); j++) + case 'v': + /* vv(VV) -- 4(16) way fork. */ + /* Vector register fv0/4/8/12. */ + if (s[2] == 'V') + { + /* 2 vector registers. */ + for (j = 0; j < 15; j++) + expand_opcode ((val << 4) | j, i, s + 4); + } + else { - table[val | j] = i; + /* 1 vector register. */ + for (j = 0; j < 4; j += 1) + expand_opcode ((val << 2) | j, i, s + 2); } + break; } } } @@ -2127,7 +2445,7 @@ filltable (p) for (; p->name; p++) { p->index = index++; - expand_opcode (12, 0, p->index, p->code); + expand_opcode (0, p->index, p->code); } } @@ -2136,7 +2454,7 @@ filltable (p) processing insns (ppi) for code 0xf800 (ppi nopx nopy). Copy the latter tag to represent all combinations of ppi with ddt. */ static void -ppi_moves () +expand_ppi_movxy () { int i; @@ -2171,6 +2489,18 @@ gensim_caselist (p) *s); exit (1); break; + case '?': + /* Wildcard expansion, nothing to do here. */ + s += 2; + break; + case 'v': + printf (" int v1 = ((iword >> 10) & 3) * 4;\n"); + s += 2; + break; + case 'V': + printf (" int v2 = ((iword >> 8) & 3) * 4;\n"); + s += 2; + break; case '0': case '1': s += 2; @@ -2179,7 +2509,8 @@ gensim_caselist (p) s += 4; break; case 'n': - printf (" int n = (iword >>8) & 0xf;\n"); + case 'e': + printf (" int n = (iword >> 8) & 0xf;\n"); needn = 1; s += 4; break; @@ -2188,12 +2519,26 @@ gensim_caselist (p) s += 2; break; case 'x': - printf (" int n = ((iword >> 9) & 1) + 4;\n"); + if (s[1] == 'y') /* xy */ + { + printf (" int n = (iword & 3) ? \n"); + printf (" ((iword >> 9) & 1) + 4 : \n"); + printf (" REG_xy ((iword >> 8) & 3);\n"); + } + else + printf (" int n = ((iword >> 9) & 1) + 4;\n"); needn = 1; s += 2; break; case 'y': - printf (" int n = ((iword >> 8) & 1) + 6;\n"); + if (s[1] == 'x') /* yx */ + { + printf (" int n = (iword & 0xc) ? \n"); + printf (" ((iword >> 8) & 1) + 6 : \n"); + printf (" REG_yx ((iword >> 8) & 3);\n"); + } + else + printf (" int n = ((iword >> 8) & 1) + 6;\n"); needn = 1; s += 2; break; @@ -2202,23 +2547,51 @@ gensim_caselist (p) case 's': case 'M': case 'G': - printf (" int m = (iword >>4) & 0xf;\n"); + printf (" int m = (iword >> 4) & 0xf;\n"); s += 4; break; case 'X': - printf (" int m = ((iword >> 7) & 1) + 8;\n"); + if (s[1] == 'Y') /* XY */ + { + printf (" int m = (iword & 3) ? \n"); + printf (" ((iword >> 7) & 1) + 8 : \n"); + printf (" DSP_xy ((iword >> 6) & 3);\n"); + } + else + printf (" int m = ((iword >> 7) & 1) + 8;\n"); s += 2; break; case 'a': - printf (" int m = 7 - ((iword >> 6) & 2);\n"); + if (s[1] == 'x') /* ax */ + { + printf (" int m = (iword & 3) ? \n"); + printf (" 7 - ((iword >> 6) & 2) : \n"); + printf (" DSP_ax ((iword >> 6) & 3);\n"); + } + else + printf (" int m = 7 - ((iword >> 6) & 2);\n"); s += 2; break; case 'Y': - printf (" int m = ((iword >> 6) & 1) + 10;\n"); + if (s[1] == 'X') /* YX */ + { + printf (" int m = (iword & 0xc) ? \n"); + printf (" ((iword >> 6) & 1) + 10 : \n"); + printf (" DSP_yx ((iword >> 6) & 3);\n"); + } + else + printf (" int m = ((iword >> 6) & 1) + 10;\n"); s += 2; break; case 'A': - printf (" int m = 7 - ((iword >> 5) & 2);\n"); + if (s[1] == 'Y') /* AY */ + { + printf (" int m = (iword & 0xc) ? \n"); + printf (" 7 - ((iword >> 5) & 2) : \n"); + printf (" DSP_ay ((iword >> 6) & 3);\n"); + } + else + printf (" int m = 7 - ((iword >> 5) & 2);\n"); s += 2; break; @@ -2246,10 +2619,10 @@ gensim_caselist (p) case '1': break; case '2': - printf ("<<1"); + printf (" << 1"); break; case '4': - printf ("<<2"); + printf (" << 2"); break; } printf (";\n"); @@ -2258,27 +2631,27 @@ gensim_caselist (p) } if (sextbit > 0) { - printf (" i = (i ^ (1<<%d))-(1<<%d);\n", + printf (" i = (i ^ (1 << %d)) - (1 << %d);\n", sextbit - 1, sextbit - 1); } if (needm && needn) - printf (" TB(m,n);\n"); + printf (" TB (m,n);\n"); else if (needm) - printf (" TL(m);\n"); + printf (" TL (m);\n"); else if (needn) - printf (" TL(n);\n"); + printf (" TL (n);\n"); { /* Do the refs */ char *r; for (r = p->refs; *r; r++) { - if (*r == '0') printf(" CREF(0);\n"); - if (*r == '8') printf(" CREF(8);\n"); - if (*r == '9') printf(" CREF(9);\n"); - if (*r == 'n') printf(" CREF(n);\n"); - if (*r == 'm') printf(" CREF(m);\n"); + if (*r == '0') printf (" CREF (0);\n"); + if (*r == '8') printf (" CREF (8);\n"); + if (*r == '9') printf (" CREF (9);\n"); + if (*r == 'n') printf (" CREF (n);\n"); + if (*r == 'm') printf (" CREF (m);\n"); } } @@ -2297,9 +2670,9 @@ gensim_caselist (p) char *r; for (r = p->defs; *r; r++) { - if (*r == '0') printf(" CDEF(0);\n"); - if (*r == 'n') printf(" CDEF(n);\n"); - if (*r == 'm') printf(" CDEF(m);\n"); + if (*r == '0') printf(" CDEF (0);\n"); + if (*r == 'n') printf(" CDEF (n);\n"); + if (*r == 'm') printf(" CDEF (m);\n"); } } @@ -2312,6 +2685,18 @@ static void gensim () { printf ("{\n"); + printf ("/* REG_xy = [r4, r5, r0, r1]. */\n"); + printf ("#define REG_xy(R) ((R)==0 ? 4 : (R)==2 ? 5 : (R)==1 ? 0 : 1)\n"); + printf ("/* REG_yx = [r6, r7, r2, r3]. */\n"); + printf ("#define REG_yx(R) ((R)==0 ? 6 : (R)==1 ? 7 : (R)==2 ? 2 : 3)\n"); + printf ("/* DSP_ax = [a0, a1, x0, x1]. */\n"); + printf ("#define DSP_ax(R) ((R)==0 ? 7 : (R)==2 ? 5 : (R)==1 ? 8 : 9)\n"); + printf ("/* DSP_ay = [a0, a1, y0, y1]. */\n"); + printf ("#define DSP_ay(R) ((R)==0 ? 7 : (R)==1 ? 5 : (R)==2 ? 10 : 11)\n"); + printf ("/* DSP_xy = [x0, x1, y0, y1]. */\n"); + printf ("#define DSP_xy(R) ((R)==0 ? 8 : (R)==2 ? 9 : (R)==1 ? 10 : 11)\n"); + printf ("/* DSP_yx = [y0, y1, x0, x1]. */\n"); + printf ("#define DSP_yx(R) ((R)==0 ? 10 : (R)==1 ? 11 : (R)==2 ? 8 : 9)\n"); printf (" switch (jump_table[iword]) {\n"); gensim_caselist (tab); @@ -2335,22 +2720,27 @@ gendefines () char *s = p->name; printf ("#define OPC_"); while (*s) { - if (isupper(*s)) - *s = tolower(*s); - if (isalpha(*s)) printf("%c", *s); - if (*s == ' ') printf("_"); - if (*s == '@') printf("ind_"); - if (*s == ',') printf("_"); + if (isupper (*s)) + *s = tolower (*s); + if (isalpha (*s)) + printf ("%c", *s); + if (*s == ' ') + printf ("_"); + if (*s == '@') + printf ("ind_"); + if (*s == ',') + printf ("_"); s++; } - printf(" %d\n",p->index); + printf (" %d\n",p->index); } } static int ppi_index; /* Take a ppi code, expand all varying fields in it and fill all the - right entries in 'table' with the opcode index. */ + right entries in 'table' with the opcode index. + NOTE: tail recursion optimization removed for simplicity. */ static void expand_ppi_code (val, i, s) @@ -2360,46 +2750,40 @@ expand_ppi_code (val, i, s) { int j; - for (;;) + switch (s[0]) { - switch (s[0]) - { - default: - fprintf (stderr, "gencode/expand_ppi_code: Illegal char '%c'\n", - s[0]); - exit (2); - break; - /* The last eight bits are disregarded for the switch table. */ - case 'm': - case 'x': - case '.': - table[val] = i; - return; - case '0': - val += val; - s++; - break; - case '1': - val += val + 1; - s++; - break; - case 'i': - case 'e': case 'f': - val += val; - s++; - expand_ppi_code (val, i, s); - val++; - break; - case 'c': - val <<= 2; - s += 2; - val++; - expand_ppi_code (val, ppi_index++, s); - val++; - expand_ppi_code (val, i, s); - val++; - break; - } + default: + fprintf (stderr, "gencode/expand_ppi_code: Illegal char '%c'\n", s[0]); + exit (2); + break; + case 'g': + case 'z': + /* The last four bits are disregarded for the switch table. */ + table[val] = i; + return; + case 'm': + /* Four-bit expansion. */ + for (j = 0; j < 16; j++) + expand_ppi_code ((val << 4) + j, i, s + 4); + break; + case '.': + case '0': + expand_ppi_code ((val << 1), i, s + 1); + break; + case '1': + expand_ppi_code ((val << 1) + 1, i, s + 1); + break; + case 'i': + case 'e': case 'f': + case 'x': case 'y': + expand_ppi_code ((val << 1), i, s + 1); + expand_ppi_code ((val << 1) + 1, i, s + 1); + break; + case 'c': + expand_ppi_code ((val << 2) + 1, ppi_index++, s + 2); + expand_ppi_code ((val << 2) + 2, i, s + 2); + expand_ppi_code ((val << 2) + 3, i, s + 2); + break; } } @@ -2451,18 +2835,24 @@ ppi_gensim () printf ("ppi_insn (iword)\n"); printf (" int iword;\n"); printf ("{\n"); + printf (" /* 'ee' = [x0, x1, y0, a1] */\n"); printf (" static char e_tab[] = { 8, 9, 10, 5};\n"); + printf (" /* 'ff' = [y0, y1, x0, a1] */\n"); printf (" static char f_tab[] = {10, 11, 8, 5};\n"); + printf (" /* 'xx' = [x0, x1, a0, a1] */\n"); printf (" static char x_tab[] = { 8, 9, 7, 5};\n"); + printf (" /* 'yy' = [y0, y1, m0, m1] */\n"); printf (" static char y_tab[] = {10, 11, 12, 14};\n"); + printf (" /* 'gg' = [m0, m1, a0, a1] */\n"); printf (" static char g_tab[] = {12, 14, 7, 5};\n"); + printf (" /* 'uu' = [x0, y0, a0, a1] */\n"); printf (" static char u_tab[] = { 8, 10, 7, 5};\n"); printf ("\n"); printf (" int z;\n"); printf (" int res, res_grd;\n"); printf (" int carry, overflow, greater_equal;\n"); printf ("\n"); - printf (" switch (ppi_table[iword >> 8]) {\n"); + printf (" switch (ppi_table[iword >> 4]) {\n"); for (; p->name; p++) { @@ -2618,12 +3008,12 @@ main (ac, av) memset (table, 0, sizeof table); filltable (movsxy_tab); - ppi_moves (); + expand_ppi_movxy (); dumptable ("sh_dsp_table", 1 << 12, 0xf000); memset (table, 0, sizeof table); ppi_filltable (); - dumptable ("ppi_table", 1 << 8, 0); + dumptable ("ppi_table", 1 << 12, 0); } else if (strcmp (av[1], "-x") == 0) { diff --git a/sim/sh/interp.c b/sim/sh/interp.c index 5ca8e61a0a7..981067804cd 100644 --- a/sim/sh/interp.c +++ b/sim/sh/interp.c @@ -1,4 +1,4 @@ -/* Simulator for the Hitachi SH architecture. +/* Simulator for the Renesas (formerly Hitachi) / SuperH Inc. SH architecture. Written by Steve Chamberlain of Cygnus Support. sac@cygnus.com @@ -120,6 +120,9 @@ typedef union int re; /* sh3 */ int bank[8]; + int dbr; /* debug base register */ + int sgr; /* saved gr15 */ + int ldst; /* load/store flag (boolean) */ } named; int i[16]; } cregs; @@ -167,10 +170,8 @@ static int target_dsp; static int host_little_endian; static char **prog_argv; -#if 1 static int maskw = 0; static int maskl = 0; -#endif static SIM_OPEN_KIND sim_kind; static char *myname; @@ -182,15 +183,17 @@ static char *myname; #define R0 saved_state.asregs.regs[0] #define Rn saved_state.asregs.regs[n] #define Rm saved_state.asregs.regs[m] -#define UR0 (unsigned int)(saved_state.asregs.regs[0]) -#define UR (unsigned int)R -#define UR (unsigned int)R +#define UR0 (unsigned int) (saved_state.asregs.regs[0]) +#define UR (unsigned int) R +#define UR (unsigned int) R #define SR0 saved_state.asregs.regs[0] #define CREG(n) (saved_state.asregs.cregs.i[(n)]) #define GBR saved_state.asregs.cregs.named.gbr #define VBR saved_state.asregs.cregs.named.vbr +#define DBR saved_state.asregs.cregs.named.dbr #define SSR saved_state.asregs.cregs.named.ssr #define SPC saved_state.asregs.cregs.named.spc +#define SGR saved_state.asregs.cregs.named.sgr #define SREG(n) (saved_state.asregs.sregs.i[(n)]) #define MACH saved_state.asregs.sregs.named.mach #define MACL saved_state.asregs.sregs.named.macl @@ -228,6 +231,7 @@ static char *myname; #define Q ((saved_state.asregs.cregs.named.sr & SR_MASK_Q) != 0) #define S ((saved_state.asregs.cregs.named.sr & SR_MASK_S) != 0) #define T ((saved_state.asregs.cregs.named.sr & SR_MASK_T) != 0) +#define LDST ((saved_state.asregs.cregs.named.ldst) != 0) #define SR_BL ((saved_state.asregs.cregs.named.sr & SR_MASK_BL) != 0) #define SR_RB ((saved_state.asregs.cregs.named.sr & SR_MASK_RB) != 0) @@ -249,6 +253,7 @@ do { \ #define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q) #define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S) #define SET_SR_T(EXP) SET_SR_BIT ((EXP), SR_MASK_T) +#define SET_LDST(EXP) (saved_state.asregs.cregs.named.ldst = ((EXP) != 0)) /* stc currently relies on being able to read SR without modifications. */ #define GET_SR() (saved_state.asregs.cregs.named.sr - 0) @@ -265,9 +270,9 @@ do { \ #define FPSCR_MASK_SZ (1 << 20) #define FPSCR_MASK_PR (1 << 19) -#define FPSCR_FR ((GET_FPSCR() & FPSCR_MASK_FR) != 0) -#define FPSCR_SZ ((GET_FPSCR() & FPSCR_MASK_SZ) != 0) -#define FPSCR_PR ((GET_FPSCR() & FPSCR_MASK_PR) != 0) +#define FPSCR_FR ((GET_FPSCR () & FPSCR_MASK_FR) != 0) +#define FPSCR_SZ ((GET_FPSCR () & FPSCR_MASK_SZ) != 0) +#define FPSCR_PR ((GET_FPSCR () & FPSCR_MASK_PR) != 0) /* Count the number of arguments in an argv. */ static int @@ -325,7 +330,7 @@ void raise_exception (x) int x; { - RAISE_EXCEPTION(x); + RAISE_EXCEPTION (x); } void @@ -400,7 +405,7 @@ do { \ #ifdef PARANOID int valid[16]; -#define CREF(x) if(!valid[x]) fail(); +#define CREF(x) if (!valid[x]) fail (); #define CDEF(x) valid[x] = 1; #define UNDEF(x) valid[x] = 0; #else @@ -411,14 +416,14 @@ int valid[16]; static void parse_and_set_memory_size PARAMS ((char *str)); static int IOMEM PARAMS ((int addr, int write, int value)); -static struct loop_bounds get_loop_bounds PARAMS((int, int, unsigned char *, - unsigned char *, int, int)); -static void process_wlat_addr PARAMS((int, int)); -static void process_wwat_addr PARAMS((int, int)); -static void process_wbat_addr PARAMS((int, int)); -static int process_rlat_addr PARAMS((int)); -static int process_rwat_addr PARAMS((int)); -static int process_rbat_addr PARAMS((int)); +static struct loop_bounds get_loop_bounds PARAMS ((int, int, unsigned char *, + unsigned char *, int, int)); +static void process_wlat_addr PARAMS ((int, int)); +static void process_wwat_addr PARAMS ((int, int)); +static void process_wbat_addr PARAMS ((int, int)); +static int process_rlat_addr PARAMS ((int)); +static int process_rwat_addr PARAMS ((int)); +static int process_rbat_addr PARAMS ((int)); static void INLINE wlat_fast PARAMS ((unsigned char *, int, int, int)); static void INLINE wwat_fast PARAMS ((unsigned char *, int, int, int, int)); static void INLINE wbat_fast PARAMS ((unsigned char *, int, int, int)); @@ -517,10 +522,10 @@ set_dr (n, exp) if (((n) & 1) || ((m) & 1)) \ RAISE_EXCEPTION (SIGILL); \ else \ - SET_DR(n, (DR(n) OP DR(m))); \ + SET_DR (n, (DR (n) OP DR (m))); \ } \ else \ - SET_FR(n, (FR(n) OP FR(m))); \ + SET_FR (n, (FR (n) OP FR (m))); \ } while (0) #define FP_UNARY(n, OP) \ @@ -530,10 +535,10 @@ set_dr (n, exp) if ((n) & 1) \ RAISE_EXCEPTION (SIGILL); \ else \ - SET_DR(n, (OP (DR(n)))); \ + SET_DR (n, (OP (DR (n)))); \ } \ else \ - SET_FR(n, (OP (FR(n)))); \ + SET_FR (n, (OP (FR (n)))); \ } while (0) #define FP_CMP(n, OP, m) \ @@ -543,10 +548,10 @@ set_dr (n, exp) if (((n) & 1) || ((m) & 1)) \ RAISE_EXCEPTION (SIGILL); \ else \ - SET_SR_T (DR(n) OP DR(m)); \ + SET_SR_T (DR (n) OP DR (m)); \ } \ else \ - SET_SR_T (FR(n) OP FR(m)); \ + SET_SR_T (FR (n) OP FR (m)); \ } while (0) static void @@ -575,7 +580,7 @@ wlat_fast (memory, x, value, maskl) unsigned char *memory; { int v = value; - unsigned int *p = (unsigned int *)(memory + x); + unsigned int *p = (unsigned int *) (memory + x); WRITE_BUSERROR (x, maskl, v, process_wlat_addr); *p = v; } @@ -585,7 +590,7 @@ wwat_fast (memory, x, value, maskw, endianw) unsigned char *memory; { int v = value; - unsigned short *p = (unsigned short *)(memory + (x ^ endianw)); + unsigned short *p = (unsigned short *) (memory + (x ^ endianw)); WRITE_BUSERROR (x, maskw, v, process_wwat_addr); *p = v; } @@ -606,7 +611,7 @@ static int INLINE rlat_fast (memory, x, maskl) unsigned char *memory; { - unsigned int *p = (unsigned int *)(memory + x); + unsigned int *p = (unsigned int *) (memory + x); READ_BUSERROR (x, maskl, process_rlat_addr); return *p; @@ -617,7 +622,7 @@ rwat_fast (memory, x, maskw, endianw) unsigned char *memory; int x, maskw, endianw; { - unsigned short *p = (unsigned short *)(memory + (x ^ endianw)); + unsigned short *p = (unsigned short *) (memory + (x ^ endianw)); READ_BUSERROR (x, maskw, process_rwat_addr); return *p; @@ -627,7 +632,7 @@ static int INLINE riat_fast (insn_ptr, endianw) unsigned char *insn_ptr; { - unsigned short *p = (unsigned short *)((size_t) insn_ptr ^ endianw); + unsigned short *p = (unsigned short *) ((size_t) insn_ptr ^ endianw); return *p; } @@ -650,10 +655,10 @@ rbat_fast (memory, x, maskb) #define WLAT(x,v) (wlat_fast (memory, x, v, maskl)) #define WBAT(x,v) (wbat_fast (memory, x, v, maskb)) -#define RUWAT(x) (RWAT(x) & 0xffff) -#define RSWAT(x) ((short)(RWAT(x))) -#define RSLAT(x) ((long)(RLAT(x))) -#define RSBAT(x) (SEXT(RBAT(x))) +#define RUWAT(x) (RWAT (x) & 0xffff) +#define RSWAT(x) ((short) (RWAT (x))) +#define RSLAT(x) ((long) (RLAT (x))) +#define RSBAT(x) (SEXT (RBAT (x))) #define RDAT(x, n) (do_rdat (memory, (x), (n), (maskl))) static int @@ -758,11 +763,11 @@ process_rbat_addr (addr) #define SEXT(x) (((x & 0xff) ^ (~0x7f))+0x80) #define SEXT12(x) (((x & 0xfff) ^ 0x800) - 0x800) -#define SEXTW(y) ((int)((short)y)) +#define SEXTW(y) ((int) ((short) y)) #if 0 -#define SEXT32(x) ((int)((x & 0xffffffff) ^ 0x80000000U) - 0x7fffffff - 1) +#define SEXT32(x) ((int) ((x & 0xffffffff) ^ 0x80000000U) - 0x7fffffff - 1) #else -#define SEXT32(x) ((int)(x)) +#define SEXT32(x) ((int) (x)) #endif #define SIGN32(x) (SEXT32 (x) >> 31) @@ -801,7 +806,7 @@ do { \ #define L(x) thislock = x; #define TL(x) if ((x) == prevlock) stalls++; -#define TB(x,y) if ((x) == prevlock || (y)==prevlock) stalls++; +#define TB(x,y) if ((x) == prevlock || (y) == prevlock) stalls++; #endif @@ -999,10 +1004,11 @@ trap (i, regs, insn_ptr, memory, maskl, maskw, endianw) Besides, it's quite dangerous. */ #if 0 case SYS_execve: - regs[0] = execve (ptr (regs[5]), (char **)ptr (regs[6]), (char **)ptr (regs[7])); + regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]), + (char **) ptr (regs[7])); break; case SYS_execv: - regs[0] = execve (ptr (regs[5]),(char **) ptr (regs[6]), 0); + regs[0] = execve (ptr (regs[5]), (char **) ptr (regs[6]), 0); break; #endif case SYS_pipe: @@ -1027,9 +1033,11 @@ trap (i, regs, insn_ptr, memory, maskl, maskw, endianw) case SYS_write: strnswap (regs[6], regs[7]); if (regs[5] == 1) - regs[0] = (int)callback->write_stdout (callback, ptr(regs[6]), regs[7]); + regs[0] = (int) callback->write_stdout (callback, + ptr (regs[6]), regs[7]); else - regs[0] = (int)callback->write (callback, regs[5], ptr (regs[6]), regs[7]); + regs[0] = (int) callback->write (callback, regs[5], + ptr (regs[6]), regs[7]); strnswap (regs[6], regs[7]); break; case SYS_lseek: @@ -1042,7 +1050,7 @@ trap (i, regs, insn_ptr, memory, maskl, maskw, endianw) { int len = strswaplen (regs[5]); strnswap (regs[5], len); - regs[0] = callback->open (callback,ptr (regs[5]), regs[6]); + regs[0] = callback->open (callback, ptr (regs[5]), regs[6]); strnswap (regs[5], len); break; } @@ -1333,11 +1341,11 @@ macw (regs, memory, n, m, endianw) long tempm, tempn; long prod, macl, sum; - tempm=RSWAT(regs[m]); regs[m]+=2; - tempn=RSWAT(regs[n]); regs[n]+=2; + tempm=RSWAT (regs[m]); regs[m]+=2; + tempn=RSWAT (regs[n]); regs[n]+=2; macl = MACL; - prod = (long)(short) tempm * (long)(short) tempn; + prod = (long) (short) tempm * (long) (short) tempn; sum = prod + macl; if (S) { @@ -1377,10 +1385,10 @@ macl (regs, memory, n, m) long long m64; /* 64 bit MAC */ }mac64; - tempm = RSLAT(regs[m]); + tempm = RSLAT (regs[m]); regs[m] += 4; - tempn = RSLAT(regs[n]); + tempn = RSLAT (regs[n]); regs[n] += 4; mach = MACH; @@ -1389,7 +1397,7 @@ macl (regs, memory, n, m) mac64.m[0] = macl; mac64.m[1] = mach; - ans = (long long)tempm * (long long)tempn; /* Multiply 32bit * 32bit */ + ans = (long long) tempm * (long long) tempn; /* Multiply 32bit * 32bit */ mac64.m64 += ans; /* Accumulate 64bit + 64 bit */ @@ -1411,6 +1419,32 @@ macl (regs, memory, n, m) MACH = mach; } + +/* GET_LOOP_BOUNDS {EXTENDED} + These two functions compute the actual starting and ending point + of the repeat loop, based on the RS and RE registers (repeat start, + repeat stop). The extended version is called for LDRC, and the + regular version is called for SETRC. The difference is that for + LDRC, the loop start and end instructions are literally the ones + pointed to by RS and RE -- for SETRC, they're not (see docs). */ + +static struct loop_bounds +get_loop_bounds_ext (rs, re, memory, mem_end, maskw, endianw) + int rs, re; + unsigned char *memory, *mem_end; + int maskw, endianw; +{ + struct loop_bounds loop; + + /* FIXME: should I verify RS < RE? */ + loop.start = PT2H (RS); /* FIXME not using the params? */ + loop.end = PT2H (RE & ~1); /* Ignore bit 0 of RE. */ + SKIP_INSN (loop.end); + if (loop.end >= mem_end) + loop.end = PT2H (0); + return loop; +} + float fsca_s (int in, double (*f) (double)) { @@ -1446,7 +1480,7 @@ fsrra_s (float in) architectural spec. */ frac = frexp (result, &exp); frac = ldexp (frac, 24); - error = 4.; /* 1 << 24-1-21 */ + error = 4.0; /* 1 << 24-1-21 */ /* use eps to compensate for possible 1 ulp error in our 'exact' result. */ eps = ldexp (1., -29); upper = floor (frac + error - eps); @@ -1499,8 +1533,7 @@ get_loop_bounds (rs, re, memory, mem_end, maskw, endianw) return loop; } -static void -ppi_insn(); +static void ppi_insn (); #include "ppi.c" @@ -1541,7 +1574,9 @@ init_dsp (abfd) int was_dsp = target_dsp; unsigned long mach = bfd_get_mach (abfd); - if (mach == bfd_mach_sh_dsp || mach == bfd_mach_sh3_dsp) + if (mach == bfd_mach_sh_dsp || + mach == bfd_mach_sh4al_dsp || + mach == bfd_mach_sh3_dsp) { int ram_area_size, xram_start, yram_start; int new_select; @@ -1556,7 +1591,7 @@ init_dsp (abfd) xram_start = 0x0800f000; ram_area_size = 0x1000; } - if (mach == bfd_mach_sh3_dsp) + if (mach == bfd_mach_sh3_dsp || mach == bfd_mach_sh4al_dsp) { /* SH7612: 8KB each for X & Y memory; @@ -1624,7 +1659,7 @@ static void init_pointers () { host_little_endian = 0; - *(char*)&host_little_endian = 1; + * (char*) &host_little_endian = 1; host_little_endian &= 1; if (saved_state.asregs.msize != 1 << sim_memory_size) @@ -1740,7 +1775,11 @@ sim_resume (sd, step, siggnal) memory = saved_state.asregs.memory; mem_end = memory + saved_state.asregs.msize; - loop = get_loop_bounds (RS, RE, memory, mem_end, maskw, endianw); + if (RE & 1) + loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw); + else + loop = get_loop_bounds (RS, RE, memory, mem_end, maskw, endianw); + insn_ptr = PT2H (saved_state.asregs.pc); CHECK_INSN_PTR (insn_ptr); @@ -1911,7 +1950,7 @@ sim_store_register (sd, rn, memory, length) unsigned val; init_pointers (); - val = swap (* (int *)memory); + val = swap (* (int *) memory); switch (rn) { case SIM_SH_R0_REGNUM: case SIM_SH_R1_REGNUM: case SIM_SH_R2_REGNUM: @@ -2203,7 +2242,8 @@ sim_info (sd, verbose) SIM_DESC sd; int verbose; { - double timetaken = (double) saved_state.asregs.ticks / (double) now_persec (); + double timetaken = + (double) saved_state.asregs.ticks / (double) now_persec (); double virttime = saved_state.asregs.cycles / 36.0e6; callback->printf_filtered (callback, "\n\n# instructions executed %10d\n", @@ -2357,7 +2397,7 @@ sim_create_inferior (sd, prog_bfd, argv, env) { /* Clear the registers. */ memset (&saved_state, 0, - (char*)&saved_state.asregs.end_of_registers - (char*)&saved_state); + (char*) &saved_state.asregs.end_of_registers - (char*) &saved_state); /* Set the PC. */ if (prog_bfd != NULL) @@ -2383,13 +2423,15 @@ sim_do_command (sd, cmd) } cmdsize = strlen (sms_cmd); - if (strncmp (cmd, sms_cmd, cmdsize) == 0 && strchr (" \t", cmd[cmdsize]) != NULL) + if (strncmp (cmd, sms_cmd, cmdsize) == 0 + && strchr (" \t", cmd[cmdsize]) != NULL) { parse_and_set_memory_size (cmd + cmdsize + 1); } else if (strcmp (cmd, "help") == 0) { - (callback->printf_filtered) (callback, "List of SH simulator commands:\n\n"); + (callback->printf_filtered) (callback, + "List of SH simulator commands:\n\n"); (callback->printf_filtered) (callback, "set-memory-size <n> -- Set the number of address bits to use\n"); (callback->printf_filtered) (callback, "\n"); } diff --git a/sim/testsuite/ChangeLog b/sim/testsuite/ChangeLog index cbd36e3e990..4e7b230be8b 100644 --- a/sim/testsuite/ChangeLog +++ b/sim/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2004-01-26 Chris Demetriou <cgd@broadcom.com> + + * sim/mips: New directory. Tests for the MIPS simulator. + +2004-01-23 Ben Elliston <bje@wasabisystems.com> + + * lib/sim-defs.exp (run_sim_test): Delete the .o and .x files if a + test passes. + 2003-10-10 Dave Brolley <brolley@redhat.com> * sim/frv/testutils.inc (or_gr_immed): New macro. diff --git a/sim/testsuite/lib/sim-defs.exp b/sim/testsuite/lib/sim-defs.exp index 017fcefb249..e75571760ad 100644 --- a/sim/testsuite/lib/sim-defs.exp +++ b/sim/testsuite/lib/sim-defs.exp @@ -289,6 +289,7 @@ proc run_sim_test { name requested_machs } { if { "$opts(xerror)" == "no" } { if [string match $opts(output) $output] { pass "$mach $testname" + file delete ${name}.o ${name}.x } else { verbose -log "output: $output" 3 verbose -log "pattern: $opts(output)" 3 @@ -304,6 +305,7 @@ proc run_sim_test { name requested_machs } { } else { if [string match $opts(output) $output] { pass "$mach $testname" + file delete ${name}.o ${name}.x } else { verbose -log "output: $output" 3 verbose -log "pattern: $opts(output)" 3 diff --git a/sim/v850/ChangeLog b/sim/v850/ChangeLog index 6f528ef0671..26b25aa6d13 100644 --- a/sim/v850/ChangeLog +++ b/sim/v850/ChangeLog @@ -1,3 +1,7 @@ +2004-01-18 Mark Kettenis <kettenis@gnu.org> + + * simops.c: Include <sys/types.h>. + 2003-09-05 Andrew Cagney <cagney@redhat.com> Nick Clifton <nickc@redhat.com> diff --git a/sim/v850/simops.c b/sim/v850/simops.c index 87868f5b748..38ec0a6af03 100644 --- a/sim/v850/simops.c +++ b/sim/v850/simops.c @@ -2,6 +2,8 @@ #include "v850_sim.h" #include "simops.h" +#include <sys/types.h> + #ifdef HAVE_UTIME_H #include <utime.h> #endif |