diff options
-rw-r--r-- | sim/.Sanitize | 1 | ||||
-rw-r--r-- | sim/sh/.Sanitize | 38 | ||||
-rw-r--r-- | sim/sh/ChangeLog | 4 | ||||
-rw-r--r-- | sim/sh/Makefile.in | 176 | ||||
-rw-r--r-- | sim/sh/configure.in | 33 | ||||
-rw-r--r-- | sim/sh/gencode.c | 703 | ||||
-rw-r--r-- | sim/sh/interp.c | 392 | ||||
-rw-r--r-- | sim/sh/run.c | 98 |
8 files changed, 1445 insertions, 0 deletions
diff --git a/sim/.Sanitize b/sim/.Sanitize index 41df081..b455fbd 100644 --- a/sim/.Sanitize +++ b/sim/.Sanitize @@ -29,6 +29,7 @@ configure.in endian.c h8300 h8500 +sh z8k Do-last: diff --git a/sim/sh/.Sanitize b/sim/sh/.Sanitize new file mode 100644 index 0000000..a76a514 --- /dev/null +++ b/sim/sh/.Sanitize @@ -0,0 +1,38 @@ +# Sanitize.in for devo. +# $Id$ +# + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +ChangeLog +Makefile.in +configure.in +interp.c +gencode.c +run.c + + +Do-last: + +# End of file. diff --git a/sim/sh/ChangeLog b/sim/sh/ChangeLog new file mode 100644 index 0000000..4c59bf5 --- /dev/null +++ b/sim/sh/ChangeLog @@ -0,0 +1,4 @@ +Mon Apr 26 18:01:10 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * created + diff --git a/sim/sh/Makefile.in b/sim/sh/Makefile.in new file mode 100644 index 0000000..8e542de --- /dev/null +++ b/sim/sh/Makefile.in @@ -0,0 +1,176 @@ +# Makefile template for Configure for the h8300sim library. +# Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc. +# Written by Cygnus Support. +# +# 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +srcdir = . + +prefix = /usr/local +program_transform_name = +exec_prefix = $(prefix) +bindir = $(exec_prefix)/bin +libdir = $(exec_prefix)/lib + +datadir = $(prefix)/lib +mandir = $(prefix)/man +man1dir = $(mandir)/man1 +man2dir = $(mandir)/man2 +man3dir = $(mandir)/man3 +man4dir = $(mandir)/man4 +man5dir = $(mandir)/man5 +man6dir = $(mandir)/man6 +man7dir = $(mandir)/man7 +man8dir = $(mandir)/man8 +man9dir = $(mandir)/man9 +infodir = $(prefix)/info +includedir = $(prefix)/include +oldincludedir = +docdir = $(srcdir)/doc + +SHELL = /bin/sh + +INSTALL = install -c +INSTALL_PROGRAM = $(INSTALL) +INSTALL_DATA = $(INSTALL) + +AR = ar +AR_FLAGS = qc +CFLAGS = -g +BISON = bison +MAKEINFO = makeinfo +RANLIB = ranlib + +INCDIR = $(srcdir)/../../include +CSEARCH = -I. -I$(srcdir) -I$(INCDIR) -I$(srcdir)/../../bfd +DEP = mkdep + +#### host, target, and site specific Makefile frags come in here. + +all: run + + +run: interp.o run.o table.o + $(CC) -o run interp.o table.o run.o ../../bfd/libbfd.a ../../libiberty/libiberty.a + +interp.o:interp.c code.c table.c +run.o:run.c + +code.c:gencode + ./gencode -x >code.c + indent code.c + +table.c:gencode + ./gencode -s >table.c + indent table.c + +gencode:gencode.c + cc -o gencode -g gencode.c + +#### host and target dependent Makefile fragments come in here. +### + +FLAGS_TO_PASS = \ + "against=$(against)" \ + "AR=$(AR)" \ + "AR_FLAGS=$(AR_FLAGS)" \ + "CC=$(CC)" \ + "CFLAGS=$(CFLAGS)" \ + "RANLIB=$(RANLIB)" \ + "MAKEINFO=$(MAKEINFO)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ + "BISON=$(BISON)" + +.c.o: + $(CC) -c $(CFLAGS) $(HDEFINES) $(TDEFINES) $(CSEARCH) $(CSWITCHES) $< + + + +.NOEXPORT: + +check: + +info: +clean-info: +install-info: + +# HDEPFILES comes from the host config; TDEPFILES from the target config. + + + +tags etags: TAGS + +TAGS: force + etags $(INCDIR)/*.h $(srcdir)/*.h $(srcdir)/*.c + +clean: + rm -f *.[oa] *~ core *.E *.p *.ip aout-params.h gen-aout + +clobber realclean: clean + rm -f libbfd.a TAGS + +# Mark everything as depending on config.status, since the timestamp on +# sysdep.h might actually move backwards if we reconfig and relink it +# to a different hosts/h-xxx.h file. This will force a recompile anyway. +RECONFIG = config.status + + + +# This target should be invoked before building a new release. +# 'VERSION' file must be present and contain a string of the form "x.y" +# +roll: + @V=`cat VERSION` ; \ + MAJ=`sed 's/\..*//' VERSION` ; \ + MIN=`sed 's/.*\.//' VERSION` ; \ + V=$$MAJ.`expr $$MIN + 1` ; \ + rm -f VERSION ; \ + echo $$V >VERSION ; \ + echo Version $$V + +# Dummy target to force execution of dependent targets. +# +force: + +install: + -parent=`echo $(bindir)|sed -e 's@/[^/]*$$@@'`; \ + if [ -d $$parent ] ; then true ; else mkdir $$parent ; fi + -if [ -d $(bindir) ] ; then true ; else mkdir $(bindir) ; fi + -parent=`echo $(man1dir)|sed -e 's@/[^/]*$$@@'`; \ + if [ -d $$parent ] ; then true ; else mkdir $$parent ; fi + -if [ -d $(man1dir) ] ; then true ; else mkdir $(man1dir) ; fi + -n=`t='$(program_transform_name)'; echo run | sed -e "" $$t`; \ + $(INSTALL_PROGRAM) run $(bindir)/$$n; \ + $(M_INSTALL) + + + +Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag) + $(SHELL) ./config.status + +dep: $(CFILES) + mkdep $(CFLAGS) $? + + +# What appears below is generated by a hacked mkdep using gcc -MM. + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY + diff --git a/sim/sh/configure.in b/sim/sh/configure.in new file mode 100644 index 0000000..22bc10a --- /dev/null +++ b/sim/sh/configure.in @@ -0,0 +1,33 @@ +# This file is a shell script that supplies the information necessary +# to tailor a template configure script into the configure script +# appropriate for this directory. For more information, check any +# existing configure script. + +srctrigger=compile.c +srcname="shsim" + +# per-host: + +. ${srcdir}/../../bfd/configure.host + +# Set up to make a link between the host's include file and "sysdep.h". +files="../../bfd/hosts/${my_host}.h" + +links="sysdep.h" + +if [ ! -f ${srcdir}/${files} ] ; then + if [ -n "${my_host}" ] ; then + echo '***' No file ${srcdir}/${files} 1>&2 + fi + echo '***' ${srcname} does not support host ${host} 1>&2 + exit 1 +fi + +host_makefile_frag= +if [ -f ${srcdir}/../../bfd/config/${my_host}.mh ] ; then + host_makefile_frag=../../bfd/config/${my_host}.mh +fi + +# per-target: + + diff --git a/sim/sh/gencode.c b/sim/sh/gencode.c new file mode 100644 index 0000000..8b495e5 --- /dev/null +++ b/sim/sh/gencode.c @@ -0,0 +1,703 @@ +/* Simulator/Opcode generator for the Hitachi Super-H architecture. + + Written by Steve Chamberlain of Cygnus Support. + sac@cygnus.com + + This file is part of SH sim + + + THIS SOFTWARE IS NOT COPYRIGHTED + + Cygnus offers the following for use in the public domain. Cygnus + makes no warranty with regard to the software or it's performance + and the user accepts the software "AS IS" with all faults. + + CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO + THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +/* This program generates the opcode table for the assembler and + the simulator code + + -t prints a pretty table for the assembler manual + -s generates the simulator code jump table + -x generates the simulator code switch statement + default generates the opcode tables + +*/ + +typedef struct +{ + char *name; + char *code; + char *stuff[10]; + int index; +} + +op; + + +op tab[] = +{ + + {"add #<imm>,<REG_N>", "0111nnnni8*1....", "R[n] += SEXT(i);"}, + {"add <REG_M>,<REG_N>", "0011nnnnmmmm1100", "R[n] += R[m];"}, + {"addc <REG_M>,<REG_N>", "0011nnnnmmmm1110", "ult = R[n]; R[n] += (R[m]+T); T = ult>R[n];"}, + {"addv <REG_M>,<REG_N>", "0011nnnnmmmm1111", + "long ans;", + "ans = R[n] + R[m];", + "T = ((~R[n] & R[m] & ans) | (R[n] & R[m] & ~ans)) >>31;", + "R[n] = ans;"}, + + {"and #<imm>,R0", "11001001i8*1....", "R0&=i;"}, + {"and <REG_M>,<REG_N>", "0010nnnnmmmm1001", "R[n]&=R[m];"}, + {"and.b #<imm>,@(R0,GBR)", "11001101i8*1....", "WBAT(GBR+R0, RBAT(GBR+R0) & i);"}, + + {"bf <bdisp8>", "10001011i8p1....", "if(T==0) {PC+=(SEXT(i)<<1)+2;C+=2;}"}, + {"bra <bdisp12>", "1010i12.........", "ult = PC; PC=PC+(i<<1)+2;SL(ult+2);"}, + {"bsr <bdisp12>", "1011i12.........", "PR = PC; PC=PC+(i<<1)+2;SL(PR+2);"}, + {"bt <bdisp8>", "10001001i8p1....", "if(T==1) {PC+=(SEXT(i)<<1)+2;C+=2;}"}, + {"clrmac", "0000000000101000", "MACH = MACL = 0;"}, + {"clrt", "0000000000001000", "T= 0;"}, + {"cmp/eq #<imm>,R0", "10001000i8*1....", "T = R0 == SEXT(i);"}, + {"cmp/eq <REG_M>,<REG_N>", "0011nnnnmmmm0000", "T=R[n]==R[m];"}, + {"cmp/ge <REG_M>,<REG_N>", "0011nnnnmmmm0011", "T=R[n]>=R[m];"}, + {"cmp/gt <REG_M>,<REG_N>", "0011nnnnmmmm0111", "T=R[n]>R[m];"}, + {"cmp/hi <REG_M>,<REG_N>", "0011nnnnmmmm0110", "T=UR[n]>UR[m];"}, + {"cmp/hs <REG_M>,<REG_N>", "0011nnnnmmmm0010", "T=UR[n]>=UR[m];"}, + {"cmp/pl <REG_N>", "0100nnnn00010101", "T = R[n]>0;"}, + {"cmp/pz <REG_N>", "0100nnnn00010001", "T = R[n]>=0;"}, + {"cmp/str <REG_M>,<REG_N>", "0010nnnnmmmm1100", "ult = R[n] ^ R[m]; T=((ult&0xff000000)==0) |((ult&0xff0000)==0) |((ult&0xff00)==0) |((ult&0xff)==0); "}, + {"div0s <REG_M>,<REG_N>", "0010nnnnmmmm0111", "Q=R[n]<0; M=R[m]<0; T=M!=Q;;"}, + {"div0u", "0000000000011001", "M=Q=T=0;"}, + {"div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100", "T=div1(R,n,m,T);"}, + {"exts.b <REG_M>,<REG_N>", "0110nnnnmmmm1110", "R[n] = SEXT(R[m]);"}, + {"exts.w <REG_M>,<REG_N>", "0110nnnnmmmm1111", "R[n] = SEXTW(R[m]);"}, + {"extu.b <REG_M>,<REG_N>", "0110nnnnmmmm1100", "R[n] = R[m] & 0xff;"}, + {"extu.w <REG_M>,<REG_N>", "0110nnnnmmmm1101", "R[n] = R[m] & 0xffff;"}, + {"jmp @<REG_N>", "0100nnnn00101011", "ult = PC; PC=R[n]-2; SL(ult+2);"}, + {"jsr @<REG_N>", "0100nnnn00001011", "PR = PC; PC=R[n]-2; SL(PR+2);"}, + {"ldc <REG_N>,GBR", "0100nnnn00011110", "GBR=R[n];"}, + {"ldc <REG_N>,SR", "0100nnnn00001110", "SET_SR(R[n]);"}, + {"ldc <REG_N>,VBR", "0100nnnn00101110", "VBR=R[n];"}, + {"ldc.l @<REG_N>+,GBR", "0100nnnn00010111", "GBR=RLAT(R[n]);R[n]+=4;;"}, + {"ldc.l @<REG_N>+,SR", "0100nnnn00000111", "SET_SR(RLAT(R[n]));R[n]+=4;;"}, + {"ldc.l @<REG_N>+,VBR", "0100nnnn00100111", "VBR=RLAT(R[n]);R[n]+=4;;"}, + {"lds <REG_N>,MACH", "0100nnnn00001010", "MACH = SEXT(R[n]);"}, + {"lds <REG_N>,MACL", "0100nnnn00011010", "MACL= R[n];"}, + {"lds <REG_N>,PR", "0100nnnn00101010", "PR = R[n];"}, + {"lds.l @<REG_N>+,MACH", "0100nnnn00000110", "MACH = SEXT(RLAT(R[n]));R[n]+=4;"}, + {"lds.l @<REG_N>+,MACL", "0100nnnn00010110", "MACL = RLAT(R[n]);R[n]+=4;"}, + {"lds.l @<REG_N>+,PR", "0100nnnn00100110", "PR = RLAT(R[n]);R[n]+=4;;"}, + {"mac.w @<REG_M>+,@<REG_N>+", "0100nnnnmmmm1111", "abort();"}, + {"mov #<imm>,<REG_N>", "1110nnnni8*1....", "R[n] = SEXT(i);"}, + {"mov <REG_M>,<REG_N>", "0110nnnnmmmm0011", "R[n] = R[m];"}, +{"mov.b <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0100", "WBAT(R[n]+R0, R[m]);"}, +{"mov.b <REG_M>,@-<REG_N>", "0010nnnnmmmm0100", "R[n]--; WBAT(R[n], R[m]);"}, + {"mov.b <REG_M>,@<REG_N>", "0010nnnnmmmm0000", "WBAT(R[n], R[m]);"}, + {"mov.b @(<disp>,<REG_M>),R0", "10000100mmmmi4*1", "R0=RBAT(i+R[m]);"}, + {"mov.b @(<disp>,GBR),R0", "11000100i8*1....", "R0=RBAT(i+GBR);"}, + {"mov.b @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1100", "R[n]=RBAT(R0+R[m]);"}, +{"mov.b @<REG_M>+,<REG_N>", "0110nnnnmmmm0100", "R[n] = RBAT(R[m]);R[m]++;"}, + {"mov.b @<REG_M>,<REG_N>", "0110nnnnmmmm0000", "R[n]=RBAT(R[m]);"}, + {"mov.b R0,@(<disp>,<REG_M>)", "10000000mmmmi4*1", "R0=RBAT(i+R[m]);"}, + {"mov.b R0,@(<disp>,GBR)", "11000000i8*1....", "R0 = RBAT(i+GBR);"}, + {"mov.l <REG_M>,@(<disp>,<REG_N>)", "0001nnnnmmmmi4*4", "WLAT(i+R[n],R[m]);"}, + {"mov.l <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0110", "WLAT(R0+R[n],R[m]);"}, +{"mov.l <REG_M>,@-<REG_N>", "0010nnnnmmmm0110", "R[n]-=4;WLAT(R[n],R[m]);"}, + {"mov.l <REG_M>,@<REG_N>", "0010nnnnmmmm0010", "WLAT(R[n], R[m]);"}, + {"mov.l @(<disp>,<REG_N>),<REG_M>", "0101nnnnmmmmi4*4", "R[m]=RLAT(i+R[n]);"}, + {"mov.l @(<disp>,GBR),R0", "11000110i4*4", "R0=RLAT(i+GBR);"}, + {"mov.l @(<disp>,PC),<REG_N>", "1101nnnni8p4....", "R[n]=RLAT(i+4+PC);"}, + {"mov.l @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1110", "R[n]=RLAT(R0+R[m]);"}, +{"mov.l @<REG_M>+,<REG_N>", "0110nnnnmmmm0110", "R[n]=RLAT(R[m]);R[m]+=4;"}, + {"mov.l @<REG_M>,<REG_N>", "0110nnnnmmmm0010", "R[n]=RLAT(R[m]);"}, + {"mov.l R0,@(<disp>,GBR)", "11000010i8*4....", "R0=RLAT(R0+GBR);"}, + {"mov.w <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0101", "WWAT(R0+R[n],R[m]);"}, +{"mov.w <REG_M>,@-<REG_N>", "0010nnnnmmmm0101", "R[n]-=2;WWAT(R[n],R[m]);"}, + {"mov.w <REG_M>,@<REG_N>", "0010nnnnmmmm0001", "WWAT(R[n],R[m]);"}, + {"mov.w @(<disp>,<REG_M>),R0", "10000101mmmmi4*2", "R0=RSWAT(i+R[m]);"}, + {"mov.w @(<disp>,GBR),R0", "11000101i8*2....", "R0=RSWAT(i+GBR);"}, + {"mov.w @(<disp>,PC),<REG_N>", "1001nnnni8p2....", "R[n]=RSWAT(PC+i+4);"}, +{"mov.w @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1101", "R[n]=RSWAT(R0+R[m]);"}, +{"mov.w @<REG_M>+,<REG_N>", "0110nnnnmmmm0101", "R[n]=RSWAT(R[m]);R[m]+=2;"}, + {"mov.w @<REG_M>,<REG_N>", "0110nnnnmmmm0001", "R[n]=RSWAT(R[m]);"}, + {"mov.w R0,@(<disp>,<REG_M>)", "10000001mmmmi4*2", "R0=RSWAT(i+R[m]);"}, + {"mov.w R0,@(<disp>,GBR)", "11000001i8*2....", "R0=RSWAT(i+GBR);"}, + {"mova @(<disp>,PC),R0", "11000111i8p4....", "R0=i+4+PC;"}, + {"movt <REG_N>", "0000nnnn00101001", "R[n]=T;"}, + {"muls <REG_M>,<REG_N>", "0010nnnnmmmm1111", + "MACL=((long)(short)R[n])*((long)(short)R[m]);"}, +{"mulu <REG_M>,<REG_N>","0010nnnnmmmm1110", "MACL=((unsigned long)(unsigned short)R[n])*((unsigned long)(unsigned short)R[m]);"}, + {"neg <REG_M>,<REG_N>", "0110nnnnmmmm1011", "R[n] = - R[m];"}, + {"negc <REG_M>,<REG_N>", "0110nnnnmmmm1010", "ult=0-R[m];R[n]=ult-T;T=SBIT(R[n])!=SBIT(ult);"}, + {"nop", "0000000000001001", ""}, + {"not <REG_M>,<REG_N>", "0110nnnnmmmm0111", "R[n]=~R[m];"}, + {"or #<imm>,R0", "11001011i8*1....", "R0|=i;"}, + {"or <REG_M>,<REG_N>", "0010nnnnmmmm1011", "R[n]|=R[m];"}, + {"or.b #<imm>,@(R0,GBR)", "11001111i8*1....", "WBAT(R0+GBR,RBAT(R0+GBR)|i);"}, + {"rotcl <REG_N>", "0100nnnn00100100", "ult = R[n] <0;R[n] = (R[n]<<1)|T;T=ult;"}, + {"rotcr <REG_N>", "0100nnnn00100101", "ult = R[n]&1;R[n]=(UR[n]>>1)|(T<<31);T=ult;"}, + {"rotl <REG_N>", "0100nnnn00000100", "T=R[n]<0;R[n]<<=1;R[n]|=T;"}, + {"rotr <REG_N>", "0100nnnn00000101", "T=R[n]&1;UR[n]>>=1;R[n]|=(T<<31);"}, + {"rte", "0000000000101011", "abort();"}, + {"rts", "0000000000001011", "ult=PC;PC=PR+2;SL(ult+2);"}, + {"sett", "0000000000011000", "T=1;"}, + {"shal <REG_N>", "0100nnnn00100000", "T=R[n]<0; R[n]<<=1;"}, + {"shar <REG_N>", "0100nnnn00100001", "T=R[n]&1; R[n]>>=1;"}, + {"shll <REG_N>", "0100nnnn00000000", "T=R[n]<0; R[n]<<=1;"}, + {"shll16 <REG_N>", "0100nnnn00101000", "R[n]<<=16;"}, + {"shll2 <REG_N>", "0100nnnn00001000", "R[n]<<=2;"}, + {"shll8 <REG_N>", "0100nnnn00011000", "R[n]<<=8;"}, + {"shlr <REG_N>", "0100nnnn00000001", "T=R[n]&1;R[n]=UR[n]>>1;"}, + {"shlr16 <REG_N>", "0100nnnn00101001", "R[n]=UR[n]>>16;"}, + {"shlr2 <REG_N>", "0100nnnn00001001", "R[n]=UR[n]>>2;"}, + {"shlr8 <REG_N>", "0100nnnn00011001", "R[n]=UR[n]>>8;"}, + {"sleep", "0000000000011011", "abort();"}, + {"stc GBR,<REG_N>", "0000nnnn00010010", "R[n]=GBR;"}, + {"stc SR,<REG_N>", "0000nnnn00000010", "R[n]=GET_SR();"}, + {"stc VBR,<REG_N>", "0000nnnn00100010", "R[n]=VBR;"}, + {"stc.l GBR,@-<REG_N>", "0100nnnn00010011", "R[n]-=4;WLAT(R[n],GBR);;"}, + {"stc.l SR,@-<REG_N>", "0100nnnn00000011", "R[n]-=4;WLAT(R[n],GET_SR());"}, + {"stc.l VBR,@-<REG_N>", "0100nnnn00100011", "R[n]-=4;WLAT(R[n],VBR);"}, + {"sts MACH,<REG_N>", "0000nnnn00001010", "R[n]=MACH;"}, + {"sts MACL,<REG_N>", "0000nnnn00011010", "R[n]=MACL;"}, + {"sts PR,<REG_N>", "0000nnnn00101010", "R[n]=PR;"}, + {"sts.l MACH,@-<REG_N>", "0100nnnn00000010", "R[n]-=4;WLAT(R[n],MACH);"}, + {"sts.l MACL,@-<REG_N>", "0100nnnn00010010", "R[n]-=4;WLAT(R[n],MACL);"}, + {"sts.l PR,@-<REG_N>", "0100nnnn00100010", "R[n]-=4;WLAT(R[n],PR);"}, + {"sub <REG_M>,<REG_N>", "0011nnnnmmmm1000", "R[n]-=R[m];"}, + {"subc <REG_M>,<REG_N>", "0011nnnnmmmm1010", "ult = R[n];R[n]-=R[m]+T;T=ult<UR[n];"}, + {"subv <REG_M>,<REG_N>", "0011nnnnmmmm1011", "abort();"}, + {"swap.b <REG_M>,<REG_N>", "0110nnnnmmmm1000", "R[n]=((R[m]<<8)&0xff00)|((R[m]>>8)&0x00ff);"}, + {"swap.w <REG_M>,<REG_N>", "0110nnnnmmmm1001", "R[n]=((R[m]<<16)&0xffff0000)|((R[m]>>16)&0x00ffff);"}, + {"tas.b @<REG_N>", "0100nnnn00011011", "ult=RBAT(R[n]);T=ult==0;WBAT(R[n],ult|0x80);"}, + {"trapa #<imm>", "11000011i8*1....", "trap(i,R);"}, + {"tst #<imm>,R0", "11001000i8*1....", "T=(R0&i)==0;"}, + {"tst <REG_M>,<REG_N>", "0010nnnnmmmm1000", "T=(R[n]&R[m])==0;"}, + {"tst.b #<imm>,@(R0,GBR)", "11001100i8*1....", "T=(RBAT(GBR+R0)&i)==0;"}, + {"xor #<imm>,R0", "11001010i8*1....", "R0^=i;"}, + {"xor <REG_M>,<REG_N>", "0010nnnnmmmm1010", "R[n]^=R[m];"}, + {"xor.b #<imm>,@(R0,GBR)", "11001110i8*1....", "ult=RBAT(GBR+R0);ult^=i;WBAT(GBR+R0,ult);"}, + {"xtrct <REG_M>,<REG_N>", "0010nnnnmmmm1101", "R[n]=((R[n]>>16)&0xffff)|((R[m]<<16)&0xffff0000);"}, + +#if 0 +{"mul.l <REG_M>,<REG_N>","0000nnnnmmmm0111","/* mull */"}, +{"dmuls.l <REG_M>,<REG_N>","0011nnnnmmmm1101","/* dmuls.l */"}, +{"dmulu.l <REG_M>,<REG_N>","0011nnnnmmmm0101",""}, +{"mac.l @<REG_M>+,@<REG_N>+","0000nnnnmmmm1111",""}, +{"bt/s <bdisp8>","10001101i8p1....",""}, +{"bf/s <bdisp8>","10001111i8p1....",""}, +{"dt <REG_N>","0100nnnn00010000",""}, +{"braf @<REG_N>","0000nnnn00100011",""}, +{"bsrf @<REG_N>","0000nnnn00000011",""}, +{"mulu <REG_M>,<REG_N>","0010nnnnmmmm1110",""}, +{"muls <REG_M>,<REG_N>","0010nnnnmmmm1111",""}, +#endif + + {0, 0}}; + +/* Tables of things to put into enums for sh-opc.h */ +static char *nibble_type_list[] = +{ + "HEX_0", + "HEX_1", + "HEX_2", + "HEX_3", + "HEX_4", + "HEX_5", + "HEX_6", + "HEX_7", + "HEX_8", + "HEX_9", + "HEX_A", + "HEX_B", + "HEX_C", + "HEX_D", + "HEX_E", + "HEX_F", + "REG_N", + "REG_M", + "BRANCH_12", + "BRANCH_8", + "DISP_8", + "DISP_4", + "IMM_4", + "IMM_4BY2", + "IMM_4BY4", + "PCRELIMM_8BY2", + "PCRELIMM_8BY4", + "IMM_8", + "IMM_8BY2", + "IMM_8BY4", + 0 +}; +static +char *arg_type_list[] = +{ + "A_END", + "A_BDISP12", + "A_BDISP8", + "A_DEC_M", + "A_DEC_N", + "A_DISP_GBR", + "A_DISP_PC", + "A_DISP_REG_M", + "A_DISP_REG_N", + "A_GBR", + "A_IMM", + "A_INC_M", + "A_INC_N", + "A_IND_M", + "A_IND_N", + "A_IND_R0_REG_M", + "A_IND_R0_REG_N", + "A_MACH", + "A_MACL", + "A_PR", + "A_R0", + "A_R0_GBR", + "A_REG_M", + "A_REG_N", + "A_SR", + "A_VBR", + 0, +}; + +static void +make_enum_list (name, s) + char *name; + char **s; +{ + int i = 1; + printf ("typedef enum {\n"); + while (*s) + { + printf ("\t%s,\n", *s, i); + s++; + i++; + } + printf ("} %s;\n", name); +} + +static void +gengastab () +{ + op *p; + sorttab (); + for (p = tab; p->name; p++) + { + printf ("%s %-30s\n", p->code, p->name); + } + + +} + + +static void +genopc () +{ + op *p; + make_enum_list ("sh_nibble_type", nibble_type_list); + make_enum_list ("sh_arg_type", arg_type_list); + + printf ("typedef struct {\n"); + printf ("char *name;\n"); + printf ("sh_arg_type arg[3];\n"); + printf ("sh_nibble_type nibbles[4];\n"); + printf ("} sh_opcode_info;\n"); + printf ("#ifdef DEFINE_TABLE\n"); + printf ("sh_opcode_info sh_table[]={\n"); + for (p = tab; p->name; p++) + { + printf ("\n\/\* %s %-20s*/", p->code, p->name); + think (p); + } + printf ("0};\n"); + printf ("#endif\n"); +} + + +m (ptr, a, rep) + char **ptr; + char *a; + char *rep; +{ + int l = strlen (a); + if (strncmp (*ptr, a, l) == 0) + { + printf ("%s", rep); + *ptr += l; + if (**ptr) + printf (","); + } +} + +think (o) + op *o; +{ + int t; + char *n; + char *p; + + printf ("{\""); + n = o->name; + while (*n && *n != ' ') + { + printf ("%c", *n); + n++; + } + printf ("\",{"); + + p = n; + + if (!*p) + { + printf ("0"); + } + while (*p) + { + while (*p == ',' || *p == ' ') + p++; + m (&p, "#<imm>", "A_IMM"); + m (&p, "R0", "A_R0"); + m (&p, "<REG_N>", "A_REG_N"); + m (&p, "@<REG_N>+", "A_INC_N"); + m (&p, "@<REG_N>", "A_IND_N"); + m (&p, "@-<REG_N>", "A_DEC_N"); + m (&p, "<REG_M>", " A_REG_M"); + m (&p, "@<REG_M>+", "A_INC_M"); + m (&p, "@<REG_M>", "A_IND_M"); + m (&p, "@-<REG_M>", "A_DEC_M"); + m (&p, "@(<disp>,PC)", "A_DISP_PC"); + m (&p, "@(<disp>,<REG_M>)", "A_DISP_REG_M"); + m (&p, "@(<disp>,<REG_N>)", "A_DISP_REG_N"); + m (&p, "@(R0,<REG_N>)", "A_IND_R0_REG_N"); + m (&p, "@(R0,<REG_M>)", "A_IND_R0_REG_M"); + m (&p, "@(<disp>,GBR)", "A_DISP_GBR"); + m (&p, "@(R0,GBR)", "A_R0_GBR"); + m (&p, "<bdisp8>", "A_BDISP8"); + m (&p, "<bdisp12>", "A_BDISP12"); + m (&p, "SR", "A_SR"); + m (&p, "GBR", "A_GBR"); + m (&p, "VBR", "A_VBR"); + m (&p, "MACH", "A_MACH"); + m (&p, "MACL", "A_MACL"); + m (&p, "PR", "A_PR"); + + } + printf ("},{"); + + p = o->code; + while (*p) + { + m (&p, "0000", "HEX_0"); + m (&p, "0001", "HEX_1"); + m (&p, "0010", "HEX_2"); + m (&p, "0011", "HEX_3"); + m (&p, "0100", "HEX_4"); + m (&p, "0101", "HEX_5"); + m (&p, "0110", "HEX_6"); + m (&p, "0111", "HEX_7"); + + m (&p, "1000", "HEX_8"); + m (&p, "1001", "HEX_9"); + m (&p, "1010", "HEX_A"); + m (&p, "1011", "HEX_B"); + m (&p, "1100", "HEX_C"); + m (&p, "1101", "HEX_D"); + m (&p, "1110", "HEX_E"); + m (&p, "1111", "HEX_F"); + m (&p, "i8*1....", "IMM_8"); + m (&p, "i4*1", "IMM_4"); + m (&p, "i8p4....", "PCRELIMM_8BY4"); + m (&p, "i8p2....", "PCRELIMM_8BY2"); + m (&p, "i8*2....", "IMM_8BY2"); + m (&p, "i4*2", "IMM_4BY2"); + m (&p, "i8*4....", "IMM_8BY4"); + m (&p, "i4*4", "IMM_4BY4"); + m (&p, "i12.........", "BRANCH_12"); + m (&p, "i8p1....", "BRANCH_8"); + m (&p, "nnnn", "REG_N"); + m (&p, "mmmm", "REG_M"); + + } + printf ("}},\n"); +} + +qfunc (a, b) + op *a; + op *b; +{ + char bufa[9]; + char bufb[9]; + memcpy (bufa, a->code, 4); + memcpy (bufa + 4, a->code + 12, 4); + bufa[8] = 0; + + memcpy (bufb, b->code, 4); + memcpy (bufb + 4, b->code + 12, 4); + bufb[8] = 0; + return (strcmp (bufa, bufb)); +} + + +sorttab () +{ + op *p = tab; + + int len = 0; + + while (p->name) + { + p++; + len++; + } + + qsort (tab, len, sizeof (*p), qfunc); + +} + +/* 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 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*/ + +expand_opcode (shift, val, i, s) + char *s; +{ + int j; + + if (*s == 0) + { + table[val] = i; + } + else + { + switch (s[0]) + { + + case '0': + case '1': + { + + int n = bton (s); + if (n >= 0) + { + expand_opcode (shift - 4, val | (n << shift), i, s + 4); + } + break; + } + case 'n': + case 'm': + for (j = 0; j < 16; j++) + { + expand_opcode (shift - 4, val | (j << shift), i, s + 4); + + } + break; + + default: + for (j = 0; j < (1 << (shift + 4)); j++) + { + table[val | j] = i; + } + } + } +} + +/* Print the jump table used to index an opcode into a switch + statement entry */ +static void + +dumptable () +{ + int lump = 256; + int online = 16; + + int i = 0; + + while (i < 1 << 16) + { + int j = 0; + int nc = 0; + + printf ("unsigned char sh_jump_table%x[%d]={\n", i, lump); + + while (j < lump) + { + int k = 0; + while (k < online) + { + printf ("%2d", table[i + j + k]); + if (j + k < lump) + printf (","); + + k++; + } + j += k; + printf ("\n"); + } + i += j; + printf ("};\n"); + } + +} + + +static void +filltable () +{ + op *p; + int index = 1; + + sorttab (); + for (p = tab; p->name; p++) + { + p->index = index++; + expand_opcode (12, 0, p->index, p->code); + } +} + +static void +gensim () +{ + op *p; + int j; + + printf ("{\n"); + printf ("switch (jump_table[iword]) {\n"); + + for (p = tab; p->name; p++) + { + int sextbit = -1; + + char *s = p->code; + + printf ("\/\* %s %s *\/\n", p->name, p->code); + printf ("case %d: \n", p->index); + + printf ("{\n"); + while (*s) + { + switch (*s) + { + case '0': + case '1': + case '.': + s += 4; + break; + case 'n': + printf ("int n = (iword >>8) & 0xf;\n"); + s += 4; + break; + case 'm': + printf ("int m = (iword >>4) & 0xf;\n"); + s += 4; + + break; + + case 'i': + printf ("int i = (iword & 0x"); + + switch (s[1]) + { + case '4': + printf ("f"); + break; + case '8': + printf ("ff"); + break; + case '1': + sextbit = 12; + + printf ("fff"); + break; + } + printf (")"); + + switch (s[3]) + { + case '1': + break; + case '2': + printf ("<<1"); + break; + case '4': + printf ("<<2"); + break; + } + printf (";\n"); + s += 4; + } + } + if (sextbit>0) + { + printf("i = (i ^ (1<<%d))-(1<<%d);\n",sextbit-1,sextbit-1); + } + + for (j = 0; j < 10; j++) + { + if (p->stuff[j]) + { + printf ("%s\n", p->stuff[j]); + } + } + printf ("break;\n", p->stuff); + printf ("}\n"); + } + printf ("}\n}\n"); +} + + +int +main (ac, av) + char **av; + +{ + if (ac > 1) + { + if (strcmp (av[1], "-t") == 0) + { + gengastab (); + } + else if (strcmp (av[1], "-s") == 0) + { + filltable (); + dumptable (); + + } + else if (strcmp (av[1], "-x") == 0) + { + filltable (); + gensim (); + } + } + else + { + genopc (); + } + return 0; +} diff --git a/sim/sh/interp.c b/sim/sh/interp.c new file mode 100644 index 0000000..152ab05 --- /dev/null +++ b/sim/sh/interp.c @@ -0,0 +1,392 @@ +#define MSIZE (256*1024) +#define MMASKL ((MSIZE -1) & ~3) +#define MMASKW ((MSIZE -1) & ~1) +#define MMASKB ((MSIZE -1) & ~0) +/* Simulator for the Hitachi SH architecture. + + Written by Steve Chamberlain of Cygnus Support. + sac@cygnus.com + + This file is part of SH sim + + + THIS SOFTWARE IS NOT COPYRIGHTED + + Cygnus offers the following for use in the public domain. Cygnus + makes no warranty with regard to the software or it's performance + and the user accepts the software "AS IS" with all faults. + + CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO + THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +*/ + +#include <signal.h> +#include <sys/times.h> +#include <sys/param.h> + +#define O_RECOMPILE 85 +#define DEFINE_TABLE + +#define DISASSEMBLER_TABLE + +#define SBIT(x) ((x)&sbit) +#define R0 saved_state.asregs.regs[0] +#define Rn saved_state.asregs.regs[n] +#define Rm saved_state.asregs.regs[m] + +#define UR0 (unsigned long)(saved_state.asregs.regs[0]) +#define UR (unsigned long)R +#define UR (unsigned long)R + +#define SR0 saved_state.asregs.regs[0] + +#define GBR saved_state.asregs.gbr +#define VBR saved_state.asregs.vbr +#define MACH saved_state.asregs.mach +#define MACL saved_state.asregs.macl +#define GET_SR() (saved_state.asregs.sr.bits.t = T, saved_state.asregs.sr.word) +#define SET_SR(x) {saved_state.asregs.sr.word = (x); T =saved_state.asregs.sr.bits.t;} + +#define PC pc +#define C cycles + +#define LMEM(x) *((long *)(memory+(x&maskl))) +#define BMEM(x) *((char *)(memory+(x&maskb))) +#define UWMEM(x) *((unsigned short *)(memory+(x&maskw))) +#define SWMEM(x) *((short *)(memory+(x&maskw))) +#define WLAT(x,value) (LMEM(x) = value) +#define RLAT(x) (LMEM(x)) + +#define WWAT(x,value) (UWMEM(x) = value) +#define RSWAT(x) (SWMEM(x)) +#define RUWAT(x) (UWMEM(x)) + +#define WBAT(x,value) (BMEM(x) = value) +#define RBAT(x) (BMEM(x)) + +#define SEXT(x) ((int)((char)x)) +#define SEXTW(y) ((int)((short)y)) +#define M saved_state.asregs.sr.bits.m +#define Q saved_state.asregs.sr.bits.q +#define SL(TEMPPC) iword= RUWAT(TEMPPC); goto top; +int debug; +typedef union +{ + + struct + { + + int regs[16]; + int pc; + int pr; + + int gbr; + int vbr; + int mach; + int macl; + + + union + { + struct + { + int d0:22; + int m:1; + int q:1; + int i:4; + int d1:2; + int s:1; + int t:1; + } + bits; + int word; + } + sr; + int ticks; + int cycles; + int insts; + unsigned char *memory; + int exception; + + } + asregs; + int asints[25]; + +} + +saved_state_type; + + + +saved_state_type saved_state; + + + +/*#include "../opcodes/sh-opc.h"*/ + + +static int +get_now () +{ + struct tms b; + times (&b); + return b.tms_utime + b.tms_stime; +} + +static int +now_persec () +{ + return HZ; +} + +/* simulate a monitor trap */ +trap (i, regs) + int *regs; +{ + switch (i) + { + case 1: + printf ("%c", regs[0]); + break; + case 2: + saved_state.asregs.exception = SIGQUIT; + break; + case 255: + saved_state.asregs.exception = SIGILL; + break; + } + +} +void +control_c (sig, code, scp, addr) + int sig; + int code; + char *scp; + char *addr; +{ + saved_state.asregs.exception = SIGINT; +} + + +int div1(R,m,n,T) + int *R; + int m; + int n; + int T; +{ + unsigned long tmp0; + unsigned char old_q, tmp1; + + old_q = Q; + Q= R[n] <0; + + R[n] <<=1; + R[n] |= T; + + switch (old_q) + { + case 0: + switch (M) + { + case 0: + tmp0 = R[n]; + R[n] -= R[m]; + tmp1 = (R[n] > tmp0) != Q; + break; + case 1: + tmp0 = R[n]; + R[n] += R[m]; + tmp1 = (R[n] < tmp0) == Q; + break; + } + break; + case 1: + switch (M) + { + case 0: + tmp0 = R[n]; + R[n] += R[m]; + tmp1 = (R[n] < tmp0) != Q; + break; + case 1: + tmp0 = R[n]; + R[n] -= R[m]; + tmp1 = (R[n] > tmp0) == Q; + break; + } + break; + + } + + T=(Q==M); +return T; + +} + + +int +sim_resume (step) +{ + static int init1; + int pc; +register int cycles = 0; +register int insts = 0; + int tick_start = get_now (); + void (*prev) (); + extern unsigned char sh_jump_table0[]; + + register unsigned char *jump_table = sh_jump_table0; + + register int *R = &(saved_state.asregs.regs[0]); + register int T; + register int PR; + + register int maskb = MMASKB; + register int maskw = MMASKW; + register int maskl = MMASKL; + register unsigned char *memory = saved_state.asregs.memory; + register int sbit = (1<<31); + + prev = signal (SIGINT, control_c); + + if (step) + { + saved_state.asregs.exception = SIGTRAP; + } + else + { + saved_state.asregs.exception = 0; + } + + pc = saved_state.asregs.pc; + PR = saved_state.asregs.pr; + T = saved_state.asregs.sr.bits.t; + + do + { + unsigned int iword = RUWAT (pc); + unsigned long ult; + + insts++; + top: + +#include "code.c" + + pc += 2; + cycles++; + } + while (!saved_state.asregs.exception); + + if (saved_state.asregs.exception == SIGILL) + { + pc-=2; + } + + saved_state.asregs.ticks += get_now () - tick_start; + saved_state.asregs.cycles += cycles; + saved_state.asregs.insts += insts; + saved_state.asregs.pc = pc; + saved_state.asregs.sr.bits.t = T; + saved_state.asregs.pr = PR; + + signal (SIGINT, prev); +} + + + +void +sim_write (addr, buffer, size) + long int addr; + unsigned char *buffer; + int size; +{ + int i; + init_pointers (); + + for (i = 0; i < size; i++) + { + saved_state.asregs.memory[MMASKB & (addr + i)] = buffer[i]; + } +} + +void +sim_read (addr, buffer, size) + long int addr; + char *buffer; + int size; +{ + int i; + + init_pointers (); + + for (i = 0; i < size; i++) + { + buffer[i] = saved_state.asregs.memory[MMASKB & (addr + i)]; + } +} + + +sim_store_register (rn, value) + int rn; + int value; +{ + saved_state.asregs.regs[rn] = value; +} + +sim_fetch_register (rn, buf) + int rn; + char *buf; +{ + + int value = ((int *) (&saved_state))[rn]; + + buf[0] = value >> 24; + buf[1] = value >> 16; + buf[2] = value >> 8; + buf[3] = value >> 0; + +} + +int +sim_trace () +{ + + int i; + return 0; + +} + +sim_stop_signal () +{ + return saved_state.asregs.exception; +} + +sim_set_pc (x) +{ + saved_state.asregs.pc = x; +} + + + +sim_info () +{ + double timetaken = (double) saved_state.asregs.ticks / (double) now_persec (); + double virttime = saved_state.asregs.cycles / 10.0e6; + + printf ("\n\ninstructions executed %10d\n", saved_state.asregs.insts); + printf ("cycles %10d\n", saved_state.asregs.cycles); + printf ("real time taken %10.4f\n", timetaken); + printf ("cycles/second %10d\n", (int)(saved_state.asregs.cycles/timetaken)); + printf ("virtual time taked %10.4f\n", virttime); + printf ("simulation ratio %10.4f\n", virttime / timetaken); +} + +init_pointers () +{ + if (!saved_state.asregs.memory) + { + saved_state.asregs.memory = (unsigned char *) (calloc (64, MSIZE / 64)); + } +} diff --git a/sim/sh/run.c b/sim/sh/run.c new file mode 100644 index 0000000..f7d987f --- /dev/null +++ b/sim/sh/run.c @@ -0,0 +1,98 @@ +/* run front end support for H8/500 + Copyright (C) 1987, 1992 Free Software Foundation, Inc. + +This file is part of H8300 SIM + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +/* Steve Chamberlain + sac@cygnus.com */ + +#include "bfd.h" +#include "sysdep.h" + +int +main (ac, av) + int ac; + char **av; +{ + bfd *abfd; + bfd_vma start_address; + asection *s; + int i; + int verbose = 0; + int trace = 0; + char *name = ""; + for (i = 1; i < ac; i++) + { + if (strcmp (av[i], "-v") == 0) + { + verbose = 1; + } + else if (strcmp (av[i], "-t") == 0) + { + trace = 1; + } + else + { + name = av[i]; + } + } + if (verbose) + { + printf ("run %s\n", name); + } + abfd = bfd_openr (name, "coff-sh"); + if (abfd) + { + + if (bfd_check_format (abfd, bfd_object)) + { + + for (s = abfd->sections; s; s = s->next) + { + unsigned char *buffer = malloc (bfd_section_size (abfd, s)); + bfd_get_section_contents (abfd, + s, + buffer, + 0, + bfd_section_size (abfd, s)); + sim_write (s->vma, buffer, bfd_section_size (abfd, s)); + } + + start_address = bfd_get_start_address (abfd); + sim_set_pc (start_address); + if (trace) + { + int done = 0; + while (!done) + { + done = sim_trace (); + } + } + else + { + sim_resume (0, 0); + } + if (verbose) + sim_info (); + + return 0; + } + } + + return 1; +} |