From: Ian Carmichael Date: Fri, 16 Jan 1998 19:27:02 +0000 (+0000) Subject: * Initial Device Support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1e1e3b618f80c51d59a6ebeefe282bb920d4a0e8;p=binutils-gdb.git * Initial Device Support * *Modified Files: * .Sanitize ChangeLog *Added Files: * Makefile.in README.Cygnus config.in configure configure.in * device.c device.h dma.c dma.h engine-sky.c gencode.c gpuif.c * gpuif.h hardware.c hardware.h interp.c m16.igen mdmx.igen * mips.dc mips.igen pke0.c pke0.h pke1.c pke1.h r5900.igen * sim-main.h tconfig.in vr5400.igen vu0.c vu0.h vu1.c vu1.h --- diff --git a/sim/txvu/.Sanitize b/sim/txvu/.Sanitize index eecd57e5cc5..362eae05e81 100644 --- a/sim/txvu/.Sanitize +++ b/sim/txvu/.Sanitize @@ -25,6 +25,38 @@ Do-first: Things-to-keep: ChangeLog +interp.c +configure.in +Makefile.in +config.in +tconfig.in +README.Cygnus +configure +gencode.c +m16.igen +mdmx.igen +mips.dc +mips.igen +r5900.igen +sim-main.h +vr5400.igen +engine-sky.c +gpuif.h +dma.h +device.c +gpuif.c +device.h +dma.c +vu0.h +pke0.h +vu1.h +pke1.h +vu1.c +vu0.c +pke0.c +pke1.c +hardware.c +hardware.h Things-to-lose: diff --git a/sim/txvu/ChangeLog b/sim/txvu/ChangeLog index 1aea3eabc90..f6c8673c352 100644 --- a/sim/txvu/ChangeLog +++ b/sim/txvu/ChangeLog @@ -1,3 +1,7 @@ +Fri Jan 16 14:25:54 1998 Ian Carmichael + + * Initial Device Support + Thu Jan 15 10:25:54 1998 Ian Carmichael * ChangeLog created diff --git a/sim/txvu/Makefile.in b/sim/txvu/Makefile.in new file mode 100644 index 00000000000..006e4406394 --- /dev/null +++ b/sim/txvu/Makefile.in @@ -0,0 +1,260 @@ +# template for Configure for the MIPS simulator. +# Written by Cygnus Support. + +## COMMON_PRE_CONFIG_FRAG + +srcdir=@srcdir@ +srcroot=$(srcdir)/../../ + +SIM_NO_OBJ = + +SIM_IGEN_OBJ = \ + support.o \ + itable.o \ + semantics.o \ + idecode.o \ + icache.o \ + irun.o + +SIM_M16_OBJ = \ + $(SIM_IGEN_OBJ) = \ + m16_support.o \ + m16_itable.o \ + m16_semantics.o \ + m16_idecode.o \ + m16_icache.o \ + m16_engine.o \ + m16_irun.o + +SIM_OBJS = \ + $(SIM_@sim_gen@_OBJ) \ + $(SIM_NEW_COMMON_OBJS) \ + engine-sky.o \ + interp.o \ + hardware.o \ + device.o \ + gpuif.o \ + dma.o \ + vu0.o \ + vu1.o \ + pke0.o \ + pke1.o \ + sim-hload.o \ + sim-engine.o \ + sim-stop.o \ + sim-resume.o \ + sim-reason.o + + +# List of flags to always pass to $(CC). +SIM_SUBTARGET=@SIM_SUBTARGET@ + +SIM_NO_CFLAGS = -DWITH_IGEN=0 +SIM_IGEN_CFLAGS = -DWITH_IGEN=1 +SIM_M16_CFLAGS = -DWITH_IGEN=1 + +# FIXME: Hack to find syscall.h? Better support for syscall.h +# is in progress. +SIM_EXTRA_CFLAGS = \ + $(SIM_SUBTARGET) \ + -I$(srcdir)/../../newlib/libc/sys/idt \ + $(SIM_@sim_gen@_CFLAGS) + +SIM_EXTRA_CLEAN = clean-igen clean-m16 clean-extra + +SIM_EXTRA_ALL = $(SIM_@sim_gen@_ALL) + +# List of main object files for `run'. +SIM_RUN_OBJS = nrun.o + + + +## COMMON_POST_CONFIG_FRAG + +interp.o: $(srcdir)/interp.c config.h sim-main.h oengine.c + +oengine.c: gencode + ./gencode @SIMCONF@ > tmp-oengine + mv tmp-oengine oengine.c + +gencode: gencode.o getopt.o getopt1.o + $(CC_FOR_BUILD) -o $@ gencode.o getopt.o getopt1.o + +gencode.o: $(srcdir)/gencode.c + $(CC_FOR_BUILD) -c -g -I${srcroot}/include $(srcdir)/gencode.c + +getopt.o: $(srcdir)/../../libiberty/getopt.c + $(CC_FOR_BUILD) -c -g -I${srcroot}/include $(srcdir)/../../libiberty/getopt.c +getopt1.o: $(srcdir)/../../libiberty/getopt1.c + $(CC_FOR_BUILD) -c -g -I${srcroot}/include $(srcdir)/../../libiberty/getopt1.c + + +../igen/igen: + cd ../igen && $(MAKE) + +IGEN_TRACE= # -G omit-line-numbers # -G trace-rule-selection -G trace-rule-rejection -G trace-entries +IGEN_INSN=$(srcdir)/mips.igen +IGEN_DC=$(srcdir)/mips.dc +IGEN_INCLUDE=\ + $(start-sanitize-r5900) \ + $(srcdir)/r5900.igen \ + $(end-sanitize-r5900) \ + $(start-sanitize-vr5400) \ + $(srcdir)/vr5400.igen \ + $(srcdir)/mdmx.igen \ + $(end-sanitize-vr5400) \ + $(srcdir)/m16.igen + +SIM_IGEN_ALL = tmp-igen + +BUILT_SRC_FROM_IGEN = \ + icache.h \ + icache.c \ + idecode.h \ + idecode.c \ + semantics.h \ + semantics.c \ + model.h \ + model.c \ + support.h \ + support.c \ + itable.h \ + itable.c \ + engine.h \ + engine.c \ + irun.c + +$(BUILT_SRC_FROM_IGEN): tmp-igen + +.PHONY: clean-igen +clean-igen: + rm -f $(BUILT_SRC_FROM_IGEN) + rm -f tmp-igen + +tmp-igen: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) + cd ../igen && $(MAKE) + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + @sim_igen_flags@ \ + -G gen-direct-access \ + -G gen-zero-r0 \ + -i $(IGEN_INSN) \ + -o $(IGEN_DC) \ + -x \ + -n icache.h -hc tmp-icache.h \ + -n icache.c -c tmp-icache.c \ + -n semantics.h -hs tmp-semantics.h \ + -n semantics.c -s tmp-semantics.c \ + -n idecode.h -hd tmp-idecode.h \ + -n idecode.c -d tmp-idecode.c \ + -n model.h -hm tmp-model.h \ + -n model.c -m tmp-model.c \ + -n support.h -hf tmp-support.h \ + -n support.c -f tmp-support.c \ + -n itable.h -ht tmp-itable.h \ + -n itable.c -t tmp-itable.c \ + -n engine.h -he tmp-engine.h \ + -n engine.c -e tmp-engine.c \ + -n irun.c -r tmp-irun.c + $(srcdir)/../../move-if-change tmp-icache.h icache.h + $(srcdir)/../../move-if-change tmp-icache.c icache.c + $(srcdir)/../../move-if-change tmp-idecode.h idecode.h + $(srcdir)/../../move-if-change tmp-idecode.c idecode.c + $(srcdir)/../../move-if-change tmp-semantics.h semantics.h + $(srcdir)/../../move-if-change tmp-semantics.c semantics.c + $(srcdir)/../../move-if-change tmp-model.h model.h + $(srcdir)/../../move-if-change tmp-model.c model.c + $(srcdir)/../../move-if-change tmp-support.h support.h + $(srcdir)/../../move-if-change tmp-support.c support.c + $(srcdir)/../../move-if-change tmp-itable.h itable.h + $(srcdir)/../../move-if-change tmp-itable.c itable.c + $(srcdir)/../../move-if-change tmp-engine.h engine.h + $(srcdir)/../../move-if-change tmp-engine.c engine.c + $(srcdir)/../../move-if-change tmp-irun.c irun.c + touch tmp-igen + +semantics.o: sim-main.h $(SIM_EXTRA_DEPS) +engine.o: sim-main.h $(SIM_EXTRA_DEPS) +support.o: sim-main.h $(SIM_EXTRA_DEPS) +idecode.o: sim-main.h $(SIM_EXTRA_DEPS) +itable.o: sim-main.h $(SIM_EXTRA_DEPS) + + + +SIM_M16_ALL = tmp-igen $(SIM_M16_ALL) + +BUILT_SRC_FROM_M16 = \ + m16_icache.h \ + m16_icache.c \ + m16_idecode.h \ + m16_idecode.c \ + m16_semantics.h \ + m16_semantics.c \ + m16_model.h \ + m16_model.c \ + m16_support.h \ + m16_support.c \ + m16_itable.h \ + m16_itable.c \ + m16_engine.h \ + m16_engine.c \ + m16_irun.c + +$(BUILT_SRC_FROM_M16): tmp-m16 + +.PHONY: clean-m16 +clean-m16: + rm -f $(BUILT_SRC_FROM_M16) + rm -f tmp-m16 + +tmp-m16: $(IGEN_INSN) $(IGEN_DC) ../igen/igen $(IGEN_INCLUDE) + cd ../igen && $(MAKE) + ../igen/igen \ + $(IGEN_TRACE) \ + -I $(srcdir) \ + -Werror \ + -Wnodiscard \ + -F 16 \ + -M mips16 \ + -G gen-direct-access \ + -i $(IGEN_INSN) \ + -o $(IGEN_DC) \ + -x \ + -n m16_icache.h -hc tmp-icache.h \ + -n m16_icache.c -c tmp-icache.c \ + -n m16_semantics.h -hs tmp-semantics.h \ + -n m16_semantics.c -s tmp-semantics.c \ + -n m16_idecode.h -hd tmp-idecode.h \ + -n m16_idecode.c -d tmp-idecode.c \ + -n m16_model.h -hm tmp-model.h \ + -n m16_model.c -m tmp-model.c \ + -n m16_support.h -hf tmp-support.h \ + -n m16_support.c -f tmp-support.c \ + -n m16_itable.h -ht tmp-itable.h \ + -n m16_itable.c -t tmp-itable.c \ + -n m16_engine.h -he tmp-engine.h \ + -n m16_engine.c -e tmp-engine.c \ + -n m16_irun.c -r tmp-irun.c + $(srcdir)/../../move-if-change tmp-icache.h m16_icache.h + $(srcdir)/../../move-if-change tmp-icache.c m16_icache.c + $(srcdir)/../../move-if-change tmp-idecode.h m16_idecode.h + $(srcdir)/../../move-if-change tmp-idecode.c m16_idecode.c + $(srcdir)/../../move-if-change tmp-semantics.h m16_semantics.h + $(srcdir)/../../move-if-change tmp-semantics.c m16_semantics.c + $(srcdir)/../../move-if-change tmp-model.h m16_model.h + $(srcdir)/../../move-if-change tmp-model.c m16_model.c + $(srcdir)/../../move-if-change tmp-support.h m16_support.h + $(srcdir)/../../move-if-change tmp-support.c m16_support.c + $(srcdir)/../../move-if-change tmp-itable.h m16_itable.h + $(srcdir)/../../move-if-change tmp-itable.c m16_itable.c + $(srcdir)/../../move-if-change tmp-engine.h m16_engine.h + $(srcdir)/../../move-if-change tmp-engine.c m16_engine.c + $(srcdir)/../../move-if-change tmp-irun.c m16_irun.c + touch tmp-m16 + + +clean-extra: + rm -f gencode oengine.c tmp.igen diff --git a/sim/txvu/README.Cygnus b/sim/txvu/README.Cygnus new file mode 100644 index 00000000000..06c5e433830 --- /dev/null +++ b/sim/txvu/README.Cygnus @@ -0,0 +1,38 @@ +> README.Cygnus +------------------------------------------------------------------------------- + +The following are the main reasons for constructing the simulator as a +generator: + +1) Avoid large fixed decode source file, with lots of #ifs controlling + the compilation. i.e. keep the source cleaner, smaller and easier + to parse. + +2) Allow optimum code to be created, without run-time checks on + instruction types. Ensure that the simulator engine only includes + code for the architecture being targetted. e.g. This avoids + run-time checks on ISA conformance, aswell as increasing + throughput. + +3) Allow updates to the instruction sets to be added quickly. Having a + table means that the information is together, and is easier to + manipulate. Having the table generate the engine, rather than the + run-time parse the table gives higher performance at simulation + time. + +4) Keep all the similar simulation code together. i.e. have a single + place where, for example, the addition code is held. This ensures that + updates to the simulation are not spread over a large flat source + file maintained by the developer. + +------------------------------------------------------------------------------- + +To keep the simulator simple (and to avoid the slight chance of +mis-matched files) the manifests describing an engine, and the +simulator engine itself, are held in the same source file. + +This means that the engine must be included twice, with the first pass +controlled by the SIM_MANIFESTS definition. + +------------------------------------------------------------------------------- +> EOF README.Cygnus diff --git a/sim/txvu/config.in b/sim/txvu/config.in new file mode 100644 index 00000000000..f28acc641d3 --- /dev/null +++ b/sim/txvu/config.in @@ -0,0 +1,50 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* Define if you have the aint function. */ +#undef HAVE_AINT + +/* Define if you have the anint function. */ +#undef HAVE_ANINT + +/* Define if you have the getrusage function. */ +#undef HAVE_GETRUSAGE + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the sqrt function. */ +#undef HAVE_SQRT + +/* Define if you have the time function. */ +#undef HAVE_TIME + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the m library (-lm). */ +#undef HAVE_LIBM diff --git a/sim/txvu/configure b/sim/txvu/configure new file mode 100755 index 00000000000..53d86a69db9 --- /dev/null +++ b/sim/txvu/configure @@ -0,0 +1,2476 @@ +#! /bin/sh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12.1 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-sim-bswap Use Host specific BSWAP instruction." +ac_help="$ac_help + --enable-sim-cflags=opts Extra CFLAGS for use in building simulator" +ac_help="$ac_help + --enable-sim-debug=opts Enable debugging flags" +ac_help="$ac_help + --enable-sim-stdio Specify whether to use stdio for console input/output." +ac_help="$ac_help + --enable-sim-trace=opts Enable tracing flags" +ac_help="$ac_help + --enable-sim-profile=opts Enable profiling flags" +ac_help="$ac_help + --enable-sim-inline=inlines Specify which functions should be inlined." +ac_help="$ac_help + --enable-sim-alignment=align Specify strict, nonstrict or forced alignment of memory accesses." +ac_help="$ac_help + --enable-sim-hostendian=end Specify host byte endian orientation." +ac_help="$ac_help + --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings" +ac_help="$ac_help + --enable-sim-endian=endian Specify target byte endian orientation." +ac_help="$ac_help + --enable-sim-bitsize=n Specify target bitsize (32 or 64)." +ac_help="$ac_help + --enable-sim-float Specify that the target processor has floating point hardware." +ac_help="$ac_help + --enable-sim-igen=opts Enable IGEN simulator" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12.1" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=Makefile.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:628: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:649: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:666: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + +# autoconf.info says this should be called right after AC_INIT. + + +ac_aux_dir= +for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:739: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:760: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:778: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:822: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:851: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:899: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:933: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:938: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:962: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1001: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Put a plausible default for CC_FOR_BUILD in Makefile. +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi + + + + +AR=${AR-ar} + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1067: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# Check for common headers. +# FIXME: Seems to me this can cause problems for i386-windows hosts. +# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*. +for ac_hdr in stdlib.h string.h strings.h unistd.h time.h sys/time.h sys/resource.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1101: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1111: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getrusage time sigaction +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1140: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +. ${srcdir}/../../bfd/configure.host + + + +# Check whether --enable-sim-bswap or --disable-sim-bswap was given. +if test "${enable_sim_bswap+set}" = set; then + enableval="$enable_sim_bswap" + case "${enableval}" in + yes) sim_bswap="-DWITH_BSWAP=1 -DUSE_BSWAP=1";; + no) sim_bswap="-DWITH_BSWAP=0";; + *) { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";; +esac +if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then + echo "Setting bswap flags = $sim_bswap" 6>&1 +fi +else + sim_bswap="" +fi + + + +# Check whether --enable-sim-cflags or --disable-sim-cflags was given. +if test "${enable_sim_cflags+set}" = set; then + enableval="$enable_sim_cflags" + case "${enableval}" in + yes) sim_cflags="-O2";; + trace) { echo "configure: error: "Please use --enable-sim-debug instead."" 1>&2; exit 1; }; sim_cflags="";; + no) sim_cflags="";; + *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then + echo "Setting sim cflags = $sim_cflags" 6>&1 +fi +else + sim_cflags="" +fi + + + +# Check whether --enable-sim-debug or --disable-sim-debug was given. +if test "${enable_sim_debug+set}" = set; then + enableval="$enable_sim_debug" + case "${enableval}" in + yes) sim_debug="-DDEBUG=7 -DWITH_DEBUG=7";; + no) sim_debug="-DDEBUG=0 -DWITH_DEBUG=0";; + *) sim_debug="-DDEBUG='(${enableval})' -DWITH_DEBUG='(${enableval})'";; +esac +if test x"$silent" != x"yes" && test x"$sim_debug" != x""; then + echo "Setting sim debug = $sim_debug" 6>&1 +fi +else + sim_debug="" +fi + + + +# Check whether --enable-sim-stdio or --disable-sim-stdio was given. +if test "${enable_sim_stdio+set}" = set; then + enableval="$enable_sim_stdio" + case "${enableval}" in + yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; + no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";; +esac +if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then + echo "Setting stdio flags = $sim_stdio" 6>&1 +fi +else + sim_stdio="" +fi + + + +# Check whether --enable-sim-trace or --disable-sim-trace was given. +if test "${enable_sim_trace+set}" = set; then + enableval="$enable_sim_trace" + case "${enableval}" in + yes) sim_trace="-DTRACE=1 -DWITH_TRACE=-1";; + no) sim_trace="-DTRACE=0 -DWITH_TRACE=0";; + [-0-9]*) + sim_trace="-DTRACE='(${enableval})' -DWITH_TRACE='(${enableval})'";; + [a-z]*) + sim_trace="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_trace" = x; then + sim_trace="-DWITH_TRACE='(TRACE_$x" + else + sim_trace="${sim_trace}|TRACE_$x" + fi + done + sim_trace="$sim_trace)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then + echo "Setting sim trace = $sim_trace" 6>&1 +fi +else + sim_trace="" +fi + + + +# Check whether --enable-sim-profile or --disable-sim-profile was given. +if test "${enable_sim_profile+set}" = set; then + enableval="$enable_sim_profile" + case "${enableval}" in + yes) sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1";; + no) sim_profile="-DPROFILE=0 -DWITH_PROFILE=0";; + [-0-9]*) + sim_profile="-DPROFILE='(${enableval})' -DWITH_PROFILE='(${enableval})'";; + [a-z]*) + sim_profile="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_profile" = x; then + sim_profile="-DWITH_PROFILE='(PROFILE_$x" + else + sim_profile="${sim_profile}|PROFILE_$x" + fi + done + sim_profile="$sim_profile)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_profile" != x""; then + echo "Setting sim profile = $sim_profile" 6>&1 +fi +else + sim_profile="" +fi + + + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:1323: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { +int i; +; return 0; } +EOF +if { (eval echo configure:1345: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <&1 +fi +else + if test x"$GCC" != "x" -a x"${default_sim_inline}" != "x" ; then + sim_inline="${default_sim_inline}" + if test x"$silent" != x"yes"; then + echo "Setting inline flags = $sim_inline" 6>&1 + fi +else + sim_inline="" +fi +fi + +wire_alignment="NONSTRICT_ALIGNMENT" +default_alignment="" + +# Check whether --enable-sim-alignment or --disable-sim-alignment was given. +if test "${enable_sim_alignment+set}" = set; then + enableval="$enable_sim_alignment" + case "${enableval}" in + strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";; + nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";; + forced | FORCED) sim_alignment="-DWITH_ALIGNMENT=FORCED_ALIGNMENT";; + yes) if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}" + else + if test x"$default_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${default_alignment}" + else + echo "No hard-wired alignment for target $target" 1>&6 + sim_alignment="-DWITH_ALIGNMENT=0" + fi + fi;; + no) if test x"$default_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}" + else + if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${wire_alignment}" + else + echo "No default alignment for target $target" 1>&6 + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=0" + fi + fi;; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";; +esac +if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then + echo "Setting alignment flags = $sim_alignment" 6>&1 +fi +else + if test x"$default_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}" +else + if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}" + else + sim_alignment= + fi +fi +fi + + +# Check whether --enable-sim-hostendian or --disable-sim-hostendian was given. +if test "${enable_sim_hostendian+set}" = set; then + enableval="$enable_sim_hostendian" + case "${enableval}" in + no) sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";; + b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";; + l*|L*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN";; + *) { echo "configure: error: "Unknown value $enableval for --enable-sim-hostendian"" 1>&2; exit 1; }; sim_hostendian="";; +esac +if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then + echo "Setting hostendian flags = $sim_hostendian" 6>&1 +fi +else + +if test "x$cross_compiling" = "xno"; then + echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:1489: checking whether byte ordering is bigendian" >&5 +if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_bigendian=unknown +# See if sys/param.h defines the BYTE_ORDER macro. +cat > conftest.$ac_ext < +#include +int main() { + +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif +; return 0; } +EOF +if { (eval echo configure:1507: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + # It does; now see whether it defined to BIG_ENDIAN or not. +cat > conftest.$ac_ext < +#include +int main() { + +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif +; return 0; } +EOF +if { (eval echo configure:1522: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_bigendian=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_bigendian=no +fi +rm -f conftest* +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +if test $ac_cv_c_bigendian = unknown; then +if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_c_bigendian=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_bigendian=yes +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_c_bigendian" 1>&6 +if test $ac_cv_c_bigendian = yes; then + cat >> confdefs.h <<\EOF +#define WORDS_BIGENDIAN 1 +EOF + +fi + + if test $ac_cv_c_bigendian = yes; then + sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN" + else + sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN" + fi +else + sim_hostendian="-DWITH_HOST_BYTE_ORDER=0" +fi +fi + + +# Check whether --enable-sim-warnings or --disable-sim-warnings was given. +if test "${enable_sim_warnings+set}" = set; then + enableval="$enable_sim_warnings" + case "${enableval}" in + yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations ";; + no) sim_warnings="-w";; + *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then + echo "Setting warning flags = $sim_warnings" 6>&1 +fi +else + sim_warnings="" +fi + + + +# Ensure a reasonable default simulator is constructed: +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) SIMCONF="-mips1 -mcpu=r1900 -mno-fp --warnings";; +# end-sanitize-tx19 +# start-sanitize-tx49 + mips64tx49*-*-*) SIMCONF="-mips3 --warnings -mcpu=r4900";; +# end-sanitize-tx49 +# start-sanitize-r5900 + mips64r59*-*-*) SIMCONF="-mips3 --warnings -mcpu=r5900";; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) SIMCONF="-mips3 --warnings -mcpu=r5900";; +# end-sanitize-sky + mips64*-*-*) SIMCONF="-mips0 --warnings";; + mips16*-*-*) SIMCONF="-mips0 --warnings";; + mips*-*-*) SIMCONF="-mips2 --warnings";; + *) SIMCONF="-mips0 --warnings";; +esac + + +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";; +# end-sanitize-tx19 + *) SIM_SUBTARGET="";; +esac + + + +# +# Select the byte order of the target +# +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) mips_endian=0 ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) mips_endian=LITTLE_ENDIAN ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) mips_endian=LITTLE_ENDIAN ;; +# end-sanitize-sky + mips64*-*-*) mips_endian=0 ;; + mips16*-*-*) mips_endian=0 ;; + mips*-*-*) mips_endian=0 ;; + *) mips_endian=0 ;; +esac + +wire_endian="$mips_endian" +default_endian="" +# Check whether --enable-sim-endian or --disable-sim-endian was given. +if test "${enable_sim_endian+set}" = set; then + enableval="$enable_sim_endian" + case "${enableval}" in + b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";; + l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";; + yes) if test x"$wire_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}" + else + if test x"$default_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${default_endian}" + else + echo "No hard-wired endian for target $target" 1>&6 + sim_endian="-DWITH_TARGET_BYTE_ORDER=0" + fi + fi;; + no) if test x"$default_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}" + else + if test x"$wire_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${wire_endian}" + else + echo "No default endian for target $target" 1>&6 + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=0" + fi + fi;; + *) { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";; +esac +if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then + echo "Setting endian flags = $sim_endian" 6>&1 +fi +else + if test x"$default_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}" +else + if test x"$wire_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}" + else + sim_endian= + fi +fi +fi + + + +# +# Select the bitsize of the target +# +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) mips_bitsize=32 ; mips_msb=31 ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) mips_bitsize=64 ; mips_msb=63 ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) mips_bitsize=64 ; mips_msb=63 ;; +# end-sanitize-sky + mips64*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips16*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips*-*-*) mips_bitsize=32 ; mips_msb=31 ;; + *) mips_bitsize=64 ; mips_msb=63 ;; +esac +wire_bitsize="$mips_bitsize" +wire_msb="$mips_msb" +# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given. +if test "${enable_sim_bitsize+set}" = set; then + enableval="$enable_sim_bitsize" + case "${enableval}" in + 64,63) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=63";; + 32,31) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=31";; + 64,0) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0";; + 32,0) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0";; + 32) if test x"$wire_msb" != x -a x"$wire_msb" != x0; then + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=31" + else + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0" + fi ;; + 64) if test x"$wire_msb" != x -a x"$wire_msb" != x0; then + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=63" + else + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=0" + fi ;; + *) { echo "configure: error: "--enable-sim-bitsize was given $enableval. Expected 32 or 64"" 1>&2; exit 1; }; sim_bitsize="";; +esac +if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then + echo "Setting bitsize flags = $sim_bitsize" 6>&1 +fi +else + sim_bitsize="" +if test x"$wire_bitsize" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_WORD_BITSIZE=$wire_bitsize" +fi +if test x"$wire_msb" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_WORD_MSB=$wire_msb" +fi +fi + + + +# +# Select the floating hardware support of the target +# +mips_fpu=HARDWARE_FLOATING_POINT +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) mips_fpu=SOFT_FLOATING_POINT ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) mips_fpu=HARD_FLOATING_POINT ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) mips_fpu=HARD_FLOATING_POINT ;; +# end-sanitize-sky + mips64*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips16*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + *) mips_fpu=HARD_FLOATING_POINT ;; +esac + +default_sim_floating_point="$mips_fpu" +# Check whether --enable-sim-float or --disable-sim-float was given. +if test "${enable_sim_float+set}" = set; then + enableval="$enable_sim_float" + case "${enableval}" in + yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";; + no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";; +esac +if test x"$silent" != x"yes" && test x"$sim_float" != x""; then + echo "Setting float flags = $sim_float" 6>&1 +fi +else + sim_float="-DWITH_FLOATING_POINT=${default_sim_floating_point}" +fi + + + +# +# Select the IGEN architecture +# +sim_use_gen=NO +sim_igen_machine="-M mipsIV" +sim_m16_machine="-M mips16" +sim_igen_filter="32,64,f" +sim_m16_filter="16" + +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) sim_default_gen=M16 + sim_igen_machine="-M tx19" + sim_m16_machine="-M tx19" + sim_igen_filter="32" + sim_m16_filter="16" + ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) sim_default_gen=IGEN + sim_igen_machine="-M r5900" + ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) sim_default_gen=IGEN + sim_igen_machine="-M r5900" + ;; +# end-sanitize-sky +# start-sanitize-vr5400 + mips64vr54*-*-*) sim_default_gen=IGEN + sim_use_gen=IGEN + sim_igen_machine="-M vr5000,vr5400 -G gen-multi-sim=vr5400" + ;; +# end-sanitize-vr5400 + mips64vr5*-*-*) sim_default_gen=IGEN + sim_use_gen=IGEN + sim_igen_machine="-M vr5000" +# start-sanitize-vr5400 + sim_igen_machine="-M vr5000,vr5400 -G gen-multi-sim=vr5000" +# end-sanitize-vr5400 + ;; + mips16*-*-*) sim_default_gen=M16 + ;; + mips32*-*-*) sim_default_gen=IGEN + sim_igen_filter="32,f" + ;; + *) sim_default_gen=IGEN + ;; +esac +sim_igen_flags="-F ${sim_igen_filter} ${sim_igen_machine}" +sim_m16_flags=" -F ${sim_m16_filter} ${sim_m16_machine}" + + + +# +# Enable igen +# +# Check whether --enable-sim-igen or --disable-sim-igen was given. +if test "${enable_sim_igen+set}" = set; then + enableval="$enable_sim_igen" + case "${enableval}" in + yes) sim_gen="${sim_default_gen}";; + no) sim_gen=NO;; + 16) sim_gen=M16;; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_gen="";; +esac +if test x"$silent" != x"yes" && test x"$sim_gen" != x""; then + echo "Setting sim_igen = $sim_gen" 6>&1 +fi +else + sim_gen="${sim_use_gen}" +fi + + + + +for ac_hdr in string.h strings.h stdlib.h stdlib.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1875: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1885: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for fabs in -lm""... $ac_c" 1>&6 +echo "configure:1912: checking for fabs in -lm" >&5 +ac_lib_var=`echo m'_'fabs | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lm $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + +for ac_func in aint anint sqrt +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1961: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1989: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1 | grep ac_space` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12.1" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile.sim:Makefile.in Make-common.sim:../common/Make-common.in .gdbinit:../common/gdbinit.in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@sim_environment@%$sim_environment%g +s%@sim_alignment@%$sim_alignment%g +s%@sim_assert@%$sim_assert%g +s%@sim_bitsize@%$sim_bitsize%g +s%@sim_endian@%$sim_endian%g +s%@sim_hostendian@%$sim_hostendian%g +s%@sim_float@%$sim_float%g +s%@sim_scache@%$sim_scache%g +s%@sim_default_model@%$sim_default_model%g +s%@sim_hardware@%$sim_hardware%g +s%@sim_inline@%$sim_inline%g +s%@sim_packages@%$sim_packages%g +s%@sim_regparm@%$sim_regparm%g +s%@sim_reserved_bits@%$sim_reserved_bits%g +s%@sim_smp@%$sim_smp%g +s%@sim_stdcall@%$sim_stdcall%g +s%@sim_xor_endian@%$sim_xor_endian%g +s%@sim_warnings@%$sim_warnings%g +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@HDEFINES@%$HDEFINES%g +s%@AR@%$AR%g +s%@RANLIB@%$RANLIB%g +s%@CPP@%$CPP%g +s%@sim_bswap@%$sim_bswap%g +s%@sim_cflags@%$sim_cflags%g +s%@sim_debug@%$sim_debug%g +s%@sim_stdio@%$sim_stdio%g +s%@sim_trace@%$sim_trace%g +s%@sim_profile@%$sim_profile%g +s%@SIMCONF@%$SIMCONF%g +s%@SIM_SUBTARGET@%$SIM_SUBTARGET%g +s%@sim_igen_flags@%$sim_igen_flags%g +s%@sim_m16_flags@%$sim_m16_flags%g +s%@sim_gen@%$sim_gen%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=$1; shift; ac_dests=$* + set $ac_sources; ac_source=$1; shift; ac_sources=$* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; } + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; } + fi +done +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +case "x$CONFIG_FILES" in + xMakefile*) + echo "Merging Makefile.sim+Make-common.sim into Makefile ..." + rm -f Makesim1.tmp Makesim2.tmp Makefile + sed -n -e '/^## COMMON_PRE_/,/^## End COMMON_PRE_/ p' Makesim1.tmp + sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' Makesim2.tmp + sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \ + -e '/^## COMMON_POST_/ r Makesim2.tmp' \ + Makefile + rm -f Makefile.sim Make-common.sim Makesim1.tmp Makesim2.tmp + ;; + esac + case "x$CONFIG_HEADERS" in xconfig.h:config.in) echo > stamp-h ;; esac + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/sim/txvu/configure.in b/sim/txvu/configure.in new file mode 100644 index 00000000000..6c01e7f0a90 --- /dev/null +++ b/sim/txvu/configure.in @@ -0,0 +1,185 @@ +dnl Process this file with autoconf to produce a configure script. +sinclude(../common/aclocal.m4) +AC_PREREQ(2.5)dnl +AC_INIT(Makefile.in) + +SIM_AC_COMMON + +dnl Options available in this module +SIM_AC_OPTION_INLINE(0) +SIM_AC_OPTION_ALIGNMENT(NONSTRICT_ALIGNMENT) +SIM_AC_OPTION_HOSTENDIAN +SIM_AC_OPTION_WARNINGS + + +# Ensure a reasonable default simulator is constructed: +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) SIMCONF="-mips1 -mcpu=r1900 -mno-fp --warnings";; +# end-sanitize-tx19 +# start-sanitize-tx49 + mips64tx49*-*-*) SIMCONF="-mips3 --warnings -mcpu=r4900";; +# end-sanitize-tx49 +# start-sanitize-r5900 + mips64r59*-*-*) SIMCONF="-mips3 --warnings -mcpu=r5900";; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) SIMCONF="-mips3 --warnings -mcpu=r5900";; +# end-sanitize-sky + mips64*-*-*) SIMCONF="-mips0 --warnings";; + mips16*-*-*) SIMCONF="-mips0 --warnings";; + mips*-*-*) SIMCONF="-mips2 --warnings";; + *) SIMCONF="-mips0 --warnings";; +esac +AC_SUBST(SIMCONF) + +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) SIM_SUBTARGET="-DSUBTARGET_R3900=1";; +# end-sanitize-tx19 + *) SIM_SUBTARGET="";; +esac +AC_SUBST(SIM_SUBTARGET) + + +# +# Select the byte order of the target +# +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) mips_endian=0 ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) mips_endian=LITTLE_ENDIAN ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) mips_endian=LITTLE_ENDIAN ;; +# end-sanitize-sky + mips64*-*-*) mips_endian=0 ;; + mips16*-*-*) mips_endian=0 ;; + mips*-*-*) mips_endian=0 ;; + *) mips_endian=0 ;; +esac +SIM_AC_OPTION_ENDIAN($mips_endian) + + +# +# Select the bitsize of the target +# +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) mips_bitsize=32 ; mips_msb=31 ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) mips_bitsize=64 ; mips_msb=63 ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) mips_bitsize=64 ; mips_msb=63 ;; +# end-sanitize-sky + mips64*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips16*-*-*) mips_bitsize=64 ; mips_msb=63 ;; + mips*-*-*) mips_bitsize=32 ; mips_msb=31 ;; + *) mips_bitsize=64 ; mips_msb=63 ;; +esac +SIM_AC_OPTION_BITSIZE($mips_bitsize,$mips_msb) + + +# +# Select the floating hardware support of the target +# +mips_fpu=HARDWARE_FLOATING_POINT +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) mips_fpu=SOFT_FLOATING_POINT ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) mips_fpu=HARD_FLOATING_POINT ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) mips_fpu=HARD_FLOATING_POINT ;; +# end-sanitize-sky + mips64*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips16*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + mips*-*-*) mips_fpu=HARD_FLOATING_POINT ;; + *) mips_fpu=HARD_FLOATING_POINT ;; +esac +SIM_AC_OPTION_FLOAT($mips_fpu) + + +# +# Select the IGEN architecture +# +sim_use_gen=NO +sim_igen_machine="-M mipsIV" +sim_m16_machine="-M mips16" +sim_igen_filter="32,64,f" +sim_m16_filter="16" + +case "${target}" in +# start-sanitize-tx19 + mipstx19*-*-*) sim_default_gen=M16 + sim_igen_machine="-M tx19" + sim_m16_machine="-M tx19" + sim_igen_filter="32" + sim_m16_filter="16" + ;; +# end-sanitize-tx19 +# start-sanitize-r5900 + mips64r59*-*-*) sim_default_gen=IGEN + sim_igen_machine="-M r5900" + ;; +# end-sanitize-r5900 +# start-sanitize-sky + txvu-*-*) sim_default_gen=IGEN + sim_igen_machine="-M r5900" + ;; +# end-sanitize-sky +# start-sanitize-vr5400 + mips64vr54*-*-*) sim_default_gen=IGEN + sim_use_gen=IGEN + sim_igen_machine="-M vr5000,vr5400 -G gen-multi-sim=vr5400" + ;; +# end-sanitize-vr5400 + mips64vr5*-*-*) sim_default_gen=IGEN + sim_use_gen=IGEN + sim_igen_machine="-M vr5000" +# start-sanitize-vr5400 + sim_igen_machine="-M vr5000,vr5400 -G gen-multi-sim=vr5000" +# end-sanitize-vr5400 + ;; + mips16*-*-*) sim_default_gen=M16 + ;; + mips32*-*-*) sim_default_gen=IGEN + sim_igen_filter="32,f" + ;; + *) sim_default_gen=IGEN + ;; +esac +sim_igen_flags="-F ${sim_igen_filter} ${sim_igen_machine}" +sim_m16_flags=" -F ${sim_m16_filter} ${sim_m16_machine}" +AC_SUBST(sim_igen_flags) +AC_SUBST(sim_m16_flags) + +# +# Enable igen +# +AC_ARG_ENABLE(sim-igen, +[ --enable-sim-igen=opts Enable IGEN simulator], +[case "${enableval}" in + yes) sim_gen="${sim_default_gen}";; + no) sim_gen=NO;; + 16) sim_gen=M16;; + *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-stdio"); sim_gen="";; +esac +if test x"$silent" != x"yes" && test x"$sim_gen" != x""; then + echo "Setting sim_igen = $sim_gen" 6>&1 +fi],[sim_gen="${sim_use_gen}"])dnl +AC_SUBST(sim_gen) + + + +AC_CHECK_HEADERS(string.h strings.h stdlib.h stdlib.h) +AC_CHECK_LIB(m, fabs) +AC_CHECK_FUNCS(aint anint sqrt) + +SIM_AC_OUTPUT diff --git a/sim/txvu/device.c b/sim/txvu/device.c new file mode 100644 index 00000000000..5dda36162a7 --- /dev/null +++ b/sim/txvu/device.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1998, Cygnus Solutions + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "sim-main.h" +#include "device.h" + +void +device_error (device *me, char* message) +{ + fprintf(stderr, "device_error: %s: %s", me->name, message); +} + +int +device_io_read_buffer(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + if (me->io_read_buffer_callback == NULL) + device_error(me, "no io_read_buffer_callback method"); + return me->io_read_buffer_callback(me, dest, space, + addr, nr_bytes, + processor, cia); +} + +int +device_io_write_buffer(device *me, + const void *source, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + if (me->io_write_buffer_callback == NULL) + device_error(me, "no io_write_buffer_callback method"); + return me->io_write_buffer_callback(me, source, space, + addr, nr_bytes, + processor, cia); +} diff --git a/sim/txvu/device.h b/sim/txvu/device.h new file mode 100644 index 00000000000..641cd293e98 --- /dev/null +++ b/sim/txvu/device.h @@ -0,0 +1,24 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef DEVICE_H_ +#define DEVICE_H_ + +#include "sim-main.h" + +typedef int io_read_buffer_callback_type (device *, void *, int, + address_word, unsigned , + sim_cpu *, sim_cia); + +typedef int io_write_buffer_callback_type (device *, const void *, int, + address_word, unsigned , + sim_cpu *, sim_cia); + +struct _device { + char *name; + io_read_buffer_callback_type *io_read_buffer_callback; + io_write_buffer_callback_type *io_write_buffer_callback; +}; + +#endif diff --git a/sim/txvu/dma.c b/sim/txvu/dma.c new file mode 100644 index 00000000000..7f178aaefe1 --- /dev/null +++ b/sim/txvu/dma.c @@ -0,0 +1,70 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#include "sim-main.h" + +#include "device.h" +#include "dma.h" + +int +dma_io_read_buffer(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Read!\n", me->name); + return nr_bytes; +} + +static sim_event_handler do_the_dma_thing_handler; + +int +dma_io_write_buffer(device *me, + const void *source, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Write!\n", me->name); + + /* Do an event before the next instruction! */ + sim_events_schedule (CPU_STATE(processor), + 0 /*time*/, + do_the_dma_thing_handler, + CPU_STATE(processor) /*data*/); + return nr_bytes; +} + +device dma_device = + { + "Dma Controller", + &dma_io_read_buffer, + &dma_io_write_buffer + }; + +void +dma_attach(SIM_DESC sd) +{ + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + DMA_REGISTER_WINDOW_START, + DMA_REGISTER_WINDOW_SIZE /*nr_bytes*/, + 0 /*modulo*/, + &dma_device, + NULL /*buffer*/); +} + +static void +do_the_dma_thing_handler(SIM_DESC sd, void *data) +{ + printf("Dma Event!!!\n"); +} diff --git a/sim/txvu/dma.h b/sim/txvu/dma.h new file mode 100644 index 00000000000..dc2fcb7be4d --- /dev/null +++ b/sim/txvu/dma.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef DMA_H_ +#define DMA_H_ + +#include "sim-main.h" + +void dma_attach(SIM_DESC sd); + +#define DMA_REGISTER_WINDOW_START 0x10001000 + +#define DMA_D0_CHCR_ADDR 0x10001000 +#define DMA_D0_MADR_ADDR 0x10001010 +#define DMA_D0_QWC_ADDR 0x10001020 +#define DMA_D0_TADR_ADDR 0x10001030 +#define DMA_D0_ASR0_ADDR 0x10001040 +#define DMA_D0_ASR1_ADDR 0x10001050 + +#define DMA_D1_CHCR_ADDR 0x10001100 +#define DMA_D1_MADR_ADDR 0x10001110 +#define DMA_D1_QWC_ADDR 0x10001120 +#define DMA_D1_TADR_ADDR 0x10001130 +#define DMA_D1_ASR0_ADDR 0x10001140 +#define DMA_D1_ASR1_ADDR 0x10001150 + +#define DMA_D2_CHCR_ADDR 0x10001200 +#define DMA_D2_MADR_ADDR 0x10001210 +#define DMA_D2_QWC_ADDR 0x10001220 +#define DMA_D2_TADR_ADDR 0x10001230 +#define DMA_D2_ASR0_ADDR 0x10001240 +#define DMA_D2_ASR1_ADDR 0x10001250 + +#define DMA_D_CTRL 0x10001c00 +#define DMA_D_STAT 0x10001c10 +#define DMA_D_PCR 0x10001c20 +#define DMA_D_SQWC 0x10001c30 +#define DMA_D_RBSR 0x10001c40 +#define DMA_D_RBOR 0x10001c50 +#define DMA_D_STADR 0x10001c60 + +#define DMA_REGISTER_WINDOW_END 0x10001c70 +#define DMA_REGISTER_WINDOW_SIZE (DMA_REGISTER_WINDOW_END - DMA_REGISTER_WINDOW_START) + +#endif diff --git a/sim/txvu/engine-sky.c b/sim/txvu/engine-sky.c new file mode 100644 index 00000000000..78143b29cc7 --- /dev/null +++ b/sim/txvu/engine-sky.c @@ -0,0 +1,94 @@ +/* Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1998, Cygnus Solutions + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#ifndef _ENGINE_C_ +#define _ENGINE_C_ + +#include "sim-inline.c" + +#include "sim-main.h" +#include "itable.h" +#include "idecode.h" +#include "semantics.h" +#include "icache.h" +#include "engine.h" +#include "support.h" + +#include "sim-assert.h" + +enum { + /* greater or equal to zero => table */ + function_entry = -1, + boolean_entry = -2, +}; + +typedef struct _idecode_table_entry { + int shift; + unsigned32 mask; + unsigned32 value; + void *function_or_table; +} idecode_table_entry; + + +INLINE_ENGINE\ +(void) engine_run +(SIM_DESC sd, + int next_cpu_nr, + int siggnal) +{ + sim_cpu *processor = NULL; + instruction_address cia; + int current_cpu = next_cpu_nr; + + /* Hard coded main loop. Not pretty, but should work. */ + + SIM_ASSERT (current_cpu == 0); + processor = STATE_CPU (sd, current_cpu); + cia = CPU_CIA (processor); + + while (1) + { + instruction_address nia; + + instruction_word instruction_0 = IMEM (cia); + +#if defined (ENGINE_ISSUE_PREFIX_HOOK) + ENGINE_ISSUE_PREFIX_HOOK(); +#endif + + nia = idecode_issue(sd, instruction_0, cia); + +#if defined (ENGINE_ISSUE_POSTFIX_HOOK) + ENGINE_ISSUE_POSTFIX_HOOK(); +#endif + + + /* Update the instruction address */ + cia = nia; + + /* process any events */ + if (sim_events_tick (sd)) + { + CPU_CIA (processor) = cia; + sim_events_process (sd); + } + } +} + +#endif /* _ENGINE_C_*/ diff --git a/sim/txvu/gencode.c b/sim/txvu/gencode.c new file mode 100644 index 00000000000..44fac708461 --- /dev/null +++ b/sim/txvu/gencode.c @@ -0,0 +1,4846 @@ +/*> gencode.c <*/ +/* Instruction handling support for the MIPS architecture simulator. + + This file is part of the MIPS 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. + + $Revision$ + $Author$ + $Date$ +*/ + +#if 0 +#define DEBUG (1) /* Just for testing */ +#endif + +/* All output sent to stdout is for the simulator engine. All program + related warnings and errors should be sent to stderr. */ + +/* The simulator decode table is constructed this way to allow the + minimal code required for a particular instruction type to be + coded. This avoids a large simulator source file, with lots of + build-time conditionals controlling what code is included. However + this two-stage process does mean that care must be taken to ensure + that the correct decoding source is generated for a particular MIPS + simulator. */ + +/* Notes: + + We could provide pipeline modelling by splitting the simulation of + instructions into seperate bytecodes for each pipeline + stage. e.g. for the VR4300 each instruction would generate 5 + bytecodes, one for each pipeline stage. The simulator control would + then insert these into the relevant pipeline slots, and execute a + complete slots worth of bytecodes. However, the shape of the + pipeline, and what parts of each instruction are executed in each + pipeline stage, are different between MIPS implementations. If we + were to construct a simulator for a particular MIPS architecture + this would be a good solution. + + To avoid having to provide multiple different pipeline models, a + simple approach for dealing with the delay slots, and register + dependencies has been used. The "MIPS IV Instruction Set" document + (Revision 3.1 - January 1995) details the standard MIPS instruction + set, and it defines operations in instruction (not pipe-line) + cycles. This means we only need to worry about a few cases where + the result is not available until after the next instruction, or + where registers in the previous two instruction cycles may be + corrupted. The case for corruption only occurs with HI or LO + register access, so we can just keep a count within the engine for + upto two cycles before marking the register as safe. We then only + need to check the safety flag when performing an update that + involves the HI or LO register. The only other case is the + BC1F/BC1T instructions in the FP unit. For ISAs I, II and III there + must be an instruction between the FP CMP and the BC1[FT]. We can + perform the same instruction cycle count scheme, so we can raise a + warning if an attempt is made to access the condition code early + (NOTE: The hardware does not interlock on this operation, so the + simulator should just raise a warning). + + For the situations where a result is not available until later, we + implent a slot to hold pending values. After the PC is incremented, + and before the instruction is decoded we can execute the required + register update (or remainder of instruction processing). */ + +/* The FP instruction decoding is also provided by this code. The + instructions are marked as "FP" ones so that we can construct a + simulator without an FPU if required. Similarly we mark + instructions as Single or Double precision, since some MIPS + processors only have single precision FP hardware. */ + +/* NOTE: Ideally all state should be passed as parameters. This allows + a single simulator engine to be used for multiple concurrent + simulations. More importantly, if a suitably powerful control is in + place it will allow speculative simulation, since the context can + be saved easily, and then restored after performing some + simulation. The down-side is that for certain host architectures it + can slow the simulator down (e.g. if globals can be accessed faster + than local structures). However, this is not actually the case at + the moment. The constructed engine uses direct names (that can be + macro definitions). This keeps the engine source smalled (using + short-hands), and it also allows the user to control whether they + want to use global, or indirected memory locations. i.e. whether + they want a single- or multi-threaded simulator engine. */ + +/* The constructed simulator engine contains manifests for each of the + features supported. The code that includes the engine can then + discover the available features during its build. This information + can be used to control run-time features provided by the final + simulator. */ + +/*---------------------------------------------------------------------------*/ + +/* Program defaults */ +#define DEF_ISA (3) +#define DEF_PROC64 (1 == 1) +#define DEF_FP (1 == 1) +#define DEF_FPSINGLE (1 == 0) + +#define FEATURE_PROC32 (1 << 0) /* 0 = 64bit; 1 = 32bit */ +#define FEATURE_HASFPU (1 << 1) /* 0 = no FPU; 1 = include FPU */ +#define FEATURE_FPSINGLE (1 << 1) /* 0 = double; 1 = single (only used if FEATURE_HASFPU defined) */ +#define FEATURE_GP64 (1 << 2) /* 0 = GPRLEN 32; 1 = GPRLEN 64 */ +#define FEATURE_FAST (1 << 17) /* 0 = normal; 1 = disable features that slow performance */ +#define FEATURE_WARN_STALL (1 << 24) /* 0 = nothing; 1 = generate warnings when pipeline would stall */ +#define FEATURE_WARN_LOHI (1 << 25) /* 0 = nothing; 1 = generate warnings when LO/HI corrupted */ +#define FEATURE_WARN_ZERO (1 << 26) /* 0 = nothing; 1 = generate warnings if attempt to write register zero */ +#define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */ +#define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */ +#define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */ +#define FEATURE_IGEN (1 << 20) /* 0 = nothing; 1 = generate igen formatted output file */ + +/* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to + have the zero register as a destination -- the zero register just doesn't + actually change. */ +/* start-sanitize-r5900 */ +/* The 5900 madd instructions for example use this feature. */ +/* end-sanitize-r5900 */ +#if 1 +#define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31) +#else +#define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31 | FEATURE_WARN_RESULT) +#endif + +/* FEATURE_WARN_STALL */ +/* If MIPS I we want to raise a warning if an attempt is made to + access Rn in an instruction immediately following an Rn update + "WARNING : Invalid value read". The simulator engine is designed + that the previous value is read in such cases, to allow programs + that make use of this feature to execute. */ +/* If MIPS II or later, attempting to read a register before the + update has completed will generate a "WARNING : Processor stall" + message (since the processor will lock the pipeline until the value + becomes available). */ + +/* FEATURE_WARN_LOHI */ +/* Warn if an attempt is made to read the HI/LO registers before the + update has completed, or if an attempt is made to update the + registers whilst an update is occurring. */ + +/* FEATURE_WARN_ZERO */ +/* Notify the user if an attempt is made to use GPR 0 as a destination. */ + +/* FEATURE_WARN_R31 */ +/* Notify the user if register r31 (the default procedure call return + address) is used unwisely. e.g. If r31 is used as the source in a + branch-and-link instruction, it would mean that an exception in the + delay slot instruction would not allow the branch to be re-started + (since r31 will have been overwritten by the link operation during + the first execution of the branch). */ + +/* FEATURE_WARN_RESULT */ +/* Certain instructions do not raise exceptions when invalid operands + are given, they will just result in undefined values being + generated. This option controls whether the simulator flags such + events. */ + +/*---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include "ansidecl.h" +#include "opcode/mips.h" + +/* FIXME: ansidecl.h defines AND. */ +#undef AND + +#ifndef ULONG_MAX +#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ +#endif + +static unsigned long my_strtoul (); + +#if 0 +#ifndef TRUE +#define TRUE (1 == 1) +#define FALSE (1 == 0) +#endif +#endif + +/*---------------------------------------------------------------------------*/ + +/* Holding the instruction table this way makes it easier to check the + instruction values defined, and to add instructions to the + system. However, it makes the process of constructing the simulator + a bit more complicated: */ + +/* The "bitmap" is encoded as follows (NOTE: Only lower-case + alphabetic characters should be used, since the letter ordinal is + used as a bit position): */ + +typedef struct operand_encoding { + char id; /* character identifier */ + int fpos; /* first bit position */ + int flen; /* field length in bits */ + char * const type; + char * const name; + unsigned int flags; +} operand_encoding; + +/* Values for the "flags" field: */ +#define OP_NONE (0 << 0) /* To keep the source tidy */ +#define OP_GPR (1 << 0) /* Get operand from integer register bank */ +#define OP_SIGNX (1 << 1) /* Sign-extend the operand */ +#define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */ +#define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */ +#define OP_GPR1 (1 << 4) /* fetch from the GPR1 registers */ + +struct operand_encoding opfields[] = { + {'0',-1,-1,"", "", (OP_NONE)}, /* special case for explicit zero */ + {'1',-1,-1,"", "", (OP_NONE)}, /* special case for explicit one */ + {'?',-1,-1,"", "", (OP_NONE)}, /* undefined (do not care at this level) */ + /* The rest are the explicit operand fields: */ + {'a', 6, 5,"int", "op1", (OP_NONE)}, /* shift amount (or hint) */ + {'b',21, 5,"int", "fr", (OP_NONE)}, /* fr register */ + {'c',16, 1,"int", "boolean", (OP_NONE)}, /* TRUE or FALSE boolean */ + {'d',11, 5,"int", "destreg", (OP_NONE)}, /* integer destination/rd register */ + {'e', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-3bits must be zero) */ + {'f',17, 1,"int", "likely", (OP_NONE)}, /* set if branch LIKELY */ + {'g',16, 5,"t_reg", "op2", (OP_GPR)}, /* integer source rt register */ + {'h', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-1bit must be zero) */ + {'i', 0,16,"t_reg", "op2", (OP_SIGNX)}, /* signed immediate (op2) */ + {'j', 0,26,"ut_reg","op1", (OP_SHIFT2)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */ + {'k',16, 5,"int", "ft", (OP_NONE)}, + {'l', 0,16,"t_reg", "offset", (OP_SIGNX | OP_SHIFT2)}, /* signed offset shifted left 2 to make 18bit signed offset */ + {'m',21, 3,"int", "format", (OP_NONE)}, /* FP format field */ + {'n',16, 5,"int", "hint", (OP_NONE)}, /* hint */ + {'o',21, 5,"t_reg", "op1", (OP_GPR | OP_BITS5)}, /* integer source/rs register (but never treated as 32bit word) */ + {'p', 8, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */ + {'q',18, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */ + {'r', 6, 5,"int", "destreg", (OP_NONE)}, /* FP fd register */ + {'s',21, 5,"t_reg", "op1", (OP_GPR)}, /* integer source/rs register */ + {'t',16, 5,"int", "destreg", (OP_NONE)}, /* integer target rt (destination) register */ + {'u', 0, 4,"int", "cmpflags", (OP_NONE)}, /* FP comparison control flags */ + {'v',11, 5,"int", "fs", (OP_NONE)}, /* FP fs register (or PREFX hint) */ + {'w', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-2bits must be zero) */ + {'x',23, 1,"int", "to", (OP_NONE)}, /* TRUE if move To; FALSE if move From */ + {'y', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset */ + {'z', 0,16,"ut_reg","op2", (OP_NONE)}, /* unsigned immediate (zero extended) */ + {'S',21, 5,"t_reg", "rs_reg", (OP_GPR|OP_GPR1)}, /* rs field, GPR[rs] and GPR1[rs] as source */ + {'T',16, 5,"t_reg", "rt_reg", (OP_GPR|OP_GPR1)}, /* rt field, GPR[rt] and GPR1[rt] as source */ +}; + + +/* Main instruction encoding types: */ +typedef enum { + NORMAL, + SPECIAL, + REGIMM, + COP1, + COP1X, + COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */ + + MMINORM, + MMI0, + MMI1, + MMI2, + MMI3, + + /* mips16 encoding types. */ + I, RI, RR, RRI, RRR, RRI_A, ISHIFT, I8, I8_MOVR32, I8_MOV32R, I64, RI64 +} inst_type; + +/* Main instruction families: */ +typedef enum { + ADD, /* res = operand1 + operand2 */ + SUB, /* res = operand1 - operand2 */ + MUL, /* res = operand1 * operand2 */ + DIV, /* res = operand1 / operand2 */ + AND, /* res = operand1 & operand2 */ + OR, /* res = operand1 | operand2 */ + XOR, /* res = operand1 ^ operand2 */ + MOVE, /* res = operand1 */ + BRANCH, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */ + JUMP, /* execute delay slot instruction before jump */ + LOAD, /* load from memory */ + STORE, /* store to memory */ + PREFETCH, /* prefetch data into cache */ + SET, /* set register on result of condition code */ + SHIFT, /* perform a logical or arithmetic shift */ + TRAP, /* system exception generation */ + BREAK, /* system breakpoint exception generation */ + SDBBP, /* software debug breakpoint exception generation */ + SYSCALL, /* system exception generation */ + SYNC, /* system cache control */ + DECODE, /* co-processor instruction */ + CACHE, /* co-processor 0 CACHE instruction */ + MADD16, /* VR4100 specific multiply-add extensions */ + FPMOVE, + FPMOVEC, + FPFLOOR, + FPCEIL, + FPTRUNC, + FPROUND, + FPNEG, + FPABS, + FPDIV, + FPMUL, + FPSUB, + FPADD, + FPPREFX, + FPRECIP, + FPSQRT, + FPCONVERT, + FPCOMPARE, + MADD, + /* start-sanitize-r5900 */ + PABS, + PADD, + PADSBH, + POP, + PCMP, + PCPYH, + PCPYLD, + PCPYUD, + PEXCH, + PEXCW, + PEXOH, + PEXOW, + PEXTLB, + PEXTLH, + PEXTLW, + PEXTUB, + PEXTUH, + PEXTUW, + PPACB, + PPACH, + PPACW, + PREVH, + PROT3W, + PINTH, + PINTOH, + PMXX, + PMFHL, + PMTHL, + PMAXMIN, + QFSRV, + MxSA, + MTSAB, + MTSAH, + PSHIFT, + PSLLVW, + PSRLVW, + PSRAVW, + PLZCW, + PHMADDH, + PMULTH, + PMULTW, + PDIVBW, + PDIVW, + PEXT5, + PPAC5, + /* end-sanitize-r5900 */ + NYI, /* Not Yet Implemented, placeholder, errors if used */ + RSVD /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */ +} opcode_type; + +/* Flags field: */ +#define NONE (0 << 0) /* Zero value (used to keep source tidy) */ +#define SIM_SH_SIZE (0) +#define SIM_MASK_SIZE (0x7) +#define BYTE (0) /* 8bit */ +#define HALFWORD (1) /* 16bit */ +#define WORD (2) /* 32bit */ +#define DOUBLEWORD (3) /* 64bit */ +#define SINGLE (4) /* single precision FP */ +#define DOUBLE (5) /* double precision FP */ +/* start-sanitize-r5900 */ +#define QUADWORD (6) /* 128bit */ +/* end-sanitize-r5900 */ + +/* Shorthand to get the size field from the flags value: */ +#define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE) + +/* The rest are single bit flags: */ +#define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */ +#define EQ (1 << 4) +#define GT (1 << 5) +#define LT (1 << 6) +#define NOT (1 << 7) +#define LIKELY (1 << 8) +#define SIGNEXTEND (1 << 9) +#define OVERFLOW (1 << 10) +#define LINK (1 << 11) +#define ATOMIC (1 << 12) +#define SHIFT16 (1 << 13) +#define REG (1 << 14) +#define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */ +#define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */ +#define LOGICAL (1 << 17) +#define ARITHMETIC (1 << 18) +#define UNSIGNED (1 << 19) +#define HI32 (1 << 20) +#define HI (1 << 21) /* accesses or updates the HI register */ +#define LO (1 << 22) /* accesses or updates the LO register */ +#define WORD32 (1 << 23) +#define FP (1 << 24) /* Floating Point operation */ +#define FIXED (1 << 25) /* fixed point arithmetic */ +#define COPROC (1 << 26) +#define INTEGER (1 << 27) +#define CONDITIONAL (1 << 28) +#define RECIP (1 << 29) +#define CONTROL (1 << 30) +#define NOARG (1 << 31) /* Instruction has no (defined) operands */ +/* NOTE: We can overload the use of certain of these flags, since not + all options are applicable to all instruction types. This will free + up more space for new flags. */ + +/* Overloadings of above bits */ +#define PIPE1 LIKELY /* Using pipeline 1 (DIV,MUL) */ +#define OP3 EQ /* 3 operand version of operation (MUL) */ + +#define SATURATE OVERFLOW /* for PADD, saturate for overflow */ + +#define SUBTRACT LEFT /* for PMULT, PMULT becomes PMSUB */ +#define ADDITION RIGHT /* for PMULT, PMULT becomes PMADD */ + +#define FROM LEFT /* move from special register */ +#define TO RIGHT /* move to special register */ + +/* For bitwise parallel operations */ +#define POP_AND 0 /* for POP, op = & */ +#define POP_OR LEFT /* for POP, op = | */ +#define POP_NOR LIKELY /* for POP, op = ~(x | y) */ +#define POP_XOR LEFT|LIKELY /* for POP, op = ^ */ + +#define GET_OP_FROM_INSN(insn) (((insn)->flags)&(LEFT|LIKELY)) + + + +typedef struct instruction { + char *name; /* ASCII mnemonic name */ + unsigned int isa; /* MIPS ISA number where instruction introduced */ + char *bitmap; /* 32character string describing instruction operands */ + inst_type mark; /* type of MIPS instruction encoding */ + opcode_type type; /* main instruction family */ + unsigned int flags; /* flags describing instruction features */ +} instruction; +/* The number of pipeline cycles taken by an instruction varies + between MIPS processors. This means that the information must be + encoded elsewhere, in a CPU specific structure. */ + +/* NOTE: Undefined instructions cause "Reserved Instruction" + exceptions. i.e. if there is no bit-mapping defined then the + instruction is deemed to be undefined. */ + +/* NOTE: The "isa" field is also used to encode flags for particular + chip architecture extensions. e.g. the NEC VR4100 specific + instructions. Normally chip extensions are added via the COP0 + space. However, the VR4100 (and possibly other devices) also use + the normal instruction space. */ +#define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */ +/* The other bits are allocated downwards, to avoid renumbering if we + have to extend the bits allocated to the pure ISA number. + + These architecture bits come in two flavors: + ISA dependent - marking insns that should be included in the opcode + set if that architecture is requested on the gencode command line + AND the ISA of the insn is <= requested ISA; + + ISA independent - marking insn that should be included in the opcode + set if that architecture is requested + OR the ISA of the insn is <= requested ISA. + + Independent bits are listed in MASK_ISA_INDEP, the rest are dependent. + */ +#define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */ +/* start-sanitize-r5900 */ +#define ARCH_R5900 ((unsigned)1 << 30) /* Toshiba r5900 extension instructions */ +/* end-sanitize-r5900 */ +#define ARCH_R3900 ((unsigned)1 << 29) /* Toshiba r3900 (tx39) */ +/* start-sanitize-tx49 */ +#define ARCH_R4900 ((unsigned)1 << 28) /* Toshiba r4900 (tx49) */ +/* end-sanitize-tx49 */ + +/* start-sanitize-tx19 */ +/* The r1900 (tx19) is a tx39 with a mips16 decoder. For the purposes + of implementing the simulator we treat them as the same. */ +/* end-sanitize-tx19 */ + +/* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */ +#define MASK_ISA_INDEP (0 \ + | ARCH_R3900 \ + /* start-sanitize-tx49 */ \ + | ARCH_R4900 \ + /* end-sanitize-tx49 */ \ + /* start-sanitize-r5900 */ \ + | ARCH_R5900 \ + /* end-sanitize-r5900 */ \ + | 0) + +#define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA) + +/* Very short names for use in the table below to keep it neet. */ +#define G1 (3 | ARCH_VR4100) + +#define G2 (4 \ + /* start-sanitize-r5900 */ \ + | ARCH_R5900 \ + /* end-sanitize-r5900 */ \ + | 0) + +#define G3 (4 \ + /* start-sanitize-r5900 */ \ + /* insn that are not really 5900 insn but were left in */ \ + /* until we can rewrite the code-gen and libs */ \ + | ARCH_R5900 \ + /* end-sanitize-r5900 */ \ + | 0) + +#define G4 (2 | ARCH_R3900) + +#define G5 (0 \ + | ARCH_R3900 \ + /* start-sanitize-tx49 */ \ + | ARCH_R4900 \ + /* end-sanitize-tx49 */ \ + /* start-sanitize-r5900 */ \ + | ARCH_R5900 \ + /* end-sanitize-r5900 */ \ + ) + +#define G6 (3 | ARCH_R3900) + +#define G7 (ARCH_R3900 \ + /* start-sanitize-tx49 */ \ + | ARCH_R4900 \ + /* end-sanitize-tx49 */ \ + ) + +#define G8 (4 \ + /* start-sanitize-tx49 */ \ + | ARCH_R4900 \ + /* end-sanitize-tx49 */ \ + /* start-sanitize-r5900 */ \ + | ARCH_R5900 \ + /* end-sanitize-r5900 */ \ + ) + +#define G9 (3 \ + /* start-sanitize-tx49 */ \ + | ARCH_R4900 \ + /* end-sanitize-tx49 */ \ + ) + +/* start-sanitize-r5900 */ +#define T5 ARCH_R5900 +/* end-sanitize-r5900 */ + + +/* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the + COP0 space. This means that an external decoder should be added + when constructing a full VR4100 simulator. However some arithmetic + instructions are encoded in the normal instruction space. */ + +struct instruction MIPS_DECODE[] = { + /* The instructions are alphabetical, and not in instruction bit-order: */ + {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1, FPABS, (FP)}, + {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL,ADD, (WORD | WORD32 | OVERFLOW)}, /* rd = rs + rt */ + {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1, FPADD, (FP)}, + {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32 | OVERFLOW)}, + {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL,ADD, (WORD | WORD32)}, /* rd = rs + rt */ + {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32)}, + {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL,AND, (NONE)}, /* rd = rs AND rt */ + {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL, AND, (NONE)}, + {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S, BRANCH, (FP)}, + {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ)}, + {"BEQL", G4,"010100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ | LIKELY)}, + {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM, BRANCH, (GT | EQ)}, + {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)}, + {"BGEZALL",G4,"000001sssss10011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)}, + {"BGEZL", G4,"000001sssss00011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LIKELY)}, + {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT)}, + {"BGTZL", G4,"010111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT | LIKELY)}, + {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ)}, + {"BLEZL", G4,"010110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ | LIKELY)}, + {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM, BRANCH, (LT)}, + {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM, BRANCH, (LT | LINK)}, + {"BLTZALL",G4,"000001sssss10010llllllllllllllll",REGIMM, BRANCH, (LT | LINK | LIKELY)}, + {"BLTZL", G4,"000001sssss00010llllllllllllllll",REGIMM, BRANCH, (LT | LIKELY)}, + {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ)}, + {"BNEL", G4,"010101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ | LIKELY)}, + {"BREAK", 1,"000000????????????????????001101",SPECIAL,BREAK, (NOARG)}, + {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1, FPCEIL, (FP | FIXED | DOUBLEWORD)}, + {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1, FPCEIL, (FP | FIXED | WORD)}, + {"COP0", 1,"010000??????????????????????????",NORMAL, DECODE, (NOARG)}, + {"COP2", 1,"010010??????????????????????????",NORMAL, DECODE, (NOARG)}, + {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1, FPCONVERT,(FP | DOUBLE)}, + {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1, FPCONVERT,(FP | FIXED | DOUBLEWORD)}, + {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1, FPCONVERT,(FP | SINGLE)}, + {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1, FPCONVERT,(FP | FIXED | WORD)}, + {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1, FPCOMPARE,(FP)}, + {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD | CONTROL)}, + {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL,ADD, (DOUBLEWORD | OVERFLOW)}, + {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | OVERFLOW)}, + {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL,ADD, (DOUBLEWORD | UNSIGNED)}, + {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | UNSIGNED)}, + {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL,DIV, (DOUBLEWORD | HI | LO)}, + {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL,DIV, (DOUBLEWORD | UNSIGNED | HI | LO)}, + {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO)}, + {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1, FPDIV, (FP | WORD | HI | LO)}, + /* start-sanitize-r5900 */ + {"DIV1", T5,"011100sssssggggg0000000000011010",MMINORM,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO | PIPE1)}, + /* end-sanitize-r5900 */ + {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO)}, + /* start-sanitize-r5900 */ + {"DIVU1", T5,"011100sssssggggg0000000000011011",MMINORM,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO | PIPE1)}, + /* end-sanitize-r5900 */ + {"DMADD16",G1,"000000sssssggggg0000000000101001",SPECIAL,MADD16, (DOUBLEWORD | HI | LO)}, + /* See note near MULT for explanation of 3op-ness. */ + {"DMULT", G9,"000000sssssgggggddddd00000011100",SPECIAL,MUL, (OP3 | DOUBLEWORD | HI | LO)}, + {"DMULTU", G9,"000000sssssgggggddddd00000011101",SPECIAL,MUL, (OP3 | DOUBLEWORD | UNSIGNED | HI | LO)}, + {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | DOUBLEWORD)}, + {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL)}, + {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | REG)}, + {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | HI32)}, /* rd = rt << (sa + 32) */ + {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)}, + {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | REG)}, + {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | HI32)}, /* rd = rt >> (sa + 32) */ + {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)}, + {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | REG)}, + {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | HI32)}, + {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL,SUB, (DOUBLEWORD)}, + {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL,SUB, (DOUBLEWORD | UNSIGNED)}, + {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1, FPFLOOR, (FP | FIXED | DOUBLEWORD)}, + {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1, FPFLOOR, (FP | FIXED | WORD)}, + {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (NONE)}, /* NOTE: boundary case due to delay slot address being used */ + {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK)}, /* NOTE: boundary case due to delay slot address being used */ + {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL,JUMP, (LINK | REG)}, + {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK | NOT)}, + {"JR", 1,"000000sssss000000000000000001000",SPECIAL,JUMP, (NONE)}, /* need to check PC as part of instruction fetch */ + {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE | SIGNEXTEND)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */ + {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE)}, /* NOTE: See "LB" comment */ + {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD)}, + {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)}, + {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)}, + {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | LEFT)}, /* NOTE: See "LB" comment */ + {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | RIGHT)}, /* NOTE: See "LB" comment */ + {"LDXC1", G3,"010011sssssggggg00000rrrrr000001",COP1X, LOAD, (FP | DOUBLEWORD | COPROC | REG)}, + {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD | SIGNEXTEND)}, + {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD)}, + {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | ATOMIC | SIGNEXTEND)}, + {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | ATOMIC)}, + {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL, MOVE, (SHIFT16)}, /* Cheat and specify sign-extension of immediate field */ + /* start-sanitize-r5900 */ + {"LQ", T5,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (QUADWORD)}, + /* end-sanitize-r5900 */ + {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | SIGNEXTEND)}, + {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)}, + {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)}, + {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | LEFT)}, + {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | RIGHT)}, + {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD)}, + {"LWXC1", G3,"010011sssssggggg00000rrrrr000000",COP1X, LOAD, (FP | WORD | COPROC | REG)}, + {"MADD", G5,"011100sssssgggggddddd00000000000",MMINORM,MADD, (NONE)}, + {"MADDU", G5,"011100sssssgggggddddd00000000001",MMINORM,MADD, (UNSIGNED)}, + /* start-sanitize-r5900 */ + {"MADD1", T5,"011100sssssgggggddddd00000100000",MMINORM,MADD, (PIPE1)}, + {"MADDU1", T5,"011100sssssgggggddddd00000100001",MMINORM,MADD, (UNSIGNED | PIPE1)}, + /* end-sanitize-r5900 */ + {"MADD16", G1,"000000sssssggggg0000000000101000",SPECIAL,MADD16, (WORD | HI | LO)}, + {"MADD.D", G3,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X, FPADD, (FP | MULTIPLY | DOUBLE)}, + {"MADD.S", G3,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X, FPADD, (FP | MULTIPLY | SINGLE)}, + {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL,MOVE, (HI | LEFT)}, /* with following, from and to denoted by usage of LEFT or RIGHT */ + /* start-sanitize-r5900 */ + {"MFHI1", T5,"0111000000000000ddddd00000010000",MMINORM,MOVE, (HI | LEFT | PIPE1)}, + /* end-sanitize-r5900 */ + {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL,MOVE, (LO | LEFT)}, + /* start-sanitize-r5900 */ + {"MFLO1", T5,"0111000000000000ddddd00000010010",MMINORM,MOVE, (LO | LEFT | PIPE1)}, + {"MFSA", T5,"0000000000000000ddddd00000101000",SPECIAL,MxSA, (FROM)}, + /* end-sanitize-r5900 */ + {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL,MOVE, (HI | RIGHT)}, + /* start-sanitize-r5900 */ + {"MTHI1", T5,"011100sssss000000000000000010001",MMINORM,MOVE, (HI | RIGHT | PIPE1)}, + /* end-sanitize-r5900 */ + {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL,MOVE, (LO | RIGHT)}, + /* start-sanitize-r5900 */ + {"MTLO1", T5,"011100sssss000000000000000010011",MMINORM,MOVE, (LO | RIGHT | PIPE1)}, + {"MTSA", T5,"000000sssss000000000000000101001",SPECIAL,MxSA, (TO)}, + {"MTSAB", T5,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM, MTSAB, (NONE)}, + {"MTSAH", T5,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM, MTSAH, (NONE)}, + /* end-sanitize-r5900 */ + {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1, FPMOVE, (FP)}, + {"MOVN", G2,"000000sssssgggggddddd00000001011",SPECIAL,MOVE, (NOT | EQ)}, + {"MOVN", G2,"01000110mmmgggggvvvvvrrrrr010011",COP1, FPMOVE, (FP | NOT | EQ)}, + {"MOV%c", G3,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE, (FP | CONDITIONAL | INTEGER)}, + {"MOV%c", G3,"01000110mmmqqq0cvvvvvrrrrr010001",COP1, FPMOVE, (FP | CONDITIONAL)}, + {"MOVZ", G2,"000000sssssgggggddddd00000001010",SPECIAL,MOVE, (EQ)}, + {"MOVZ", G2,"01000110mmmgggggvvvvvrrrrr010010",COP1, FPMOVE, (FP | EQ)}, + {"MSUB.D", G3,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X, FPSUB, (FP | MULTIPLY | DOUBLE)}, + {"MSUB.S", G3,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)}, + {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)}, + /* The 3op version of MULT and MULTU are TX39 (and related chips) specific. + They should be removed from other chips sets, so that using the 3op opcode + causes a reserved instruction exception, but gencode can't deal with + that currently. */ + {"MULT", 1,"000000sssssgggggddddd00000011000",SPECIAL,MUL, (OP3 | WORD | WORD32 | HI | LO)}, + /* start-sanitize-r5900 */ + {"MULT1", T5,"011100sssssgggggddddd00000011000",MMINORM,MUL, (OP3 | WORD | WORD32 | HI | LO | PIPE1)}, + /* end-sanitize-r5900 */ + {"MULTU", 1,"000000sssssgggggddddd00000011001",SPECIAL,MUL, (OP3 | WORD | WORD32 | UNSIGNED | HI | LO)}, + /* start-sanitize-r5900 */ + {"MULTU1", T5,"011100sssssgggggddddd00000011001",MMINORM,MUL, (OP3 | WORD | WORD32 | UNSIGNED | HI | LO | PIPE1)}, + /* end-sanitize-r5900 */ + {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD)}, + {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)}, + {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)}, + {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X, FPADD, (FP | NOT | MULTIPLY | SINGLE)}, + {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X, FPSUB, (FP | NOT | MULTIPLY | DOUBLE)}, + {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X, FPSUB, (FP | NOT | MULTIPLY | SINGLE)}, + {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL,OR, (NOT)}, + {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL,OR, (NONE)}, + {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL, OR, (NONE)}, + + /* start-sanitize-r5900 */ + {"PABSH", T5,"01110000000TTTTTddddd00101101000",MMI1, PABS, (HALFWORD)}, + {"PABSW", T5,"01110000000TTTTTddddd00001101000",MMI1, PABS, (WORD)}, + + {"PADDB", T5,"011100SSSSSTTTTTddddd01000001000",MMI0, PADD, (BYTE)}, + {"PADDH", T5,"011100SSSSSTTTTTddddd00100001000",MMI0, PADD, (HALFWORD)}, + {"PADDW", T5,"011100SSSSSTTTTTddddd00000001000",MMI0, PADD, (WORD)}, + + {"PADDSB", T5,"011100SSSSSTTTTTddddd11000001000",MMI0, PADD, (BYTE | SATURATE)}, + {"PADDSH", T5,"011100SSSSSTTTTTddddd10100001000",MMI0, PADD, (HALFWORD | SATURATE)}, + {"PADDSW", T5,"011100SSSSSTTTTTddddd10000001000",MMI0, PADD, (WORD | SATURATE)}, + + {"PADDUB", T5,"011100SSSSSTTTTTddddd11000101000",MMI1, PADD, (BYTE | UNSIGNED)}, + {"PADDUH", T5,"011100SSSSSTTTTTddddd10100101000",MMI1, PADD, (HALFWORD | UNSIGNED)}, + {"PADDUW", T5,"011100SSSSSTTTTTddddd10000101000",MMI1, PADD, (WORD | UNSIGNED)}, + + {"PADSBH", T5,"011100SSSSSTTTTTddddd00100101000",MMI1, PADSBH, (NONE)}, + + {"PAND", T5,"011100SSSSSTTTTTddddd10010001001",MMI2, POP, (POP_AND)}, + + {"PCEQB", T5,"011100SSSSSTTTTTddddd01010101000",MMI1, PCMP, (EQ | BYTE)}, + {"PCEQH", T5,"011100SSSSSTTTTTddddd00110101000",MMI1, PCMP, (EQ | HALFWORD)}, + {"PCEQW", T5,"011100SSSSSTTTTTddddd00010101000",MMI1, PCMP, (EQ | WORD)}, + + {"PCGTB", T5,"011100SSSSSTTTTTddddd01010001000",MMI0, PCMP, (GT | BYTE)}, + {"PCGTH", T5,"011100SSSSSTTTTTddddd00110001000",MMI0, PCMP, (GT | HALFWORD)}, + {"PCGTW", T5,"011100SSSSSTTTTTddddd00010001000",MMI0, PCMP, (GT | WORD)}, + + {"PCPYH", T5,"01110000000TTTTTddddd11011101001",MMI3, PCPYH, (NONE)}, + {"PCPYLD", T5,"011100SSSSSTTTTTddddd01110001001",MMI2, PCPYLD, (NONE)}, + {"PCPYUD", T5,"011100SSSSSTTTTTddddd01110101001",MMI3, PCPYUD, (NONE)}, + + {"PDIVBW", T5,"011100SSSSSTTTTT0000011101001001",MMI2, PDIVBW, (NONE)}, + {"PDIVUW", T5,"011100SSSSSTTTTT0000001101101001",MMI3, PDIVW, (UNSIGNED)}, + {"PDIVW", T5,"011100SSSSSTTTTT0000001101001001",MMI2, PDIVW, (NONE)}, + + {"PEXCH", T5,"01110000000TTTTTddddd11010101001",MMI3, PEXCH, (NONE)}, + {"PEXCW", T5,"01110000000TTTTTddddd11110101001",MMI3, PEXCW, (NONE)}, + {"PEXOH", T5,"01110000000TTTTTddddd11010001001",MMI2, PEXOH, (NONE)}, + {"PEXOW", T5,"01110000000TTTTTddddd11110001001",MMI2, PEXOW, (NONE)}, + + {"PEXT5", T5,"01110000000TTTTTddddd11110001000",MMI0, PEXT5, (NONE)}, + + {"PEXTLB", T5,"011100SSSSSTTTTTddddd11010001000",MMI0, PEXTLB, (NONE)}, + {"PEXTLH", T5,"011100SSSSSTTTTTddddd10110001000",MMI0, PEXTLH, (NONE)}, + {"PEXTLW", T5,"011100SSSSSTTTTTddddd10010001000",MMI0, PEXTLW, (NONE)}, + {"PEXTUB", T5,"011100SSSSSTTTTTddddd11010101000",MMI1, PEXTUB, (NONE)}, + {"PEXTUH", T5,"011100SSSSSTTTTTddddd10110101000",MMI1, PEXTUH, (NONE)}, + {"PEXTUW", T5,"011100SSSSSTTTTTddddd10010101000",MMI1, PEXTUW, (NONE)}, + + {"PHMADDH",T5,"011100SSSSSTTTTTddddd10001001001",MMI2, PHMADDH, (NONE)}, + {"PHMSUBH",T5,"011100SSSSSTTTTTddddd10101001001",MMI2, PHMADDH, (SUBTRACT)}, + + {"PINTH", T5,"011100SSSSSTTTTTddddd01010001001",MMI2, PINTH, (NONE)}, + {"PINTOH", T5,"011100SSSSSTTTTTddddd01010101001",MMI3, PINTOH, (NONE)}, + + {"PLZCW", T5,"011100SSSSS00000ddddd00000000100",MMINORM,PLZCW, (NONE)}, + + {"PMADDH", T5,"011100SSSSSTTTTTddddd10000001001",MMI2, PMULTH, (ADDITION)}, + {"PMADDUW",T5,"011100SSSSSTTTTTddddd00000101001",MMI3, PMULTW, (ADDITION | UNSIGNED)}, + {"PMADDW", T5,"011100SSSSSTTTTTddddd00000001001",MMI2, PMULTW, (ADDITION)}, + + {"PMAXH", T5,"011100SSSSSTTTTTddddd00111001000",MMI0, PMAXMIN, (GT | HALFWORD)}, + {"PMAXW", T5,"011100SSSSSTTTTTddddd00011001000",MMI0, PMAXMIN, (GT | WORD)}, + + {"PMFHI", T5,"0111000000000000ddddd01000001001",MMI2, PMXX, (HI|FROM)}, + {"PMFLO", T5,"0111000000000000ddddd01001001001",MMI2, PMXX, (LO|FROM)}, + + {"PMFHL", T5,"0111000000000000dddddaaaaa110000",MMINORM,PMFHL, (NONE)}, + + {"PMINH", T5,"011100SSSSSTTTTTddddd00111101000",MMI1, PMAXMIN, (LT | HALFWORD)}, + {"PMINW", T5,"011100SSSSSTTTTTddddd00011101000",MMI1, PMAXMIN, (LT | WORD)}, + + {"PMSUBH", T5,"011100SSSSSTTTTTddddd10100001001",MMI2, PMULTH, (SUBTRACT)}, + {"PMSUBW", T5,"011100SSSSSTTTTTddddd00100001001",MMI2, PMULTW, (SUBTRACT)}, + + {"PMTHI", T5,"011100SSSSS000000000001000101001",MMI3, PMXX, (HI|TO)}, + {"PMTLO", T5,"011100SSSSS000000000001001101001",MMI3, PMXX, (LO|TO)}, + +{"PMTHL.LW",T5,"011100SSSSS000000000000000110001",MMINORM,PMTHL, (NONE)}, + + {"PMULTH", T5,"011100SSSSSTTTTTddddd11100001001",MMI2, PMULTH, (NONE)}, + {"PMULTUW",T5,"011100SSSSSTTTTTddddd01100101001",MMI3, PMULTW, (UNSIGNED)}, + {"PMULTW", T5,"011100SSSSSTTTTTddddd01100001001",MMI2, PMULTW, (NONE)}, + + {"PNOR", T5,"011100SSSSSTTTTTddddd10011101001",MMI3, POP, (POP_NOR)}, + {"POR", T5,"011100SSSSSTTTTTddddd10010101001",MMI3, POP, (POP_OR)}, + + {"PPAC5", T5,"01110000000TTTTTddddd11111001000",MMI0, PPAC5, (NONE)}, + + {"PPACB", T5,"011100SSSSSTTTTTddddd11011001000",MMI0, PPACB, (NONE)}, + {"PPACH", T5,"011100SSSSSTTTTTddddd10111001000",MMI0, PPACH, (NONE)}, + {"PPACW", T5,"011100SSSSSTTTTTddddd10011001000",MMI0, PPACW, (NONE)}, + + {"PREVH", T5,"01110000000TTTTTddddd11011001001",MMI2, PREVH, (NONE)}, + {"PROT3W", T5,"01110000000TTTTTddddd11111001001",MMI2, PROT3W, (NONE)}, + + {"PSLLH", T5,"01110000000TTTTTdddddaaaaa110100",MMINORM,PSHIFT, (LEFT | LOGICAL | HALFWORD)}, + {"PSLLVW", T5,"011100SSSSSTTTTTddddd00010001001",MMI2, PSLLVW, (NONE)}, + {"PSLLW", T5,"01110000000TTTTTdddddaaaaa111100",MMINORM,PSHIFT, (LEFT | LOGICAL | WORD)}, + + {"PSRAH", T5,"01110000000TTTTTdddddaaaaa110111",MMINORM,PSHIFT, (RIGHT | ARITHMETIC | HALFWORD)}, + {"PSRAVW", T5,"011100SSSSSTTTTTddddd00011101001",MMI3, PSRAVW, (NONE)}, + {"PSRAW", T5,"01110000000TTTTTdddddaaaaa111111",MMINORM,PSHIFT, (RIGHT | ARITHMETIC | WORD)}, + + {"PSRLH", T5,"01110000000TTTTTdddddaaaaa110110",MMINORM,PSHIFT, (RIGHT | LOGICAL | HALFWORD)}, + {"PSRLVW", T5,"011100SSSSSTTTTTddddd00011001001",MMI2, PSRLVW, (NONE)}, + {"PSRLW", T5,"01110000000TTTTTdddddaaaaa111110",MMINORM,PSHIFT, (RIGHT | LOGICAL | WORD)}, + + {"PSUBB", T5,"011100SSSSSTTTTTddddd01001001000",MMI0, PADD, (SUBTRACT | BYTE)}, + {"PSUBH", T5,"011100SSSSSTTTTTddddd00101001000",MMI0, PADD, (SUBTRACT | HALFWORD)}, + {"PSUBSB", T5,"011100SSSSSTTTTTddddd11001001000",MMI0, PADD, (SUBTRACT | SATURATE | BYTE )}, + {"PSUBSH", T5,"011100SSSSSTTTTTddddd10101001000",MMI0, PADD, (SUBTRACT | SATURATE | HALFWORD)}, + {"PSUBSW", T5,"011100SSSSSTTTTTddddd10001001000",MMI0, PADD, (SUBTRACT | SATURATE | WORD)}, + {"PSUBUB", T5,"011100SSSSSTTTTTddddd11001101000",MMI1, PADD, (SUBTRACT | UNSIGNED | BYTE)}, + {"PSUBUH", T5,"011100SSSSSTTTTTddddd10101101000",MMI1, PADD, (SUBTRACT | UNSIGNED | HALFWORD)}, + {"PSUBUW", T5,"011100SSSSSTTTTTddddd10001101000",MMI1, PADD, (SUBTRACT | UNSIGNED | WORD)}, + {"PSUBW", T5,"011100SSSSSTTTTTddddd00001001000",MMI0, PADD, (SUBTRACT | WORD)}, + + {"PXOR", T5,"011100SSSSSTTTTTddddd10011001001",MMI2, POP, (POP_XOR)}, + /* end-sanitize-r5900 */ + + {"PREF", G8,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)}, + {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X, FPPREFX, (FP)}, + + /* start-sanitize-r5900 */ + {"QFSRV", T5,"011100SSSSSTTTTTddddd11011101000",MMI1, QFSRV, (NONE)}, + /* end-sanitize-r5900 */ + + {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1, FPRECIP, (FP)}, + {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1, FPROUND, (FP | FIXED | DOUBLEWORD)}, + {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1, FPROUND, (FP | FIXED | WORD)}, + {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1, FPSQRT, (FP | RECIP)}, + {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (BYTE)}, + {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | ATOMIC)}, + {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | ATOMIC)}, + {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD)}, + {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)}, + {"SDBBP", G7,"000000????????????????????001110",SPECIAL,SDBBP, (NOARG)}, + {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)}, + {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | LEFT)}, + {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | RIGHT)}, + {"SDXC1", G3,"010011sssssgggggvvvvv00000001001",COP1X, STORE, (FP | DOUBLEWORD | COPROC | REG)}, + {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL, STORE, (HALFWORD)}, + {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << sa */ + {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */ + {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL,SET, (LT)}, + {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT)}, + {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL,SET, (LT | UNSIGNED)}, + {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT | UNSIGNED)}, + /* start-sanitize-r5900 */ + {"SQ", T5,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL, STORE, (QUADWORD)}, + /* end-sanitize-r5900 */ + {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1, FPSQRT, (FP)}, + {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)}, + {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)}, + {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)}, + {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)}, + {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL,SUB, (WORD | WORD32 | OVERFLOW)}, + {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1, FPSUB, (FP)}, + {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL,SUB, (WORD | WORD32)}, + {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD)}, + {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)}, + {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)}, + {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | LEFT)}, + {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | RIGHT)}, + {"SWXC1", G3,"010011sssssgggggvvvvv00000001000",COP1X, STORE, (FP | WORD | COPROC | REG)}, + {"SYNC", G4,"000000000000000000000aaaaa001111",SPECIAL,SYNC, (NONE)}, /* z = 5bit stype field */ + {"SYSCALL", 1,"000000????????????????????001100",SPECIAL,SYSCALL, (NOARG)}, + {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL,TRAP, (EQ)}, + {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM, TRAP, (EQ)}, + {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL,TRAP, (GT | EQ)}, + {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ)}, + {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ | UNSIGNED)}, + {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL,TRAP, (GT | EQ | UNSIGNED)}, + {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL,TRAP, (LT)}, + {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT)}, + {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT | UNSIGNED)}, + {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL,TRAP, (LT | UNSIGNED)}, + {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL,TRAP, (NOT | EQ)}, + {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM, TRAP, (NOT | EQ)}, + {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1, FPTRUNC, (FP | FIXED | DOUBLEWORD)}, + {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1, FPTRUNC, (FP | FIXED | WORD)}, + {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL,XOR, (NONE)}, + {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL, XOR, (NONE)}, + {"CACHE", G6,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, CACHE, (NONE)}, + {"", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL, RSVD, (NONE)}, +}; + +static const struct instruction MIPS16_DECODE[] = { +{"ADDIU", 1, "01000xxxddd04444", RRI_A, ADD, WORD | WORD32 }, +{"ADDIU8", 1, "01001wwwkkkkkkkk", RI, ADD, WORD | WORD32 }, +{"ADJSP", 1, "01100011KKKKKKKKS", I8, ADD, WORD | WORD32 }, +{"ADDIUPC", 1, "00001dddAAAAAAAAP", RI, ADD, WORD | WORD32 }, +{"ADDIUSP", 1, "00000dddAAAAAAAAs", RI, ADD, WORD | WORD32 }, +{"ADDU", 1, "11100xxxyyyddd01", RRR, ADD, WORD | WORD32 }, +{"AND", 1, "11101wwwyyy01100", RR, AND, NONE }, +{"B", 1, "00010qqqqqqqqqqqzZ", I, BRANCH, EQ }, +{"BEQZ", 1, "00100xxxppppppppz", RI, BRANCH, EQ }, +{"BNEZ", 1, "00101xxxppppppppz", RI, BRANCH, NOT | EQ }, +{"BREAK", 1, "01100??????00101", RR, BREAK, NOARG }, +{"BTEQZ", 1, "01100000pppppppptz", I8, BRANCH, EQ }, +{"BTNEZ", 1, "01100001pppppppptz", I8, BRANCH, NOT | EQ }, +{"CMP", 1, "11101xxxyyy01010T", RR, XOR, NONE }, +{"CMPI", 1, "01110xxxUUUUUUUUT", RI, XOR, NONE }, +{"DADDIU", 3, "01000xxxddd14444", RRI_A, ADD, DOUBLEWORD }, +{"DADDIU5", 3, "11111101wwwjjjjj", RI64, ADD, DOUBLEWORD }, +{"DADJSP", 3, "11111011KKKKKKKKS", I64, ADD, DOUBLEWORD }, +{"DADIUPC", 3, "11111110dddEEEEEP", RI64, ADD, DOUBLEWORD }, +{"DADIUSP", 3, "11111111dddEEEEEs", RI64, ADD, DOUBLEWORD }, +{"DADDU", 3, "11100xxxyyyddd00", RRR, ADD, DOUBLEWORD }, +{"DDIV", 3, "11101xxxyyy11110", RR, DIV, DOUBLEWORD | HI | LO }, +{"DDIVU", 3, "11101xxxyyy11111", RR, DIV, DOUBLEWORD | UNSIGNED | HI | LO }, +{"DIV", 1, "11101xxxyyy11010", RR, DIV, WORD | WORD32 | SIGNEXTEND | HI | LO }, +{"DIVU", 1, "11101xxxyyy11011", RR, DIV, WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO }, +{"DMULT", 3, "11101xxxyyy11100", RR, MUL, DOUBLEWORD | HI | LO }, +{"DMULTU", 3, "11101xxxyyy11101", RR, MUL, DOUBLEWORD | UNSIGNED | HI | LO }, +{"DSLL", 3, "00110dddyyy[[[01", ISHIFT, SHIFT, DOUBLEWORD | LEFT | LOGICAL }, +{"DSLLV", 3, "11101xxxvvv10100", RR, SHIFT, DOUBLEWORD | LEFT | LOGICAL | REG }, +{"DSRA", 3, "11101]]]vvv10011", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC }, +{"DSRAV", 3, "11101xxxvvv10111", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC | REG}, +{"DSRL", 3, "11101]]]vvv01000", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL }, +{"DSRLV", 3, "11101xxxvvv10110", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL | REG}, +{"DSUBU", 3, "11100xxxyyyddd10", RRR, SUB, DOUBLEWORD | UNSIGNED}, +#if 0 + /* FIXME: Should we handle these ourselves, or should we require an + emulation routine? */ +{"EXIT", 1, "1110111100001000", RR, BREAK, EXIT }, +{"ENTRY", 1, "11101??????01000", RR, BREAK, ENTRY }, +#endif +{"EXTEND", 1, "11110eeeeeeeeeee", I, RSVD, NOARG }, +{"JALR", 1, "11101xxx01000000R", RR, JUMP, LINK | REG }, +{"JAL", 1, "00011aaaaaaaaaaa", I, JUMP, LINK }, +{"JR", 1, "11101xxx00000000", RR, JUMP, NONE }, +{"JRRA", 1, "1110100000100000r", RR, JUMP, NONE }, +{"LB", 1, "10000xxxddd55555", RRI, LOAD, BYTE | SIGNEXTEND }, +{"LBU", 1, "10100xxxddd55555", RRI, LOAD, BYTE }, +{"LD", 3, "00111xxxdddDDDDD", RRI, LOAD, DOUBLEWORD }, +{"LDPC", 3, "11111100dddDDDDDP", RI64, LOAD, DOUBLEWORD }, +{"LDSP", 3, "11111000dddDDDDDs", RI64, LOAD, DOUBLEWORD }, +{"LH", 1, "10001xxxdddHHHHH", RRI, LOAD, HALFWORD | SIGNEXTEND }, +{"LHU", 1, "10101xxxdddHHHHH", RRI, LOAD, HALFWORD }, +{"LI", 1, "01101dddUUUUUUUUZ", RI, OR, NONE }, +{"LW", 1, "10011xxxdddWWWWW", RRI, LOAD, WORD | SIGNEXTEND }, +{"LWPC", 1, "10110dddVVVVVVVVP", RI, LOAD, WORD | SIGNEXTEND }, +{"LWSP", 1, "10010dddVVVVVVVVs", RI, LOAD, WORD | SIGNEXTEND }, +{"LWU", 1, "10111xxxdddWWWWW", RRI, LOAD, WORD }, +{"MFHI", 1, "11101ddd00010000", RR, MOVE, HI | LEFT }, +{"MFLO", 1, "11101ddd00010010", RR, MOVE, LO | LEFT }, +{"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32, OR, NONE }, +{"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R, OR, NONE }, +{"MULT", 1, "11101xxxyyy11000", RR, MUL, WORD | WORD32 | HI | LO}, +{"MULTU", 1, "11101xxxyyy11001", RR, MUL, WORD | WORD32 | UNSIGNED | HI | LO }, +{"NEG", 1, "11101dddyyy01011Z", RR, SUB, WORD }, +{"NOT", 1, "11101dddyyy01111Z", RR, OR, NOT }, +{"OR", 1, "11101wwwyyy01101", RR, OR, NONE }, +{"SB", 1, "11000xxxyyy55555", RRI, STORE, BYTE }, +{"SDBBP", G7, "11100??????00001", RR, SDBBP, NOARG }, +{"SD", 3, "01111xxxyyyDDDDD", RRI, STORE, DOUBLEWORD }, +{"SDSP", 3, "11111001yyyDDDDDs", RI64, STORE, DOUBLEWORD }, +{"SDRASP", 3, "11111010CCCCCCCCsQ", I64, STORE, DOUBLEWORD }, +{"SH", 1, "11001xxxyyyHHHHH", RRI, STORE, HALFWORD }, +{"SLL", 1, "00110dddyyy<<<00", ISHIFT, SHIFT, WORD | LEFT | LOGICAL }, +{"SLLV", 1, "11101xxxvvv00100", RR, SHIFT, WORD | LEFT | LOGICAL | REG}, +{"SLT", 1, "11101xxxyyy00010T", RR, SET, LT }, +{"SLTI", 1, "01010xxx88888888T", RI, SET, LT }, +{"SLTU", 1, "11101xxxyyy00011T", RR, SET, LT | UNSIGNED }, +{"SLTIU", 1, "01011xxx88888888T", RI, SET, LT | UNSIGNED }, +{"SRA", 1, "00110dddyyy<<<11", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC }, +{"SRAV", 1, "11101xxxvvv00111", RR, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC | REG }, +{"SRL", 1, "00110dddyyy<<<10", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | LOGICAL }, +{"SRLV", 1, "11101xxxvvv00110", RR, SHIFT, WORD | WORD32 | RIGHT | LOGICAL | REG }, +{"SUBU", 1, "11100xxxyyyddd11", RRR, SUB, WORD | WORD32 }, +{"SW", 1, "11011xxxyyyWWWWW", RRI, STORE, WORD }, +{"SWSP", 1, "11010yyyVVVVVVVVs", RI, STORE, WORD }, +{"SWRASP", 1, "01100010VVVVVVVVQs", I8, STORE, WORD }, +{"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE } +}; + +/*---------------------------------------------------------------------------*/ + +static void print_igen_insn_format PARAMS ((const char *bitmap, + inst_type mark, + int data_size, + const char *options, + const char *name)); + +static void +print_igen_insn_format (bitmap, mark, data_size, options, name) + const char *bitmap; + inst_type mark; + int data_size; + const char *options; + const char *name; +{ + const char *chp; + char lch = *bitmap; + for (chp = bitmap; *chp != '\0'; chp++) + { + if ((isdigit (lch) && !isdigit (*chp)) + || (!isdigit (lch) && isdigit (*chp)) + || (!isdigit (lch) && !isdigit (*chp) && lch != *chp)) + { + lch = *chp; + printf (","); + } + switch (*chp) + { + case '?': + printf ("*"); + break; + case '<': + printf ("s"); /* good guess */ + break; + default: + printf ("%c", *chp); + break; + } + } + printf (":"); + switch (mark) + { + case NORMAL: + printf ("NORMAL"); + break; + case SPECIAL: + printf ("SPECIAL"); + break; + case REGIMM: + printf ("REGIMM"); + break; + case COP1: + printf ("COP1"); + break; + case COP1X: + printf ("COP1X"); + break; + case COP1S: /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */ + printf ("COP1S"); + break; + + case MMINORM: + printf ("MMINORM"); + break; + case MMI0: + printf ("MMI0"); + break; + case MMI1: + printf ("MMI1"); + break; + case MMI2: + printf ("MMI2"); + break; + case MMI3: + printf ("MMI3"); + break; + + /* mips16 encoding types. */ + case I: + printf ("I"); + break; + case RI: + printf ("RI"); + break; + case RR: + printf ("RR"); + break; + case RRI: + printf ("RRI"); + break; + case RRR: + printf ("RRR"); + break; + case RRI_A: + printf ("RRI_A"); + break; + case ISHIFT: + printf ("ISHIFT"); + break; + case I8: + printf ("I8"); + break; + case I8_MOVR32: + printf ("I8_MOVR32"); + break; + case I8_MOV32R: + printf ("I8_MOV32R"); + break; + case I64: + printf ("I64"); + break; + case RI64: + printf ("RI64"); + break; + } + printf (":"); + switch (data_size) + { + case DOUBLEWORD: + printf ("64"); + break; + /* start-sanitize-r5900 */ + case QUADWORD: + printf ("128"); + break; + /* end-sanitize-r5900 */ + case -1: + printf ("16"); + break; + default: + printf ("32"); + } + printf (":%s:%s\n", options, name); +} + +static void print_igen_insn_models PARAMS ((unsigned int isa)); + +static void +print_igen_insn_models (isa) + unsigned int isa; +{ + /* common mips ISAs */ + switch ((isa & MASK_ISA)) + { + case 1: + printf ("*mipsI:\n"); + case 2: + printf ("*mipsII:\n"); + case 3: + printf ("*mipsIII:\n"); + /* start-sanitize-cygnus-never */ + printf ("// %s-%s-%s\n", "start", "sanitize", "r5900"); + /* end-sanitize-cygnus-never */ + /* start-sanitize-r5900 */ + printf ("*r5900:\n"); + /* end-sanitize-r5900 */ + /* start-sanitize-cygnus-never */ + printf ("// %s-%s-%s\n", "end", "sanitize", "r5900"); + /* end-sanitize-cygnus-never */ + printf ("*r3900:\n"); + /* start-sanitize-cygnus-never */ + printf ("// %s-%s-%s\n", "start", "sanitize", "tx19"); + /* end-sanitize-cygnus-never */ + /* start-sanitize-tx19 */ + printf ("*tx19:\n"); + /* end-sanitize-tx19 */ + /* start-sanitize-cygnus-never */ + printf ("// %s-%s-%s\n", "end", "sanitize", "tx19"); + /* end-sanitize-cygnus-never */ + break; + default: + /* processor specific ISAs */ + if ((isa & ARCH_VR4100)) + printf ("*vr4100:\n"); + /* start-sanitize-r5900 */ + if ((isa & ARCH_R5900)) + printf ("*r5900:\n"); + /* end-sanitize-r5900 */ + if ((isa & ARCH_R3900)) + printf ("*r3900:\n"); + } +} + +/*---------------------------------------------------------------------------*/ + +static int bitmap_val PARAMS ((const char *, int, int)); +static void build_mips16_operands PARAMS ((const char *)); +static void build_instruction + PARAMS ((int, unsigned int, int, const struct instruction *)); + +/*---------------------------------------------------------------------------*/ + +static char* +name_for_data_len( insn ) + struct instruction* insn; + { + if (GETDATASIZEINSN(insn) == BYTE) + return "BYTE"; + + else if (GETDATASIZEINSN(insn) == HALFWORD) + return "HALFWORD"; + + else if (GETDATASIZEINSN(insn) == WORD) + return "WORD"; + + else if (GETDATASIZEINSN(insn) == DOUBLEWORD) + return "DOUBLEWORD"; + + /* start-sanitize-r5900 */ + else if (GETDATASIZEINSN(insn) == QUADWORD) + return "QUADWORD"; + + /* end-sanitize-r5900 */ + else + return 0; + } + +static char* +letter_for_data_len( insn ) + struct instruction* insn; + { + if (GETDATASIZEINSN(insn) == BYTE) + return "B"; + + else if (GETDATASIZEINSN(insn) == HALFWORD) + return "H"; + + else if (GETDATASIZEINSN(insn) == WORD) + return "W"; + + else if (GETDATASIZEINSN(insn) == DOUBLEWORD) + return "D"; + + /* start-sanitize-r5900 */ + else if (GETDATASIZEINSN(insn) == QUADWORD) + return "Q"; + + /* end-sanitize-r5900 */ + else + return 0; + } + +static char* +type_for_data_len( insn , is_signed ) + struct instruction* insn; + int is_signed; + { + if (GETDATASIZEINSN(insn) == BYTE) + return is_signed ? "int" : "unsigned int"; + + else if (GETDATASIZEINSN(insn) == HALFWORD) + return is_signed ? "int" : "unsigned int"; + + else if (GETDATASIZEINSN(insn) == WORD) + return is_signed ? "signed64" : "unsigned64"; + + else if (GETDATASIZEINSN(insn) == DOUBLEWORD) + return 0; + + /* start-sanitize-r5900 */ + else if (GETDATASIZEINSN(insn) == QUADWORD) + return 0; + + /* end-sanitize-r5900 */ + else + return 0; + } + +static char* +max_for_data_len( insn ) + struct instruction* insn; + { + if (GETDATASIZEINSN(insn) == BYTE) + return "127"; + + else if (GETDATASIZEINSN(insn) == HALFWORD) + return "32767"; + + else if (GETDATASIZEINSN(insn) == WORD) + return "(int)0x7FFFFFFF"; + + else if (GETDATASIZEINSN(insn) == DOUBLEWORD) + return 0; + + /* start-sanitize-r5900 */ + else if (GETDATASIZEINSN(insn) == QUADWORD) + return 0; + + /* end-sanitize-r5900 */ + else + return 0; + } + +static char* +min_for_data_len( insn ) + struct instruction* insn; + { + if (GETDATASIZEINSN(insn) == BYTE) + return "-128"; + + else if (GETDATASIZEINSN(insn) == HALFWORD) + return "-32768"; + + else if (GETDATASIZEINSN(insn) == WORD) + return "(int)0x80000000"; + + else if (GETDATASIZEINSN(insn) == DOUBLEWORD) + return 0; + + /* start-sanitize-r5900 */ + else if (GETDATASIZEINSN(insn) == QUADWORD) + return 0; + + /* end-sanitize-r5900 */ + else + return 0; + } + +static char* +umax_for_data_len( insn ) + struct instruction* insn; + { + if (GETDATASIZEINSN(insn) == BYTE) + return "0xFF"; + + else if (GETDATASIZEINSN(insn) == HALFWORD) + return "0xFFFF"; + + else if (GETDATASIZEINSN(insn) == WORD) + return "0xFFFFFFFF"; + + else if (GETDATASIZEINSN(insn) == DOUBLEWORD) + return 0; + + /* start-sanitize-r5900 */ + else if (GETDATASIZEINSN(insn) == QUADWORD) + return 0; + + /* end-sanitize-r5900 */ + else + return 0; + } + +static char* +bits_for_data_len( insn ) + struct instruction* insn; + { + if (GETDATASIZEINSN(insn) == BYTE) + return "8"; + + else if (GETDATASIZEINSN(insn) == HALFWORD) + return "16"; + + else if (GETDATASIZEINSN(insn) == WORD) + return "32"; + + else if (GETDATASIZEINSN(insn) == DOUBLEWORD) + return "64"; + + /* start-sanitize-r5900 */ + else if (GETDATASIZEINSN(insn) == QUADWORD) + return "128"; + + /* end-sanitize-r5900 */ + else + return 0; + } + +/*---------------------------------------------------------------------------*/ + + +void +convert_bitmap(bitmap,onemask,zeromask,dontmask) + char *bitmap; + unsigned int *onemask, *zeromask, *dontmask; +{ + int loop; /* current bitmap position */ + int lastsp = -1; /* last bitmap field starting position */ + int lastoe = -1; /* last bitmap field encoding */ + + *onemask = 0x00000000; + *zeromask = 0x00000000; + *dontmask = 0x00000000; + + if (strlen(bitmap) != 32) { + fprintf(stderr,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap); + exit(3); + } + + for (loop = 0; (loop < 32); loop++) { + int oefield ; + for (oefield = 0; (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))); oefield++) + if (bitmap[31 - loop] == opfields[oefield].id) + break; + if (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))) { + if ((lastoe != -1) && (lastoe != oefield)) + if ((loop - lastsp) != (opfields[lastoe].flen)) { + fprintf(stderr,"Invalid field length %d for bitmap field '%c' (0x%02X) (should be %d) : bitmap = \"%s\"\n",(loop - lastsp),(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],opfields[lastoe].flen,bitmap); + exit(4); + } + + switch (bitmap[31 - loop]) { + case '0' : /* fixed value */ + *zeromask |= (1 << loop); + lastsp = loop; + lastoe = -1; + break; + + case '1' : /* fixed value */ + *onemask |= (1 << loop); + lastsp = loop; + lastoe = -1; + break; + + case '?' : /* fixed value */ + *dontmask |= (1 << loop); + lastsp = loop; + lastoe = -1; + break; + + default : /* check character encoding */ + { + if (opfields[oefield].fpos != -1) { + /* If flag not set, then check starting position: */ + if (lastoe != oefield) { + if (loop != opfields[oefield].fpos) { + fprintf(stderr,"Bitmap field '%c' (0x%02X) at wrong offset %d in bitmap \"%s\"\n",(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],loop,bitmap); + exit(4); + } + lastsp = loop; + lastoe = oefield; + } + } + *dontmask |= (1 << loop); + } + break; + } + } else { + fprintf(stderr,"Unrecognised bitmap character '%c' (0x%02X) at offset %d in bitmap \"%s\"\n",(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],loop,bitmap); + exit(4); + } + } + + /* NOTE: Since we check for the position and size of fields when + parsing the "bitmap" above, we do *NOT* need to check that invalid + field combinations have been used. */ +} + +/* Get the value of a 16 bit bitstring for a given shift count and + number of bits. */ + +static int +bitmap_val (bitmap, shift, bits) + const char *bitmap; + int shift; + int bits; +{ + const char *s; + int ret; + + ret = 0; + s = bitmap + 16 - shift - bits; + for (; bits > 0; --bits) + { + ret <<= 1; + if (*s == '0') + ; + else if (*s == '1') + ret |= 1; + else + abort (); + ++s; + } + + return ret; +} + +/*---------------------------------------------------------------------------*/ + +static void +build_operands(doisa,features,insn) + int doisa; + unsigned int features; + instruction* insn; +{ + int proc64 = ((features & FEATURE_PROC32) ? 0 : -1); + int finish_jump_flag = 0; + int check_mult = 0; + int check_condition_code = 0; + int sfield_used = 0; + int gfield_used = 0; + int any_operand = 0; + + int current_field_id = -1; + int bitpos; + + for (bitpos=0; bitpos<32; bitpos++) { + if (insn->bitmap[31-bitpos] != current_field_id) + { + int opindex; + + current_field_id = insn->bitmap[31-bitpos]; + + for (opindex = 0; (opindex < (sizeof(opfields) / sizeof(operand_encoding))); opindex++) + if ((opfields[opindex].fpos != -1) && (opfields[opindex].id == insn->bitmap[31-bitpos])) { + + any_operand = 1; + + printf(" %s %s UNUSED = ",opfields[opindex].type,opfields[opindex].name); + + if (opfields[opindex].flags & OP_SIGNX) + printf("SIGNEXTEND((%s)",opfields[opindex].type); + + if (opfields[opindex].flags & OP_GPR) + printf("GPR["); + + if (opfields[opindex].flags & OP_SHIFT2) + printf("("); + + printf("((instruction >> %d) & 0x%08X)",opfields[opindex].fpos,((1 << opfields[opindex].flen) - 1)); + + if (opfields[opindex].flags & OP_SHIFT2) + printf(" << 2)"); + + if (opfields[opindex].flags & OP_GPR) + printf("]"); + + if (opfields[opindex].flags & OP_BITS5) + printf("&0x1F"); + + if (opfields[opindex].flags & OP_SIGNX) + printf(",%d)",(opfields[opindex].flen + ((opfields[opindex].flags & OP_SHIFT2) ? 2 : 0))); + + printf(";\n"); + + if (opfields[opindex].flags & OP_GPR1) + { + printf(" %s %s1 = GPR1[",opfields[opindex].type,opfields[opindex].name); + printf("((instruction >> %d) & 0x%08X)", + opfields[opindex].fpos, + ((1 << opfields[opindex].flen) - 1)); + printf("];\n"); + } + + if (opfields[opindex].id == 'j') + finish_jump_flag = 1; + + if (opfields[opindex].id == 'e') + check_mult = 8; + + if (opfields[opindex].id == 'w') + check_mult = 4; + + if (opfields[opindex].id == 'w') + check_mult = 2; + + if (opfields[opindex].id == 'p') + check_condition_code = 1; + + if (opfields[opindex].id == 's') + sfield_used = 1; + + if (opfields[opindex].id == 'g') + gfield_used = 1; + } + } + } + + if ( !any_operand && !(insn->flags & NOARG)) { + fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn->name) ; + exit(5) ; + } + + /* Finish constructing the jump address if required: */ + if (finish_jump_flag) + printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n"); + + /* Now perform required operand checks: */ + + /* The following code has been removed, since it seems perfectly + reasonable to have a non-aligned offset that is added to another + non-aligned base to create an aligned address. Some more + information on exactly what the MIPS IV specification requires is + needed before deciding on the best strategy. Experimentation with a + VR4300 suggests that we do not need to raise the warning. */ +#if 0 + /* For MIPS IV (and onwards), certain instruction operand values + will give undefined results. For the simulator we could + generate explicit exceptions (i.e. ReservedInstruction) to + make it easier to spot invalid use. However, for the moment we + just raise a warning. NOTE: This is a different check to the + later decoding, which checks for the final address being + valid. */ + + if (check_mult != 0 && check_mult != 1) { + printf(" if (instruction & 0x%1X)\n", check_mult); + printf(" {\n"); + /* NOTE: If we change this to a SignalException(), we must + ensure that the following opcode processing is not + executed. i.e. the code falls straight out to the simulator + control loop. */ + printf(" sim_io_eprintf(sd,\"Instruction has lo-order offset bits set in instruction\\n\");\n"); + printf(" }\n"); + } +#endif + + /* The extended condition codes only appeared in ISA IV */ + if (check_condition_code && (doisa < 4)) { + printf(" if (condition_code != 0)\n"); + printf(" {\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" }\n"); + printf(" else\n"); + } + + if ((insn->flags & WORD32) && (GETDATASIZEINSN(insn) != WORD)) { + fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n"); + exit(1); + } + +#if 1 + /* The R4000 book differs slightly from the MIPS IV ISA + manual. An example is the sign-extension of a 64-bit processor + SUBU operation, and what is meant by an Undefined Result. This + is now provided purely as a warning. After examining a HW + implementation, this is now purely a warning... and the actual + operation is performed, with possibly undefined results. */ + if (((insn->flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) { + /* The compiler should optimise out an OR with zero */ + printf(" if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0")); + printf(" UndefinedResult();\n") ; + } +#else + /* Check that the source is a 32bit value */ + if ((insn->flags & WORD32) && proc64) { + /* The compiler should optimise out an OR with zero */ + printf(" if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0")); + printf(" UndefinedResult();\n") ; + printf(" else\n") ; + } +#endif + + return; +} + +/* The mips16 operand table. */ + +struct mips16_op +{ + /* The character which appears in the bitmap string. */ + int type; + /* The type of the variable in the simulator. */ + const char *vartype; + /* The name of the variable in the simulator. */ + const char *name; + /* The number of bits. */ + int nbits; + /* The number of bits when extended (zero if can not be extended). */ + int extbits; + /* The amount by which the short form is shifted when it is used; + for example, the sw instruction has a shift count of 2. */ + int shift; + /* Flags. */ + int flags; +}; + +/* Flags which appears in the mips16 operand table. */ + +/* Whether this is a mips16 register index. */ +#define MIPS16_REG16 (0x1) +/* Whether this is a register value. */ +#define MIPS16_REGVAL (0x2) +/* Whether this is a swapped mips32 register index (MOV32R) */ +#define MIPS16_REG32_SWAPPED (0x4) +/* Whether this index is also the destination register. */ +#define MIPS16_DESTREG (0x8) +/* Whether the short form is unsigned. */ +#define MIPS16_UNSP (0x10) +/* Whether the extended form is unsigned. */ +#define MIPS16_EXTU (0x20) +/* Implicit stack pointer. */ +#define MIPS16_SP (0x40) +/* Implicit program counter. */ +#define MIPS16_PC (0x80) +/* Implicit $0. */ +#define MIPS16_ZERO (0x100) +/* Implicit $24. */ +#define MIPS16_TREG (0x200) +/* Implicit $31. */ +#define MIPS16_RA (0x400) +/* Jump address. */ +#define MIPS16_JUMP_ADDR (0x800) +/* Branch offset. */ +#define MIPS16_BRANCH (0x1000) + +/* The mips16 operand table. */ + +static const struct mips16_op mips16_op_table[] = +{ + { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16 }, + { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL }, + { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG}, + { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL }, + { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG }, + { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL }, + { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED }, + { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR }, + { 'e', "int", "ext", 11, 0, 0, 0 }, + { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU }, + { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU }, + { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU }, + { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU }, + { '4', "int", "op2", 4, 15, 0, 0 }, + { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP }, + { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP }, + { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP }, + { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP }, + { 'j', "int", "op2", 5, 16, 0, 0 }, + { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP }, + { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP }, + { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP }, + { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP | MIPS16_EXTU }, + { 'k', "int", "op2", 8, 16, 0, 0 }, + { 'K', "int", "op2", 8, 16, 3, 0 }, + { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH }, + { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH }, + { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP }, + { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP }, + { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP }, + + /* The remaining operands are special operands which encode implied + arguments. These only appear at the end of a bitmap string, and + do not represent actual bits. */ + { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP | MIPS16_REGVAL }, + { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP|MIPS16_REGVAL|MIPS16_DESTREG }, + { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC }, + { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO }, + { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO }, + { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG | MIPS16_REGVAL }, + { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG }, + { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL }, + { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA }, + { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL }, + + { '\0', NULL, NULL, 0, 0, 0, 0 } +}; + +/* Build mips16 operands. */ + +static void +build_mips16_operands (bitmap) + const char *bitmap; +{ + const char *s; + int start = -1; + const struct mips16_op *op = NULL; + const struct mips16_op *ops[3]; + int opindex = 0; + int i; + + for (s = bitmap; *s != '\0'; s++) + { + if (op != NULL) + { + if (op->type == *s) + continue; + + /* Make sure we saw the right number of bits for that + operand. */ + if (op->nbits != 0 && (s - bitmap) - op->nbits != start) + abort (); + op = NULL; + } + + if (*s == '0' || *s == '1' || *s == '?') + continue; + + start = s - bitmap; + + for (op = mips16_op_table; op->type != *s; ++op) + if (op->type == '\0') + abort (); + + printf (" %s %s = ", op->vartype, op->name); + if (op->nbits != 0) + printf ("(instruction >> %d) & 0x%x", + 16 - (s - bitmap) - op->nbits, + (1 << op->nbits) - 1); + else + { + if ((op->flags & MIPS16_SP) != 0) + printf ("29"); + else if ((op->flags & MIPS16_PC) != 0) + { + int j; + + printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? cia - 4 : cia - 2) : (have_extendval ? cia - 2 : cia)) & ~ (uword64) 1)"); + for (j = 0; j < opindex; j++) + if (ops[j]->shift != 0) + printf (" & ~ (uword64) 0x%x", (1 << ops[j]->shift) - 1); + } + else if ((op->flags & MIPS16_ZERO) != 0) + printf ("0"); + else if ((op->flags & MIPS16_TREG) != 0) + printf ("24"); + else if ((op->flags & MIPS16_RA) != 0) + printf ("31"); + else + abort (); + } + printf (";\n"); + + if ((op->flags & MIPS16_DESTREG) != 0) + printf (" int destreg;\n"); + + if (opindex > 2) + abort (); + ops[opindex] = op; + ++opindex; + } + + if (op != NULL) + { + /* Make sure we saw the right number of bits for that + operand. */ + if (op->nbits != 0 && 16 - op->nbits != start) + abort (); + } + + for (i = 0; i < opindex; i++) + { + op = ops[i]; + if ((op->flags & MIPS16_REG16) != 0) + { + printf (" if (%s < 2)\n", op->name); + printf (" %s += 16;\n", op->name); + } + if ((op->flags & MIPS16_REG32_SWAPPED) != 0) + printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n", + op->name, op->name, op->name); + if ((op->flags & MIPS16_DESTREG) != 0) + printf (" destreg = %s;\n", op->name); + if ((op->flags & MIPS16_REGVAL) != 0) + printf (" %s = GPR[%s];\n", op->name, op->name); + + if (op->extbits != 0) + { + printf (" if (have_extendval)\n"); + printf (" {\n"); + if (op->extbits == 16) + printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n", + op->name); + else if (op->extbits == 15) + printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n", + op->name); + else if (op->extbits == 6) + printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n", + op->name); + else + printf (" %s = (extendval >> 6) & 0x1f;\n", + op->name); + if ((op->flags & MIPS16_EXTU) == 0) + { + printf (" if (%s >= 0x%x)\n", + op->name, 1 << (op->extbits - 1)); + printf (" %s -= 0x%x;\n", + op->name, 1 << op->extbits); + } + printf (" have_extendval = 0;\n"); + printf (" }\n"); + printf (" else\n"); + printf (" {\n"); + if ((op->flags & MIPS16_UNSP) == 0) + { + printf (" if (%s >= 0x%x)\n", + op->name, 1 << (op->nbits - 1)); + printf (" %s -= 0x%x;\n", + op->name, 1 << op->nbits); + } + if (op->shift != 0) + printf (" %s <<= %d;\n", op->name, op->shift); + if (op->type == '<' || op->type == '>' + || op->type == '[' || op->type == ']') + { + printf (" if (%s == 0)\n", op->name); + printf (" %s = 8;\n", op->name); + } + printf (" }\n"); + } + + if ((op->flags & MIPS16_BRANCH) != 0) + printf (" %s *= 2;\n", op->name); + + if ((op->flags & MIPS16_JUMP_ADDR) != 0) + { + printf (" {\n"); + printf (" address_word paddr;\n"); + printf (" int uncached;\n"); + printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n"); + printf (" {\n"); + printf (" uword64 memval;\n"); + printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n"); + printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n"); + printf (" unsigned int byte;\n"); + printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n"); + printf (" LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n"); + printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n"); + printf (" memval = (memval >> (8 * byte)) & 0xffff;\n"); + printf (" %s = (((%s & 0x1f) << 23)\n", op->name, op->name); + printf (" | ((%s & 0x3e0) << 13)\n", op->name); + printf (" | (memval << 2));\n"); + printf (" if ((instruction & 0x400) == 0)\n"); + printf (" %s |= 1;\n", op->name); + printf (" PC += 2;\n"); + printf (" }\n"); + printf (" }\n"); + printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op->name); + } + } + + /* FIXME: Is this the way to detect an unused extend opcode? */ + printf (" if (have_extendval)\n"); + printf (" SignalException (ReservedInstruction, instruction);\n"); +} + +/*---------------------------------------------------------------------------*/ + +typedef enum { + s_left, + s_right +} e_endshift; + +static void +build_endian_shift(proc64,datalen,endbit,direction,shift) + int proc64; + int datalen; + int endbit; + e_endshift direction; + int shift; +{ + if (datalen == 4) { + printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit,endbit); + printf(" memval %s= %d;\n",direction == s_left ? "<<" : ">>",shift); + printf(" }\n"); + } + + return; +} + +/*---------------------------------------------------------------------------*/ +/* doisa = number of MIPS ISA simulator table is being constructed for. + * proc64 = TRUE if constructing 64bit processor world. + * dofp = boolean, TRUE if FP instructions are to be included. + * fpsingle = boolean, TRUE if only single precision FP instructions to be included. + */ + +void +process_instructions(doarch,features) + unsigned int doarch; + unsigned int features; +{ + int doisa = (doarch & MASK_ISA); + int limit = (sizeof(MIPS_DECODE) / sizeof(instruction)); + int gprlen=((features & FEATURE_GP64) ? 64 : 32); + int proc64 = ((features & FEATURE_PROC32) ? 0 : -1); + int dofp = (features & FEATURE_HASFPU); + int fpsingle = (features & FEATURE_FPSINGLE); + int maxisa; + int loop; + + if (limit < 1) { + fprintf(stderr,"process_instructions: invalid structure length\n"); + exit(1); + } + + if (proc64 && (gprlen != 64)) { + fprintf(stderr,"Error: 64bit processor build specified, with MIPS ISA I or II\n"); + exit(3); + } + + /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */ + + maxisa = 0; + for (loop = 0; (loop < limit); loop++) + if ((MIPS_DECODE[loop].isa & MASK_ISA) > maxisa) + maxisa = (MIPS_DECODE[loop].isa & MASK_ISA); + + if (doisa == 0) + doisa = maxisa; + + if (!(features & FEATURE_IGEN)) + { + printf("#if defined(SIM_MANIFESTS)\n"); + printf("#define MIPSISA (%d)\n",doisa); + if (proc64) + printf("#define PROCESSOR_64BIT (1 == 1)\n"); + else + printf("#define PROCESSOR_64BIT (1 == 0)\n"); +#if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */ + printf("#define LOADDRMASK (0x%08X)\n",0x7); +#else + printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3)); +#endif + /* The FP registers are the same width as the CPU registers: */ + printf("#define GPRLEN (%d)\n",gprlen); + printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int")); + printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int")); + printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int")); + if (dofp) + printf("#define HASFPU (1 == 1)\n"); + if (features & FEATURE_FAST) + printf("#define FASTSIM (1 == 1)\n"); + if (features & FEATURE_WARN_STALL) + printf("#define WARN_STALL (1 == 1)\n"); + if (features & FEATURE_WARN_LOHI) + printf("#define WARN_LOHI (1 == 1)\n"); + if (features & FEATURE_WARN_ZERO) + printf("#define WARN_ZERO (1 == 1)\n"); + if (features & FEATURE_WARN_MEM) + printf("#define WARN_MEM (1 == 1)\n"); + if (features & FEATURE_WARN_R31) + printf("#define WARN_R31 (1 == 1)\n"); + if (features & FEATURE_WARN_RESULT) + printf("#define WARN_RESULT (1 == 1)\n"); + + printf("#else /* simulator engine */\n"); + + printf("/* Engine generated by \"%s\" at %s */\n","",""); + printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit); + if (dofp) + printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : "")); + printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n"); + + if (proc64) { + printf("#if !defined(PROCESSOR_64BIT)\n"); + printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n"); + printf("#endif\n"); + } + + printf("/* Actual instruction decoding block */\n"); + printf("if ((vaddr & 1) == 0){\n"); + { + int limit; + printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP); + limit = (OP_MASK_OP + 1); + + printf("#ifdef DEBUG\n"); + printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n"); + printf("#endif\n"); + + printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC); + limit += (OP_MASK_SPEC + 1); + + printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT); + limit += (OP_MASK_RT + 1); + + printf("else if (num == 0x11) {\n"); + printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM)); + printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP)); + printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP))); + printf(" else\n"); + printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC); + limit += (OP_MASK_SPEC + 1); + + printf(" else\n"); + /* To keep this code quick, we just clear out the "to" bit + here. The proper (though slower) code would be to have another + conditional, checking whether this instruction is a branch or + not, before limiting the range to the bottom two bits of the + move operation. */ + printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR); + limit += (OP_MASK_COP1SPEC + 1); + + printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC); + limit += (OP_MASK_SPEC + 1); + + printf("else if (num == 0x1C) {\n"); + printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI,OP_MASK_MMI); + + printf(" if (mmi_func == 0x08) \n"); + printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); + limit += (OP_MASK_MMISUB + 1); + + printf(" else if (mmi_func == 0x28) \n"); + printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); + limit += (OP_MASK_MMISUB + 1); + + printf(" else if (mmi_func == 0x09) \n"); + printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); + limit += (OP_MASK_MMISUB + 1); + + printf(" else if (mmi_func == 0x29) \n"); + printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB); + limit += (OP_MASK_MMISUB + 1); + + printf(" else \n"); + printf(" num = (%d + mmi_func);\n",limit); + limit += (OP_MASK_MMI + 1); + + printf("}\n"); + + printf("/* Total possible switch entries: %d */\n",limit) ; + } + + printf("#ifdef DEBUG\n"); + printf("printf(\"DBG: num = %%d\\n\",num);\n"); + printf("#endif\n"); + + printf("switch (num)\n") ; + printf("{\n"); + } + + for (loop = 0; (loop < limit); loop++) { + /* First check if the insn is in a requested isa# independent set, + then check that the ISA number we are constructing for is + valid, then if the instruction matches any of the + architecture specific flags. NOTE: We allow a selected ISA of + zero to be used to match all standard instructions. */ + unsigned int isa = MIPS_DECODE[loop].isa; + if (((isa & doarch & MASK_ISA_INDEP) + || (((isa & MASK_ISA) <= doisa) + && (((isa & MASK_ISA_DEP) == 0) || ((isa & MASK_ISA_DEP) & doarch) != 0))) + && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp)) + || (features & FEATURE_IGEN)) { + unsigned int onemask; + unsigned int zeromask; + unsigned int dontmask; + unsigned int mask; + unsigned int number; + + convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask); + + if (!(MIPS_DECODE[loop].flags & COPROC) + && ((GETDATASIZEINSN(&MIPS_DECODE[loop]) == DOUBLEWORD) && !proc64) + && !(features & FEATURE_IGEN)) { + fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name); + exit(4); + } + +#if defined(DEBUG) + printf("/* DEBUG: onemask 0x%08X */\n",onemask) ; + printf("/* DEBUG: zeromask 0x%08X */\n",zeromask) ; + printf("/* DEBUG: dontmask 0x%08X */\n",dontmask) ; +#endif + + switch (MIPS_DECODE[loop].mark) { + case NORMAL : + mask = (OP_MASK_OP << OP_SH_OP) ; + number = ((onemask >> OP_SH_OP) & OP_MASK_OP) ; + break ; + + case SPECIAL : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ; + number = ((OP_MASK_OP + 1) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ; + break ; + + case REGIMM : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_RT << OP_SH_RT)) ; + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_RT) & OP_MASK_RT)) ; + break ; + + case COP1 : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ; + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ; + break ; + + case COP1S : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_COP1SPEC << OP_SH_COP1SPEC)) ; + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_COP1SPEC) & OP_MASK_COP1SPEC)) ; + break; + + case COP1X : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ; + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ; + break ; + + case MMI0 : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI) + | (OP_MASK_MMISUB << OP_SH_MMISUB)); + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ; + break ; + + case MMI1 : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI) + | (OP_MASK_MMISUB << OP_SH_MMISUB)); + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + + (OP_MASK_MMISUB + 1) + + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ; + break ; + + case MMI2 : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI) + | (OP_MASK_MMISUB << OP_SH_MMISUB)); + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ; + break ; + + case MMI3 : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI) + | (OP_MASK_MMISUB << OP_SH_MMISUB)); + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ; + break ; + + case MMINORM : + mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)) ; + number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + + (OP_MASK_MMISUB + 1) + + ((onemask >> OP_SH_MMI) & OP_MASK_MMI)) ; + break ; + + default : + fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ; + exit(5) ; + } + + if (!(features & FEATURE_IGEN)) + { + printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ; + +#if defined(DEBUG) + printf("/* DEBUG: mask 0x%08X */\n",mask) ; + printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name); +#endif + + /* Check if there are any other explicit bits in the instruction: */ + if ((~mask & (onemask | zeromask)) != 0x00000000) { + printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ; + printf(" {\n") ; + printf(" SignalException(ReservedInstruction,instruction);\n") ; + printf(" }\n") ; + printf(" else\n") ; + } + + printf(" {\n") ; + } + else + { + /* start-sanitize-cygnus-never */ + /* If any sanitization occures, this line should be printed */ + if ((MIPS_DECODE[loop].isa & ARCH_R5900)) + printf ("// %s-%s-%s\n", "start", "sanitize", "r5900"); + /* end-sanitize-cygnus-never */ + printf ("\n"); + print_igen_insn_format (MIPS_DECODE[loop].bitmap, + MIPS_DECODE[loop].mark, /* format-name */ + GETDATASIZEINSN (&MIPS_DECODE[loop]), /* filter-flags */ + "", /* options */ + MIPS_DECODE[loop].name); + print_igen_insn_models (MIPS_DECODE[loop].isa); + printf ("{\n") ; + printf (" unsigned32 instruction = instruction_0;\n"); + } + + /* Get hold of the operands */ + /* NOTE: If we wanted to make the simulator code smaller, we + * could pull these into a common sequence before we perform + * the instruction decoding. However, this would affect the + * performance since unnecessary field extraction would be + * occurring for certain instructions. + * + * Also we do not perform checking for multiple definitions of a + * particular operand here, since they are caught by the + * compilation of the produced code. + */ + build_operands(doisa, features, &MIPS_DECODE[loop]); + + printf(" {\n") ; + + build_instruction (doisa, features, 0, &MIPS_DECODE[loop]); + + printf(" }\n") ; + if (!(features & FEATURE_IGEN)) + { + printf(" }\n") ; + printf(" break ;\n") ; + } + else + { + printf ("}\n"); + printf ("\n"); + /* start-sanitize-cygnus-never */ + /* When sanitized, this output should never be produced */ + if ((MIPS_DECODE[loop].isa & ARCH_R5900)) + printf ("// %s-%s-%s\n", "end", "sanitize", "r5900"); + /* end-sanitize-cygnus-never */ + } + + } + } + + + if (!(features & FEATURE_IGEN)) + { + printf("default : /* Unrecognised instruction */\n") ; + printf(" SignalException(ReservedInstruction,instruction);\n") ; + printf(" break ;\n") ; + printf("}\n}\n") ; + } + + /* Handle mips16 instructions. The switch table looks like this: + 0 - 31: I, RI, and RRI instructions by major. + 32 - 35: ISHIFT instructions by function + 32 + 36 - 37: RRI_A instructions by function + 36 + 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38 + 46 - 49: RRR instructions by function + 46 + 50 - 81: RR instructions by minor + 50 (except for minor == 0) + 82 - 89: I64 and RI64 instructions by funct + 82 + 90 - 97: jalr (RR minor 0) by y + 90 + */ + if (!(features & FEATURE_IGEN)) + { + printf ("else {\n"); + printf ("static int extendval;\n"); + printf ("static int have_extendval;\n"); + printf ("int num = ((instruction >> %d) & 0x%08X);\n", + MIPS16OP_SH_OP, MIPS16OP_MASK_OP); + printf ("switch (num)\n{\n"); + printf ("case 0x6: num = 32 + (instruction & 3); break;\n"); + printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n"); + printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n"); + printf ("case 0x1c: num = 46 + (instruction & 3); break;\n"); + printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n"); + printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n"); + printf (" break;\n"); + printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n"); + printf ("default: break;\n}\n"); + printf ("switch (num)\n{\n"); + } + + for (loop = 0; loop < sizeof MIPS16_DECODE / sizeof MIPS16_DECODE[0]; loop++) + { + const char *bitmap; + int num; + + if (! proc64 && GETDATASIZEINSN (&MIPS16_DECODE[loop]) == DOUBLEWORD) + continue; + + bitmap = MIPS16_DECODE[loop].bitmap; + switch (MIPS16_DECODE[loop].mark) + { + case I: + case RI: + case RRI: + num = bitmap_val (bitmap, 11, 5); + break; + case ISHIFT: + num = 32 + bitmap_val (bitmap, 0, 2); + break; + case RRI_A: + num = 36 + bitmap_val (bitmap, 4, 1); + break; + case I8: + case I8_MOV32R: + case I8_MOVR32: + num = 38 + bitmap_val (bitmap, 8, 3); + break; + case RRR: + num = 46 + bitmap_val (bitmap, 0, 2); + break; + case RR: + { + int minor; + + minor = bitmap_val (bitmap, 0, 5); + if (minor != 0) + num = 50 + minor; + else + num = 90 + bitmap_val (bitmap, 5, 3); + } + break; + case I64: + case RI64: + num = 82 + bitmap_val (bitmap, 8, 3); + break; + default: + abort (); + } + + + if (!(features & FEATURE_IGEN)) + { + printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name, + bitmap); + printf (" {\n"); + } + else + { + printf ("\n"); + print_igen_insn_format (bitmap, + MIPS16_DECODE[loop].mark, /* format-name */ + -1, /* filter-flags -- -1 => MIPS16 */ + "", /* options */ + MIPS16_DECODE[loop].name); + printf ("*mips16:\n"); + printf ("{\n"); + printf (" unsigned32 instruction = instruction_0;\n"); + } + + build_mips16_operands (bitmap); + + printf (" {\n") ; + + /* build_instruction doesn't know about extend. */ + if (num != 30) + build_instruction (doisa, features, 1, &MIPS16_DECODE[loop]); + else + { + printf (" extendval = ext;\n"); + printf (" have_extendval = 1;\n"); + } + + printf (" }\n"); + if (!(features & FEATURE_IGEN)) + { + printf (" }\n") ; + printf (" break ;\n") ; + } + else + { + printf ("}\n"); + printf ("\n"); + } + } + + if (!(features & FEATURE_IGEN)) + { + printf ("default : /* Unrecognised instruction */\n") ; + printf (" SignalException(ReservedInstruction,instruction);\n") ; + printf (" break ;\n") ; + printf ("}\n}\n") ; + + printf("#endif /* simulator engine */\n"); + } + + return ; +} + +/* Output the code to execute an instruction, assuming the operands + have already been extracted. */ + +static void +build_instruction (doisa, features, mips16, insn) + int doisa; + unsigned int features; + int mips16; + const struct instruction *insn; +{ + int gprlen=((features & FEATURE_GP64) ? 64 : 32); + int proc64 = ((features & FEATURE_PROC32) ? 0 : -1); + char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int"); + + switch (insn->type) { + /* TODO: To make these easier to edit and maintain, they should + actually be provided as source macros (or inline functions) + OUTSIDE this main switch statement. The PPC simulator has a + neater scheme for describing the instruction sequences. */ + + case ADD: + case SUB: + { + char *signed_basetype = "unknown"; + char *unsigned_basetype = "unknown"; + + switch (GETDATASIZEINSN(insn)) { + case WORD : + signed_basetype = "signed int"; + unsigned_basetype = "unsigned int"; + break; + case DOUBLEWORD : + signed_basetype = "word64"; + unsigned_basetype = "uword64"; + break; + default : + fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn)); + exit(1); + } + + if ((insn->type) == ADD) { + printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype); + printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype); + if (insn->flags & OVERFLOW) { + printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n"); + printf(" SignalExceptionIntegerOverflow ();\n"); + printf(" else\n"); + } + if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD)) + printf(" GPR[destreg] = (%s)temp;\n",regtype); + else /* only sign-extend when placing 32bit result in 64bit processor */ + printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype); + } else { /* SUB */ + printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype, unsigned_basetype); + printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype); + if (insn->flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */ + printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n"); + printf(" SignalExceptionIntegerOverflow ();\n"); + printf(" else\n"); + } + /* UNSIGNED 32bit operations on a 64bit processor should + *STILL* be sign-extended. We have cheated in the + data-structure, by not marking it with UNSIGNED, and not + setting OVERFLOW. */ + if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD)) + printf(" GPR[destreg] = (%s)temp;\n",regtype); + else /* only sign-extend when placing 32bit result in 64bit processor */ + printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype); + } + } + break ; + + case MUL: + { + char* pipe = (insn->flags & PIPE1) ? "1" : ""; + + if (features & FEATURE_WARN_LOHI) { + printf(" CHECKHILO(\"Multiplication\");\n"); + } + printf(" {\n"); + if (GETDATASIZEINSN(insn) == DOUBLEWORD) { + printf(" uword64 mid;\n"); + printf(" uword64 midhi;\n"); + printf(" uword64 temp;\n"); + if ((insn->flags & UNSIGNED) == 0) + { + printf(" int sign = 0;\n"); + printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n"); + printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n"); + } + printf(" LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe); + printf(" HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe); + printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n"); + printf(" midhi = SET64HI(WORD64LO(mid));\n"); + printf(" temp = (LO%s + midhi);\n",pipe); + printf(" if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe); + printf(" HI%s += 1;\n",pipe); + printf(" HI%s += WORD64HI(mid);\n",pipe); + printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n"); + printf(" midhi = SET64HI(WORD64LO(mid));\n"); + printf(" LO%s = (temp + midhi);\n",pipe); + printf(" if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe,pipe); + printf(" HI%s += 1;\n",pipe); + printf(" HI%s += WORD64HI(mid);\n",pipe); + if ((insn->flags & UNSIGNED) == 0) + printf(" if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe,pipe,pipe,pipe,pipe); + } else { + if (insn->flags & UNSIGNED) + printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n"); + else + printf(" uword64 temp = ((word64) op1 * (word64) op2);\n"); + printf(" LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe,regtype); + printf(" HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe,regtype); + } + if (insn->flags & OP3) + { + printf(" if ( destreg != 0 )\n"); + printf(" GPR[destreg] = LO%s;\n",pipe); + } + printf(" }\n"); + break ; + } + case DIV: + { + int boolU = (insn->flags & UNSIGNED); + char* pipe = (insn->flags & PIPE1) ? "1" : ""; + + if (features & FEATURE_WARN_LOHI) { + printf(" CHECKHILO(\"Division\");\n"); + } + printf(" {\n"); + + if (GETDATASIZEINSN(insn) == DOUBLEWORD) { + printf(" %sword64 d1 = op1;\n", (boolU ? "u" : "")); + printf(" %sword64 d2 = op2;\n", (boolU ? "u" : "")); + printf(" if (d2 == 0)\n"); + printf(" {\n"); + printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe); + printf(" HI%s = 0;\n", pipe); + printf(" }\n"); + printf(" else if (d2 == -1 && d1 == SIGNED64 (0x8000000000000000))\n"); + printf(" {\n"); + printf(" LO%s = SIGNED64 (0x8000000000000000);\n", pipe); + printf(" HI%s = 0;\n", pipe); + printf(" }\n"); + printf(" else\n"); + printf(" {\n"); + printf(" LO%s = (d1 / d2);\n", pipe); + printf(" HI%s = (d1 %% d2);\n", pipe); + printf(" }\n"); + } else { + printf(" %sint d1 = op1;\n", (boolU ? "unsigned " : "")); + printf(" %sint d2 = op2;\n", (boolU ? "unsigned " : "")); + printf(" if (d2 == 0)\n"); + printf(" {\n"); + printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe); + printf(" HI%s = SIGNEXTEND(0,32);\n", pipe); + printf(" }\n"); + printf(" else if (d2 == -1 && d1 == 0x80000000)\n"); + printf(" {\n"); + printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe); + printf(" HI%s = SIGNEXTEND(0,32);\n", pipe); + printf(" }\n"); + printf(" else\n"); + printf(" {\n"); + printf(" LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe); + printf(" HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe); + printf(" }\n"); + } + printf(" }\n"); + } + break ; + + case SHIFT: + { + int datalen = GETDATASIZEINSN(insn); + int bits = ((datalen == WORD) ? 32 : 64); + char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64"); + + /* Check that the specified SHIFT is valid: */ + if ((datalen == BYTE) || (datalen == HALFWORD)) { + fprintf(stderr,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn->name); + exit(9); + } + if ((insn->flags & LEFT) && (insn->flags & RIGHT)) { + fprintf(stderr,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn->name); + exit(9); + } + if (!(insn->flags & LEFT) && !(insn->flags & RIGHT)) { + fprintf(stderr,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn->name); + exit(9); + } + if ((insn->flags & LOGICAL) && (insn->flags & ARITHMETIC)) { + fprintf(stderr,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn->name); + exit(9); + } + if (!(insn->flags & LOGICAL) && !(insn->flags & ARITHMETIC)) { + fprintf(stderr,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn->name); + exit(9); + } + if ((insn->flags & LEFT) && (insn->flags & ARITHMETIC)) { + fprintf(stderr,"Arithmetic LEFT shift \"%s\" specified\n",insn->name); + exit(9); + } + + /* Work around an MSC code generation bug by precomputing a value + * with the sign bit set. */ + if (insn->flags & ARITHMETIC) + printf(" %s highbit = (%s)1 << %d;\n", ltype, ltype, bits - 1); + + /* If register specified shift, then extract the relevant shift amount: */ + if (insn->flags & REG) + printf(" op1 &= 0x%02X;\n",(bits - 1)); + + /* If HI32 specified, then shift range is 32..63 */ + if (insn->flags & HI32) + printf(" op1 |= (1 << 5);\n"); + + /* We do not need to perform pre-masking with 0xFFFFFFFF when + dealing with 32bit shift lefts, since the sign-extension + code will replace any remaining hi-bits: */ + if (insn->flags & LEFT) + printf(" GPR[destreg] = ((uword64)op2 << op1);\n"); + else + printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : "")); + + /* For ARITHMETIC shifts, we must duplicate the sign-bit. We + don't do this if op1 is zero, since it is not needed and + since that would cause an undefined shift of the number of + bits in the type. */ + if (insn->flags & ARITHMETIC) + printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype,bits); + + /* Ensure WORD values are sign-extended into 64bit registers */ + if ((bits == 32) && (gprlen == 64)) + printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits); + } + break ; + + case MOVE: + if (insn->flags & (HI | LO)) { + char *regname = ((insn->flags & LO) ? "LO" : "HI"); + int pipe1 = (insn->flags & PIPE1); + if (insn->flags & LEFT) + printf(" GPR[destreg] = %s%s;\n",regname,(pipe1 ? "1" : "")); + else { + if (features & FEATURE_WARN_LOHI) { + printf(" if (%s%sACCESS != 0)\n",regname,(pipe1 ? "1" : "")); + printf(" sim_io_eprintf(sd,\"MT (move-to) over-writing %s register value\\n\");\n",regname); + } + printf(" %s%s = op1;\n",regname,(pipe1 ? "1" : "")); + } + if (features & FEATURE_WARN_LOHI) + printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname,(pipe1 ? "1" : "")); + } else + if (insn->flags & SHIFT16) + printf(" GPR[destreg] = (op2 << 16);\n"); + else { + /* perform conditional move */ + if (!(insn->flags & EQ)) { + fprintf(stderr,"Standard conditional %s does not have the equality flag\n",insn->name); + exit(8); + } + printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '=')); + printf(" GPR[destreg] = op1;\n"); + } + break ; + + case SYNC: + printf(" SyncOperation(op1);\n"); + break ; + + case SYSCALL: + printf(" SignalException(SystemCall,instruction);\n"); + break ; + + case BREAK: + printf(" SignalException(BreakPoint,instruction);\n"); + break ; + + case SDBBP: + printf(" SignalException(DebugBreakPoint,instruction);\n"); + break ; + + case TRAP: + { + int boolNOT = (insn->flags & NOT); + int boolEQ = (insn->flags & EQ); + int boolGT = (insn->flags & GT); + int boolLT = (insn->flags & LT); + int boolU = (insn->flags & UNSIGNED); + + if (boolGT && boolLT) { + fprintf(stderr,"GT and LT specified for \"%s\"\n",insn->name); + exit(8); + } + + if (boolNOT && (boolGT || boolLT)) { + fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",insn->name); + exit(8); + } + + printf(" if ((%sword64)op1 ",(boolU ? "u" : "")); + printf("%c%s",(boolNOT ? '!' : (boolLT ? '<' : (boolGT ? '>' : '='))),(boolEQ ? "=" : "")); + printf(" (%sword64)op2)\n",(boolU ? "u" : "")); + printf(" SignalException(Trap,instruction);\n"); + } + break ; + + case SET: + { + int boolU = (insn->flags & UNSIGNED); + + if (!(insn->flags & LT)) { + fprintf(stderr,"Set instruction without LT specified \"%s\"\n",insn->name); + exit(8); + } + + printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU ? "u" : ""),(boolU ? "u" : "")); + printf(" GPR[destreg] = 1;\n"); + printf(" else\n"); + printf(" GPR[destreg] = 0;\n"); + } + break ; + + case AND: + printf(" GPR[destreg] = (op1 & op2);\n"); + break ; + + case OR: + /* The default mips16 nop instruction does an or to register + zero; catch that case, so that we don't get useless warnings + from the simulator. */ + if (mips16) + printf (" if (destreg != 0)\n"); + printf(" GPR[destreg] = %s(op1 | op2);\n",((insn->flags & NOT) ? "~" : "")); + break ; + + case XOR: + printf(" GPR[destreg] = (op1 ^ op2);\n"); + break ; + + case DECODE: + printf(" DecodeCoproc(instruction);\n"); + break ; + + case CACHE: + /* 16-bit offset is sign-extended and added to the base register to make a virtual address */ + /* The virtual address is translated to a physical address using the TLB */ + /* The hint specifies a cache operation for that address */ + printf(" address_word vaddr = (op1 + offset);\n"); + printf(" address_word paddr;\n"); + printf(" int uncached;\n"); + /* NOTE: We are assuming that the AddressTranslation is a load: */ + printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n"); + printf(" CacheOp(hint,vaddr,paddr,instruction);\n"); + break; + + case MADD16: /* VR4100 specific multiply-add instructions */ + /* Some of this code is shared with the standard multiply + routines, so an effort should be made to merge where + possible. */ + if (features & FEATURE_WARN_LOHI) { + printf(" CHECKHILO(\"Multiply-Add\");\n"); + } + if (features & FEATURE_WARN_RESULT) { + /* Give user a warning if either op1 or op2 are not 16bit signed integers */ + printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n"); + printf(" sim_io_eprintf(sd,\"MADD16 operation with non-16bit operands\\n\");\n"); + } + printf(" {\n"); + printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */ + if (GETDATASIZEINSN(insn) == DOUBLEWORD) { + printf(" LO = LO + temp;\n"); + } else { /* WORD */ + printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n"); + printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype); + printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype); + } + printf(" }\n"); + break; + + case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */ + if (doisa < 4) { + printf(" if (CoProcPresent(3))\n"); + printf(" SignalExceptionCoProcessorUnusable ();\n"); + printf(" else\n"); + } + printf(" SignalException(ReservedInstruction,instruction);\n"); + break ; + + case JUMP: + if (insn->flags & LINK) { + if (!(insn->flags & REG)) + printf(" int destreg = 31;\n"); + printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n", + mips16 ? 2 : 4, mips16 ? 2 : 4); + } + + if (insn->flags & NOT) + printf(" op1 ^= 1;\n"); + + printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n"); + printf(" so we just truncate it to 32 bits here. */\n"); + printf(" op1 = WORD64LO(op1);\n"); + printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n"); + printf(" DSPC = op1;\n"); + if ((insn->flags & LINK) + && ! (insn->flags & REG)) + printf(" JALDELAYSLOT();\n"); + else + printf(" DELAYSLOT();\n"); + break ; + + case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */ + if (insn->flags & FP) { + if (doisa < 4) { + printf(" if (condition_code != 0)\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else {\n"); + } + /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */ + printf(" int condition = (%s == boolean);\n",((doisa < 4) ? "PREVCOC1()" : "GETFCC(condition_code)")); + } else { + if ((insn->flags & NOT) && !(insn->flags & EQ)) { + fprintf(stderr,"NOT specified when not EQ in \"%s\"\n",insn->name); + exit(7); + } + if ((insn->flags & NOT) && (insn->flags & (GT | LT))) { + fprintf(stderr,"NOT specified with GT or LT in \"%s\"\n",insn->name); + exit(7); + } + /* GT LT */ + if (insn->flags & GT) + printf(" int condition = (op1 >%s 0);\n",((insn->flags & EQ) ? "=" : "")); + else + if (insn->flags & LT) + printf(" int condition = (op1 <%s 0);\n",((insn->flags & EQ) ? "=" : "")); + else + if (insn->flags & EQ) + printf(" int condition = (op1 %c= op2);\n",((insn->flags & NOT) ? '!' : '=')); + } + + if (insn->flags & LINK) { + if (features & FEATURE_WARN_R31) { + printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS,OP_MASK_RS); + printf(" sim_io_eprintf(sd,\"Branch with link using r31 as source operand\\n\");\n"); + } + printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n"); + } + + if (! mips16) { + printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n"); + printf(" if (condition) {\n"); + printf(" DSPC = (PC + offset);\n"); + printf(" DELAYSLOT();\n"); + printf(" }\n"); + } else { + /* No delayed slots for mips16 branches. */ + printf(" if (condition)\n"); + printf(" PC = PC + offset;\n"); + } + if ((insn->flags & FP) && (doisa != 1)) { + printf(" else if (likely) {\n"); + printf(" NULLIFY();\n"); + printf(" }\n"); + } else if (insn->flags & LIKELY) { + printf(" else\n"); + printf(" NULLIFY();\n"); + } + if ((insn->flags & FP) && (doisa < 4)) + printf(" }\n"); + break ; + + case PREFETCH: /* The beginning is shared with normal load operations */ + case LOAD: + case STORE: + { + int isload = ((insn->type == LOAD) || (insn->type == PREFETCH)); + int datalen; + char *accesslength = ""; + + switch (GETDATASIZEINSN(insn)) { + case BYTE : + datalen = 1; + accesslength = "AccessLength_BYTE"; + break ; + + case HALFWORD : + datalen = 2; + accesslength = "AccessLength_HALFWORD"; + break ; + + case WORD : + datalen = 4; + accesslength = "AccessLength_WORD"; + break ; + + case DOUBLEWORD : + datalen = 8; + accesslength = "AccessLength_DOUBLEWORD"; + break ; + /* start-sanitize-r5900 */ + + case QUADWORD : + datalen = 16; + accesslength = "AccessLength_QUADWORD"; + break ; + /* end-sanitize-r5900 */ + } + + if (insn->flags & REG) + printf(" address_word vaddr = ((uword64)op1 + op2);\n"); + else + printf(" address_word vaddr = ((uword64)op1 + offset);\n"); + printf(" address_word paddr;\n"); + printf(" int uncached;\n"); + + /* The following check should only occur on normal (non-shifted) memory loads */ + if ((datalen != 1) && !(insn->flags & (LEFT | RIGHT))) { + printf(" if ((vaddr & %d) != 0)\n",(datalen - 1)); + printf(" SignalException%s();\n",(isload ? "AddressLoad" : "AddressStore")); + printf(" else\n") ; + } + + printf(" {\n"); + printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE")); + + if (insn->type == PREFETCH) + printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n"); + else { + printf(" {\n"); + printf(" uword64 memval = 0;\n"); + printf(" uword64 memval1 = 0;\n"); + + if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) { + fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name); + exit(6); + } + + if (insn->flags & (LEFT | RIGHT)) { + if ((insn->flags & LEFT) && (insn->flags & RIGHT)) { + fprintf(stderr,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn->name); + exit(4); + } + + switch (datalen) { + case 8: + if (!(features & FEATURE_IGEN)) + { + if (!proc64) { + fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name); + exit(4); + } + } + /* fall through to... */ + case 4: + { + printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3)); + printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n"); + printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n"); + printf(" int byte;\n"); + printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n"); + printf(" byte = ((vaddr & mask) ^ bigend);\n"); + printf(" if (%sBigEndianMem)\n",((insn->flags & LEFT) ? "!" : "")); + printf(" paddr &= ~mask;\n"); + + if (isload) { + if (insn->flags & LEFT) + { + printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n"); + } + else + { + printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1)); + } + } + + if (insn->flags & LEFT) { + if (isload) { + /* For WORD transfers work out if the value will + be in the top or bottom of the DOUBLEWORD + returned: */ +#if 1 + build_endian_shift(proc64,datalen,2,s_right,32); +#else + if (proc64 && (datalen == 4)) { + printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n"); + printf(" memval >>= 32;\n"); + printf(" }\n"); + } +#endif + printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen - 1),(datalen - 1)); + if (proc64 && (datalen == 4)) + printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n"); + } else { /* store */ + printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen - 1)); +#if 1 + build_endian_shift(proc64,datalen,2,s_left,32); +#else + /* TODO: This is duplicated in the LOAD code + above - and the RIGHT LOAD and STORE code + below. It should be merged if possible. */ + if (proc64 && (datalen == 4)) { + printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n"); + printf(" memval <<= 32;\n"); + printf(" }\n"); + } +#endif + printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n"); + } + } else { /* RIGHT */ + if (isload) { +#if 1 + build_endian_shift(proc64,datalen,2,s_right,32); +#else + if (proc64 && (datalen == 4)) { + printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n"); + printf(" memval >>= 32;\n"); + printf(" }\n"); + } +#endif + printf(" {\n"); + printf(" uword64 srcmask;\n"); + /* All of this extra code is just a bodge + required because some hosts don't allow + ((v) << 64). The SPARC just leaves the (v) + value un-touched. */ + printf(" if (byte == 0)\n"); + printf(" srcmask = 0;\n"); + printf(" else\n"); + printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen); + printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n"); + printf(" }\n"); + if (proc64 && (datalen == 4)) + printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n"); + } else { /* store */ + printf(" memval = ((uword64) op2 << (byte * 8));\n"); + build_endian_shift(proc64,datalen,2,s_left,32); + printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength); + } + } + } + break; + + default: + fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn->name); + exit(6); + } + } else { /* normal memory transfer */ + if (!(features & FEATURE_IGEN)) + { + if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) { + fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name); + exit(4); + /* TODO: The R4000 documentation states that a LWU + instruction executed when in a 32bit processor mode + should cause a ReservedInstruction exception. This + will mean adding a run-time check into the code + sequence. */ + } + } + + if (isload) { +#if 1 /* see the comments attached to LOADDRMASK above */ + printf(" uword64 mask = 0x7;\n"); +#else + printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3)); +#endif + printf(" unsigned int shift = %d;\n",(datalen >> 1)); + printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n"); + printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n"); + printf(" unsigned int byte UNUSED;\n"); + +/* TODO: This should really also check for 32bit world performing 32bit access */ + if (datalen < 8) + /* not for DOUBLEWORD */ + /* start-sanitize-r5900 */ + /* not for QUADWORD */ + /* end-sanitize-r5900 */ + printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n"); + + printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength); + + /* The following will only make sense if the + "LoadMemory" above returns a DOUBLEWORD entity */ + if (datalen < 8) { + /* not for DOUBLEWORD */ + /* start-sanitize-r5900 */ + /* not for QUADWORD */ + /* end-sanitize-r5900 */ + int valmask; + switch (datalen) { + case 1: + valmask = 0xFF; + break; + + case 2: + valmask = 0xFFFF; + break; + + case 4: + valmask = 0xFFFFFFFF; + break; + + default: + fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,insn->name); + exit(4); + } + printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n"); + /* NOTE: The R4000 user manual has the COP_LW + occuring in the same cycle as the rest of the + instruction, yet the MIPS IV shows the operation + happening on the next cycle. To keep the simulator + simple, this code follows the R4000 + manual. Experimentation with a silicon + implementation will be needed to ascertain the + correct operation. */ + if (insn->flags & COPROC) + printf(" COP_LW(%s,destreg,(unsigned int)", + ((insn->flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)")); + else + printf(" GPR[destreg] = ("); + + if (insn->flags & SIGNEXTEND) + printf("SIGNEXTEND("); + printf("((memval >> (8 * byte)) & 0x%08X)",valmask); + if (insn->flags & SIGNEXTEND) + printf(",%d)",(datalen * 8)); + printf(");\n"); + } else { + if (insn->flags & COPROC) + printf(" COP_LD(%s,destreg,memval);;\n", + ((insn->flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)")); + else + { + printf(" GPR[destreg] = memval;\n"); + if (datalen > 8) + printf(" GPR1[destreg] = memval1;\n"); + } + } + } else { /* store operation */ + if ((datalen == 1) || (datalen == 2)) { + /* SH and SB */ +#if 1 /* see the comments attached to LOADDRMASK above */ + printf(" uword64 mask = 0x7;\n"); +#else + printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3)); +#endif + printf(" unsigned int shift = %d;\n",(datalen >> 1)); + printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n"); + printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n"); + printf(" unsigned int byte;\n"); + + printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n"); + printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n"); + printf(" memval = ((uword64) op2 << (8 * byte));\n"); + } else + if (datalen == 4) { /* SC and SW */ +#if 1 /* see the comments attached to LOADDRMASK above */ + printf(" uword64 mask = 0x7;\n"); +#else + printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3)); +#endif + printf(" unsigned int byte;\n"); + printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n"); + printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n"); + if (insn->flags & COPROC) + printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n", + ((insn->flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)"), + ((insn->flags & FP) ? "fs" : "destreg")); + else + printf(" memval = ((uword64) op2 << (8 * byte));\n"); + } else if (datalen <= 8) { /* SD and SCD */ + if (! (features & FEATURE_IGEN)) + { + if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) { + fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name); + exit(4); + } + } + if (insn->flags & COPROC) + printf(" memval = (uword64)COP_SD(%s,%s);\n", + ((insn->flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)"), + ((insn->flags & FP) ? "fs" : "destreg")); + else + printf(" memval = op2;\n"); + } else { /* wider than 8 */ + if (insn->flags & COPROC) { + fprintf(stderr,"COPROC not available for 128 bit operations \"%s\"\n",insn->name); + exit(4); + } + printf(" memval = rt_reg;\n"); + printf(" memval1 = rt_reg1;\n"); + } + + if (insn->flags & ATOMIC) + printf(" if (LLBIT)\n"); + + printf(" {\n"); + printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength); + printf(" }\n"); + } + + if (insn->flags & ATOMIC) { + if ((datalen != 4) && (datalen != 8)) { + fprintf(stderr,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn->name); + exit(4); + } else + if (isload) + printf(" LLBIT = 1;\n"); + else { + /* The documentation states that: + + SC *WILL* fail if coherent store into the same + block occurs, or if an exception occurs between + the LL and SC instructions. + + SC *MAY* fail if a load, store or prefetch is + executed on the processor (VR4300 doesn't seem + to), or if the instructions between the LL and + SC are not in a 2048byte contiguous VM range. + + SC *MUST* have been preceded by an LL + (i.e. LLBIT will be set), and it must use the + same Vaddr, Paddr and cache-coherence algorithm + as the LL (which means we should store this + information from the load-conditional). + */ + printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT); + } + } + } + printf(" }\n"); + } + printf(" }\n"); + } + break ; + + case FPPREFX: + /* This code could be merged with the PREFIX generation above: */ + printf(" address_word vaddr = ((uword64)op1 + (uword64)op2);\n"); + printf(" address_word paddr;\n"); + printf(" int uncached;\n"); + printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n"); + printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n"); + break ; + + case FPMOVEC: + if (insn->flags & CONTROL) { + /* The following "magic" of interpreting the FP + control-register number would not be needed if we were not + trying to match our internal register numbers with those + used by GDB. */ + printf(" if (to) {\n"); + if (doisa < 4) { + printf(" if (fs == 0) {\n"); + printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n"); + printf(" } else if (fs == 31) {\n"); + printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n"); + printf(" } /* else NOP */\n"); + printf(" PENDING_FILL(COCIDX,0); /* special case */\n"); + } else { + printf(" if (fs == 0) {\n"); + printf(" FCR0 = WORD64LO(GPR[ft]);\n"); + printf(" } else if (fs == 31) {\n"); + printf(" FCR31 = WORD64LO(GPR[ft]);\n"); + printf(" } /* else NOP */\n"); + printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n"); + } + printf(" } else { /* control from */\n"); + if (doisa < 4) { + printf(" if (fs == 0) {\n"); + printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n"); + printf(" } else if (fs == 31) {\n"); + printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n"); + printf(" } /* else NOP */\n"); + } else { + printf(" if (fs == 0) {\n"); + printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n"); + printf(" } else if (fs == 31) {\n"); + printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n"); + printf(" } /* else NOP */\n"); + } + printf(" }\n"); + } else { + printf(" if (to) {\n"); + if (GETDATASIZEINSN(insn) == WORD) { + if (doisa < 4) { + printf(" if (SizeFGR() == 64) {\n"); + printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n"); + printf(" } else { \n"); + printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n"); + printf(" }\n"); + } else { + printf(" if (SizeFGR() == 64)\n"); + printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n"); + printf(" else\n"); + printf(" FGR[fs] = WORD64LO(GPR[ft]);\n"); + printf(" FPR_STATE[fs] = fmt_uninterpreted;\n"); + } + } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) { + if (doisa < 4) { + printf(" if (SizeFGR() == 64) {\n"); + printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n"); + printf(" } else\n"); + printf(" if ((fs & 0x1) == 0)\n"); + printf(" {\n"); + printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n"); + printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n"); + printf(" }\n"); + if (features & FEATURE_WARN_RESULT) { + printf(" else\n"); + printf(" UndefinedResult();\n"); + } + } else { + printf(" if (SizeFGR() == 64) {\n"); + printf(" FGR[fs] = GPR[ft];\n"); + printf(" FPR_STATE[fs] = fmt_uninterpreted;\n"); + printf(" } else\n"); + printf(" if ((fs & 0x1) == 0)\n"); + printf(" {\n"); + printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n"); + printf(" FGR[fs] = WORD64LO(GPR[ft]);\n"); + printf(" FPR_STATE[fs + 1] = fmt_uninterpreted;\n"); + printf(" FPR_STATE[fs] = fmt_uninterpreted;\n"); + printf(" }\n"); + if (features & FEATURE_WARN_RESULT) { + printf(" else\n"); + printf(" UndefinedResult();\n"); + } + } + } else { + fprintf(stderr,"Invalid data width specified in FPU Move operation\n"); + exit(1); + } + printf(" } else {\n"); + if (GETDATASIZEINSN(insn) == WORD) { + if (doisa < 4) /* write-back occurs in next cycle */ + printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n"); + else /* in this cycle */ + printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n"); + } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) { + if (doisa < 4) { + printf(" if (SizeFGR() == 64) {\n"); + printf(" PENDING_FILL(ft,FGR[fs]);\n"); + printf(" } else\n"); + printf(" if ((fs & 0x1) == 0) {\n"); + printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n"); + printf(" } else {\n"); + printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n"); + if (features & FEATURE_WARN_RESULT) + printf(" UndefinedResult();\n"); + printf(" }\n"); + } else { + printf(" if (SizeFGR() == 64)\n"); + printf(" GPR[ft] = FGR[fs];\n"); + printf(" else\n"); + printf(" if ((fs & 0x1) == 0)\n"); + printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n"); + printf(" else {\n"); + printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n"); + if (features & FEATURE_WARN_RESULT) + printf(" UndefinedResult();\n"); + printf(" }\n"); + } + } else { + fprintf(stderr,"Invalid data width specified in FPU Move operation\n"); + exit(1); + } + printf(" }\n"); + } + break ; + + case FPMOVE: + if (insn->flags & CONDITIONAL) { + if (insn->flags & INTEGER) { /* moving GPR - testing FGR */ + printf(" if (GETFCC(condition_code) == boolean)\n"); + printf(" GPR[destreg] = op1;\n"); + } else { + if (insn->flags & EQ) /* moving FGR - testing GPR */ + printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '=')); + else + printf(" if (GETFCC(condition_code) == boolean)\n"); + printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n"); + } + } else { /* simple MOVE */ + printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n"); + } + break ; + + case FPNEG: + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n"); + break ; + + case FPABS: + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n"); + break ; + + case FPDIV: + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n"); + break ; + + case FPMUL: + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n"); + break ; + + case FPRECIP: + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n"); + break ; + + case FPSQRT: + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)%s));\n", + ((insn->flags & RECIP) ? "Recip" : ""), + ((insn->flags & RECIP) ? ",format" : "")); + break ; + + case FPCEIL: + case FPFLOOR: + case FPTRUNC: + case FPROUND: + { + char *op = ""; + char *type = ""; + + switch (insn->type) { + case FPCEIL: + op = "FP_RM_TOPINF"; + break; + case FPFLOOR: + op = "FP_RM_TOMINF"; + break; + case FPTRUNC: + op = "FP_RM_TOZERO"; + break; + case FPROUND: + op = "FP_RM_NEAREST"; + break; + default: + fprintf(stderr,"Error: Handled missing for FP reason code %d\n",insn->type); + exit(1); + } + + switch (GETDATASIZEINSN(insn)) { + case WORD : + type = "fmt_word"; + break; + case DOUBLEWORD : + type = "fmt_long"; + break; + default: + fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op); + exit(1); + } + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type); + } + break ; + + case FPCONVERT: + { + char *type = ""; + switch (GETDATASIZEINSN(insn)) { + case SINGLE: + type = "fmt_single"; + break; + case DOUBLE: + type = "fmt_double"; + break; + case WORD: + type = "fmt_word"; + break; + case DOUBLEWORD: + type = "fmt_long"; + break; + default : + fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn)); + exit(1); + } + + /* Not all combinations of conversion are valid at the + moment: When converting to a fixed-point format, only + floating-point sources are allowed. */ + printf(" if ((format == %s) | %s)\n",type,((insn->flags & FIXED) ? "((format == fmt_long) || (format == fmt_word))": "0")); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type); + } + break ; + + case FPSUB: + if (insn->flags & MULTIPLY) { + char *type = ""; + switch (GETDATASIZEINSN(insn)) { + case SINGLE: + type = "fmt_single"; + break; + case DOUBLE: + type = "fmt_double"; + break; + default: + fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn)); + exit(1); + } + if (insn->flags & NOT) + printf (" StoreFPR(destreg,%s,Negate(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n", + type, type, type, type, type, type, type); + else + printf (" StoreFPR(destreg,%s,Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n", + type, type, type, type, type, type); + } else { + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n"); + } + break ; + + case FPADD: + if (insn->flags & MULTIPLY) { + char *type = ""; + switch (GETDATASIZEINSN(insn)) { + case SINGLE: + type = "fmt_single"; + break; + case DOUBLE: + type = "fmt_double"; + break; + default: + fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn)); + exit(1); + } + if (insn->flags & NOT) + printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n", + type, type, type, type, type, type, type); + else + printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n", + type, type, type, type, type, type); + } else { + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf(" else\n"); + printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n"); + } + break ; + + case FPCOMPARE: + /* For the MIPS I,II or III there *MUST* be at least one + instruction between the compare that sets a condition code + and the branch that tests it. NOTE: However the hardware + does not detect this condition. */ + /* Explicitly limit the operation to S and D formats: */ + printf(" if ((format != fmt_single) && (format != fmt_double))\n"); + printf(" SignalException(ReservedInstruction,instruction);\n") ; + printf(" else {\n"); + if (doisa < 4) { + printf(" if (condition_code != 0)\n"); + printf(" SignalException(ReservedInstruction,instruction);\n") ; + printf(" else\n"); + } + printf(" {\n"); + printf(" int ignore = 0;\n"); + printf(" int less = 0;\n"); + printf(" int equal = 0;\n"); + printf(" int unordered = 1;\n"); + printf(" uword64 ofs = ValueFPR(fs,format);\n"); + printf(" uword64 oft = ValueFPR(ft,format);\n"); + printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n"); + printf(" if (FCSR & FP_ENABLE(IO)) {\n"); + printf(" FCSR |= FP_CAUSE(IO);\n"); + printf(" SignalExceptionFPE ();\n"); + printf(" ignore = 1;\n"); + printf(" }\n"); + printf(" } else {\n"); + printf(" less = Less(ofs,oft,format);\n"); + printf(" equal = Equal(ofs,oft,format);\n"); + printf(" unordered = 0;\n"); + printf(" }\n"); + printf(" if (!ignore) {\n"); + printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n"); + printf(" SETFCC(condition_code,condition);\n"); + printf(" }\n"); + printf(" }\n"); + printf(" }\n"); + break ; + + case MADD: + { + char* pipeline = (insn->flags & PIPE1) ? "1" : ""; + int notsigned = (insn->flags & UNSIGNED); + char* prodtype = notsigned ? "uword64" : "word64"; + + printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n", + prodtype, prodtype, pipeline, pipeline, + prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32"), + prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32") + ); + printf("LO%s = SIGNEXTEND(prod,32);\n", pipeline ); + printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline ); + printf("if( destreg != 0 ) GPR[destreg] = LO%s;\n", pipeline ); + break; + } + +/* start-sanitize-r5900 */ + case MxSA: + { + if (insn->flags & TO) + printf("SA = op1;\n"); + else + printf("GPR[destreg] = SA;\n"); + break; + } + + case MTSAB: + printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n"); + break; + + case MTSAH: + printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n"); + break; + + case QFSRV: + printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */ + printf("if (SA %% 8)\n"); + printf(" SignalException(ReservedInstruction,instruction);\n"); + printf("else\n"); + printf(" {\n"); + printf(" int i;\n"); + printf(" for(i=0;i<(16-bytes);i++)\n"); + printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n"); + printf(" for(;i<16;i++)\n"); + printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n"); + printf(" }\n"); + break; + + case PADD: + { + char* op = (insn->flags & SUBTRACT) ? "-" : "+"; + char* name = name_for_data_len( insn ); + char* letter = letter_for_data_len( insn ); + + char* tmptype; + char* maximum; + char* maxsat; + char* minimum; + char* signletter; + + if ( insn->flags & UNSIGNED ) + { + tmptype = type_for_data_len( insn, 0/*unsigned*/ ); + signletter = "U"; + maximum = umax_for_data_len( insn ); + maxsat = (insn->flags & SUBTRACT) ? "0" : maximum; + minimum = 0; + } + else if ( insn->flags & SATURATE ) + { + tmptype = type_for_data_len( insn, 1/*signed*/ ); + signletter = "S"; + maximum = max_for_data_len( insn ); + maxsat = maximum; + minimum = min_for_data_len( insn ); + } + else + { + tmptype = type_for_data_len( insn, 1/*signed*/ ); + signletter = "S"; + maximum = 0; + maxsat = 0; + minimum = 0; + } + + printf(" int i;\n"); + printf(" for (i=0; i < %sS_IN_MMI_REGS; i++)\n", name ); + printf(" {\n"); + printf(" %s s = RS_%s%s(i);\n", tmptype, signletter, letter); + printf(" %s t = RT_%s%s(i);\n", tmptype, signletter, letter); + printf(" %s r = s %s t;\n", tmptype, op); + if ( maximum ) + { + printf(" if (r > %s)\n", maximum); + printf(" GPR_%s%s(destreg,i) = %s;\n", signletter, letter, maxsat ); + if ( minimum ) + { + printf(" else if (r < %s)\n", minimum); + printf(" GPR_%s%s(destreg,i) = %s;\n", signletter, letter, minimum ); + } + printf(" else\n"); + printf(" "); + } + printf(" GPR_%s%s(destreg,i) = r;\n", signletter, letter ); + printf(" }\n"); + break; + } + + case PMULTH: + { + char* op; + if ( insn->flags & SUBTRACT ) + op = "-"; + else if ( insn->flags & ADDITION ) + op = "+"; + else + op = ""; + + printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op); + printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op); + printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op); + printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op); + printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op); + printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op); + printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op); + printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op); + break; + } + + case PMULTW: + { + char* op; + char* sign = (insn->flags & UNSIGNED) ? "U" : "S"; + char* prodtype = (insn->flags & UNSIGNED) ? "unsigned64" : "signed64"; + char* constructor = (insn->flags & UNSIGNED) ? "UWORD64" : "WORD64"; + + if ( insn->flags & SUBTRACT ) + { + op = "-"; + printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype, constructor ); + printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype, constructor ); + } + else if ( insn->flags & ADDITION ) + { + op = "+"; + printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype, constructor ); + printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype, constructor ); + } + else + { + op = ""; + printf(" %s sum0 = 0;\n", prodtype ); + printf(" %s sum1 = 0;\n", prodtype ); + } + + printf(" %s prod0 = (%s)RS_%sW(0) * (%s)RT_%sW(0);\n", prodtype, prodtype, sign, prodtype, sign ); + printf(" %s prod1 = (%s)RS_%sW(2) * (%s)RT_%sW(2);\n", prodtype, prodtype, sign, prodtype, sign ); + + printf(" sum0 %s= prod0;\n", op ); + printf(" sum1 %s= prod1;\n", op ); + + printf(" GPR_%sD(destreg,0) = sum0;\n", sign ); + printf(" GPR_%sD(destreg,1) = sum1;\n", sign ); + + printf(" LO = SIGNEXTEND( sum0, 32 );\n"); + printf(" HI = SIGNEXTEND( WORD64HI(sum0), 32 );\n"); + printf(" LO1 = SIGNEXTEND( sum1, 32 );\n"); + printf(" HI1 = SIGNEXTEND( WORD64HI(sum1), 32 );\n"); + break; + } + + case PDIVW: + { + char* sign = (insn->flags & UNSIGNED) ? "U" : "S"; + int i; + for (i = 0; i < 2; i ++) + { + char hi = (i == 0 ? ' ' : '1'); + int d = i * 2; + if (! (insn->flags & UNSIGNED)) + { + printf("if (RT_SW(%d) == -1)\n", d ); + printf(" {\n"); + printf(" LO%c = -RS_%sW(%d);\n", hi, sign, d ); + printf(" HI%c = 0;\n", hi ); + printf(" }\nelse "); + }; + printf("if (RT_UW(%d) != 0)\n", d ); + printf(" {\n"); + printf(" LO%c = (signed32)(RS_%sW(%d) / RT_%sW(%d));\n", hi, sign, d, sign, d ); + printf(" HI%c = (signed32)(RS_%sW(%d) %% RT_%sW(%d));\n", hi, sign, d, sign, d ); + printf(" }\n"); + } + break; + } + + case PDIVBW: + printf("signed32 devisor = RT_SH(0);\n"); + printf("if (devisor == -1)\n"); + printf(" {\n"); + printf(" LO_SW(0) = -RS_SW(0);\n"); + printf(" HI_SW(0) = 0;\n"); + printf(" LO_SW(1) = -RS_SW(1);\n"); + printf(" HI_SW(1) = 0;\n"); + printf(" LO_SW(2) = -RS_SW(2);\n"); + printf(" HI_SW(2) = 0;\n"); + printf(" LO_SW(3) = -RS_SW(3);\n"); + printf(" HI_SW(3) = 0;\n"); + printf(" }\n"); + printf("else if (devisor != 0)\n"); + printf(" {\n"); + printf(" LO_SW(0) = RS_SW(0) / devisor;\n"); + printf(" HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n"); + printf(" LO_SW(1) = RS_SW(1) / devisor;\n"); + printf(" HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n"); + printf(" LO_SW(2) = RS_SW(2) / devisor;\n"); + printf(" HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n"); + printf(" LO_SW(3) = RS_SW(3) / devisor;\n"); + printf(" HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n"); + printf(" }\n"); + break; + + case PADSBH: + printf("int i;\n"); + printf("for(i=0;iflags & SUBTRACT) ? "-" : "+"; + printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op ); + printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op ); + printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op ); + printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op ); + } + break; + + case PSHIFT: + { + char* name = name_for_data_len( insn ); + char* letter = letter_for_data_len( insn ); + char* bits = bits_for_data_len( insn ); + char* shift = (insn->flags & RIGHT) ? ">>" : "<<"; + char* sign = (insn->flags & ARITHMETIC) ? "S" : "U"; + + printf("int shift_by = op1 & (%s-1);\n", bits ); + printf("int i;\n"); + printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name ); + printf(" GPR_%s%s(destreg,i) = ", sign, letter ); + if ( insn->flags & ARITHMETIC ) + printf("SIGNEXTEND( "); + printf("(RT_%s%s(i) %s shift_by)", sign, letter, shift ); + if ( insn->flags & ARITHMETIC ) + printf(", (%s-shift_by) )", bits ); + printf(";\n"); + break; + } + + case PSLLVW: + printf("int s0 = (RS_UB(0) & 0x1F);\n"); + printf("int s1 = (RS_UB(8) & 0x1F);\n"); + printf("signed32 temp0 = RT_UW(0) << s0;\n"); + printf("signed32 temp1 = RT_UW(2) << s1;\n"); + printf("GPR_SD(destreg,0) = (signed64)temp0;\n"); + printf("GPR_SD(destreg,1) = (signed64)temp1;\n"); + break; + + case PSRLVW: + printf("GPR_UD(destreg,0) = SIGNEXTEND ( RT_UW(0) >> (RS_UB(0) & 0x1F), 31);\n"); + printf("GPR_UD(destreg,1) = SIGNEXTEND ( RT_UW(2) >> (RS_UB(8) & 0x1F), 31);\n"); + break; + + case PSRAVW: + printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n"); + printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n"); + break; + + case POP: + { + char* op1; + char* op2; + + if ( GET_OP_FROM_INSN(insn) == POP_AND ) + { + op1 = "&"; + op2 = ""; + } + else if ( GET_OP_FROM_INSN(insn) == POP_OR ) + { + op1 = "|"; + op2 = ""; + } + else if ( GET_OP_FROM_INSN(insn) == POP_NOR ) + { + op1 = "|"; + op2 = "~"; + } + else if ( GET_OP_FROM_INSN(insn) == POP_XOR ) + { + op1 = "^"; + op2 = ""; + } + + printf("int i;\n"); + printf("for(i=0;iflags & GT) ? ">" : "=="; + + printf("int i;\n"); + printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name ); + printf(" {\n"); + printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n", + letter, op, letter, letter, maximum ); + printf(" else GPR_S%s(destreg,i) = 0;\n", letter ); + printf(" }\n"); + break; + } + + case PMAXMIN: + { + char* name = name_for_data_len( insn ); + char* letter = letter_for_data_len( insn ); + char* op = (insn->flags & GT) ? ">" : "<"; + + printf("int i;\n"); + printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name ); + printf(" {\n"); + printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n", + letter, op, letter, letter, letter ); + printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter ); + printf(" }\n"); + break; + } + + case PABS: + { + char* name = name_for_data_len( insn ); + char* letter = letter_for_data_len( insn ); + char* min = min_for_data_len( insn ); + char* max = max_for_data_len( insn ); + + printf("int i;\n"); + printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name ); + printf(" {\n"); + printf(" if (RT_S%s(i) >= 0)\n", letter ); + printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter ); + printf(" else if (RT_S%s(i) == %s)\n", letter, min ); + printf(" GPR_S%s(destreg,i) = %s;\n", letter, max ); + printf(" else\n"); + printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter, letter ); + printf(" }\n"); + break; + } + + case PCPYH: + printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n"); + printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n"); + break; + + case PCPYLD: + printf("GPR_UD(destreg,0) = RT_UD(0);\n"); + printf("GPR_UD(destreg,1) = RS_UD(0);\n"); + break; + + case PCPYUD: + printf("GPR_UD(destreg,0) = RS_UD(1);\n"); + printf("GPR_UD(destreg,1) = RT_UD(1);\n"); + break; + + case PEXCH: + printf("GPR_UH(destreg,0) = RT_UH(0);\n"); + printf("GPR_UH(destreg,1) = RT_UH(2);\n"); + printf("GPR_UH(destreg,2) = RT_UH(1);\n"); + printf("GPR_UH(destreg,3) = RT_UH(3);\n"); + printf("GPR_UH(destreg,4) = RT_UH(4);\n"); + printf("GPR_UH(destreg,5) = RT_UH(6);\n"); + printf("GPR_UH(destreg,6) = RT_UH(5);\n"); + printf("GPR_UH(destreg,7) = RT_UH(7);\n"); + break; + + case PEXCW: + printf("GPR_UW(destreg,0) = RT_UW(0);\n"); + printf("GPR_UW(destreg,1) = RT_UW(2);\n"); + printf("GPR_UW(destreg,2) = RT_UW(1);\n"); + printf("GPR_UW(destreg,3) = RT_UW(3);\n"); + break; + + case PEXOH: + printf("GPR_UH(destreg,0) = RT_UH(2);\n"); + printf("GPR_UH(destreg,1) = RT_UH(1);\n"); + printf("GPR_UH(destreg,2) = RT_UH(0);\n"); + printf("GPR_UH(destreg,3) = RT_UH(3);\n"); + printf("GPR_UH(destreg,4) = RT_UH(6);\n"); + printf("GPR_UH(destreg,5) = RT_UH(5);\n"); + printf("GPR_UH(destreg,6) = RT_UH(4);\n"); + printf("GPR_UH(destreg,7) = RT_UH(7);\n"); + break; + + case PEXOW: + printf("GPR_UW(destreg,0) = RT_UW(2);\n"); + printf("GPR_UW(destreg,1) = RT_UW(1);\n"); + printf("GPR_UW(destreg,2) = RT_UW(0);\n"); + printf("GPR_UW(destreg,3) = RT_UW(3);\n"); + break; + + case PEXTLB: + printf("GPR_UB(destreg,0) = RT_UB(0);\n"); + printf("GPR_UB(destreg,1) = RS_UB(0);\n"); + printf("GPR_UB(destreg,2) = RT_UB(1);\n"); + printf("GPR_UB(destreg,3) = RS_UB(1);\n"); + printf("GPR_UB(destreg,4) = RT_UB(2);\n"); + printf("GPR_UB(destreg,5) = RS_UB(2);\n"); + printf("GPR_UB(destreg,6) = RT_UB(3);\n"); + printf("GPR_UB(destreg,7) = RS_UB(3);\n"); + printf("GPR_UB(destreg,8) = RT_UB(4);\n"); + printf("GPR_UB(destreg,9) = RS_UB(4);\n"); + printf("GPR_UB(destreg,10) = RT_UB(5);\n"); + printf("GPR_UB(destreg,11) = RS_UB(5);\n"); + printf("GPR_UB(destreg,12) = RT_UB(6);\n"); + printf("GPR_UB(destreg,13) = RS_UB(6);\n"); + printf("GPR_UB(destreg,14) = RT_UB(7);\n"); + printf("GPR_UB(destreg,15) = RS_UB(7);\n"); + break; + + case PEXTLH: + printf("GPR_UH(destreg,0) = RT_UH(0);\n"); + printf("GPR_UH(destreg,1) = RS_UH(0);\n"); + printf("GPR_UH(destreg,2) = RT_UH(1);\n"); + printf("GPR_UH(destreg,3) = RS_UH(1);\n"); + printf("GPR_UH(destreg,4) = RT_UH(2);\n"); + printf("GPR_UH(destreg,5) = RS_UH(2);\n"); + printf("GPR_UH(destreg,6) = RT_UH(3);\n"); + printf("GPR_UH(destreg,7) = RS_UH(3);\n"); + break; + + case PEXTLW: + printf("GPR_UW(destreg,0) = RT_UW(0);\n"); + printf("GPR_UW(destreg,1) = RS_UW(0);\n"); + printf("GPR_UW(destreg,2) = RT_UW(1);\n"); + printf("GPR_UW(destreg,3) = RS_UW(1);\n"); + break; + + case PEXTUB: + printf("GPR_UB(destreg,0) = RT_UB(8);\n"); + printf("GPR_UB(destreg,1) = RS_UB(8);\n"); + printf("GPR_UB(destreg,2) = RT_UB(9);\n"); + printf("GPR_UB(destreg,3) = RS_UB(9);\n"); + printf("GPR_UB(destreg,4) = RT_UB(10);\n"); + printf("GPR_UB(destreg,5) = RS_UB(10);\n"); + printf("GPR_UB(destreg,6) = RT_UB(11);\n"); + printf("GPR_UB(destreg,7) = RS_UB(11);\n"); + printf("GPR_UB(destreg,8) = RT_UB(12);\n"); + printf("GPR_UB(destreg,9) = RS_UB(12);\n"); + printf("GPR_UB(destreg,10) = RT_UB(13);\n"); + printf("GPR_UB(destreg,11) = RS_UB(13);\n"); + printf("GPR_UB(destreg,12) = RT_UB(14);\n"); + printf("GPR_UB(destreg,13) = RS_UB(14);\n"); + printf("GPR_UB(destreg,14) = RT_UB(15);\n"); + printf("GPR_UB(destreg,15) = RS_UB(15);\n"); + break; + + case PEXTUH: + printf("GPR_UH(destreg,0) = RT_UH(4);\n"); + printf("GPR_UH(destreg,1) = RS_UH(4);\n"); + printf("GPR_UH(destreg,2) = RT_UH(5);\n"); + printf("GPR_UH(destreg,3) = RS_UH(5);\n"); + printf("GPR_UH(destreg,4) = RT_UH(6);\n"); + printf("GPR_UH(destreg,5) = RS_UH(6);\n"); + printf("GPR_UH(destreg,6) = RT_UH(7);\n"); + printf("GPR_UH(destreg,7) = RS_UH(7);\n"); + break; + + case PEXTUW: + printf("GPR_UW(destreg,0) = RT_UW(2);\n"); + printf("GPR_UW(destreg,1) = RS_UW(2);\n"); + printf("GPR_UW(destreg,2) = RT_UW(3);\n"); + printf("GPR_UW(destreg,3) = RS_UW(3);\n"); + break; + + case PPACB: + printf("GPR_UB(destreg,0) = RT_UB(0);\n"); + printf("GPR_UB(destreg,1) = RT_UB(2);\n"); + printf("GPR_UB(destreg,2) = RT_UB(4);\n"); + printf("GPR_UB(destreg,3) = RT_UB(6);\n"); + printf("GPR_UB(destreg,4) = RT_UB(8);\n"); + printf("GPR_UB(destreg,5) = RT_UB(10);\n"); + printf("GPR_UB(destreg,6) = RT_UB(12);\n"); + printf("GPR_UB(destreg,7) = RT_UB(14);\n"); + printf("GPR_UB(destreg,8) = RS_UB(0);\n"); + printf("GPR_UB(destreg,9) = RS_UB(2);\n"); + printf("GPR_UB(destreg,10) = RS_UB(4);\n"); + printf("GPR_UB(destreg,11) = RS_UB(6);\n"); + printf("GPR_UB(destreg,12) = RS_UB(8);\n"); + printf("GPR_UB(destreg,13) = RS_UB(10);\n"); + printf("GPR_UB(destreg,14) = RS_UB(12);\n"); + printf("GPR_UB(destreg,15) = RS_UB(14);\n"); + break; + + case PPACH: + printf("GPR_UH(destreg,0) = RT_UH(0);\n"); + printf("GPR_UH(destreg,1) = RT_UH(2);\n"); + printf("GPR_UH(destreg,2) = RT_UH(4);\n"); + printf("GPR_UH(destreg,3) = RT_UH(6);\n"); + printf("GPR_UH(destreg,4) = RS_UH(0);\n"); + printf("GPR_UH(destreg,5) = RS_UH(2);\n"); + printf("GPR_UH(destreg,6) = RS_UH(4);\n"); + printf("GPR_UH(destreg,7) = RS_UH(6);\n"); + break; + + case PPACW: + printf("GPR_UW(destreg,0) = RT_UW(0);\n"); + printf("GPR_UW(destreg,1) = RT_UW(2);\n"); + printf("GPR_UW(destreg,2) = RS_UW(0);\n"); + printf("GPR_UW(destreg,3) = RS_UW(2);\n"); + break; + + case PREVH: + printf("GPR_UH(destreg,0) = RT_UH(3);\n"); + printf("GPR_UH(destreg,1) = RT_UH(2);\n"); + printf("GPR_UH(destreg,2) = RT_UH(1);\n"); + printf("GPR_UH(destreg,3) = RT_UH(0);\n"); + printf("GPR_UH(destreg,4) = RT_UH(7);\n"); + printf("GPR_UH(destreg,5) = RT_UH(6);\n"); + printf("GPR_UH(destreg,6) = RT_UH(5);\n"); + printf("GPR_UH(destreg,7) = RT_UH(4);\n"); + break; + + case PROT3W: + printf("GPR_UW(destreg,0) = RT_UW(0);\n"); + printf("GPR_UW(destreg,1) = RT_UW(3);\n"); + printf("GPR_UW(destreg,2) = RT_UW(1);\n"); + printf("GPR_UW(destreg,3) = RT_UW(2);\n"); + break; + + case PINTH: + printf("GPR_UH(destreg,0) = RT_UH(0);\n"); + printf("GPR_UH(destreg,1) = RS_UH(4);\n"); + printf("GPR_UH(destreg,2) = RT_UH(1);\n"); + printf("GPR_UH(destreg,3) = RS_UH(5);\n"); + printf("GPR_UH(destreg,4) = RT_UH(2);\n"); + printf("GPR_UH(destreg,5) = RS_UH(6);\n"); + printf("GPR_UH(destreg,6) = RT_UH(3);\n"); + printf("GPR_UH(destreg,7) = RS_UH(7);\n"); + break; + + case PINTOH: + printf("GPR_UH(destreg,0) = RT_UH(0);\n"); + printf("GPR_UH(destreg,1) = RS_UH(0);\n"); + printf("GPR_UH(destreg,2) = RT_UH(2);\n"); + printf("GPR_UH(destreg,3) = RS_UH(2);\n"); + printf("GPR_UH(destreg,4) = RT_UH(4);\n"); + printf("GPR_UH(destreg,5) = RS_UH(4);\n"); + printf("GPR_UH(destreg,6) = RT_UH(6);\n"); + printf("GPR_UH(destreg,7) = RS_UH(6);\n"); + break; + + case PMXX: /* Parallel move HI or LO / TO or FROM */ + { + if ( (insn->flags & (HI|FROM)) == (HI|FROM) ) + { + printf("GPR_SD(destreg,0) = HI;\n"); + printf("GPR_SD(destreg,1) = HI1;\n"); + } + else if ( (insn->flags & (LO|FROM)) == (LO|FROM) ) + { + printf("GPR_SD(destreg,0) = LO;\n"); + printf("GPR_SD(destreg,1) = LO1;\n"); + } + else if ( (insn->flags & (HI|TO)) == (HI|TO) ) + { + printf("HI = RS_SD(0);\n"); + printf("HI1 = RS_SD(1);\n"); + } + else if ( (insn->flags & (LO|TO)) == (LO|TO) ) + { + printf("LO = RS_SD(0);\n"); + printf("LO1 = RS_SD(1);\n"); + } + break; + } + + case PMTHL: + printf("LO_UW(0) = RS_UW(0);\n"); + printf("HI_UW(0) = RS_UW(1);\n"); + printf("LO_UW(2) = RS_UW(2);\n"); + printf("HI_UW(2) = RS_UW(3);\n"); + break; + + case PMFHL: + printf("if (op1 == 0)\n"); + printf(" {\n"); + printf(" GPR_UW(destreg,0) = LO_UW(0);\n"); + printf(" GPR_UW(destreg,1) = HI_UW(0);\n"); + printf(" GPR_UW(destreg,2) = LO_UW(2);\n"); + printf(" GPR_UW(destreg,3) = HI_UW(2);\n"); + printf(" }\n"); + printf("else if (op1 == 1)\n"); + printf(" {\n"); + printf(" GPR_UW(destreg,0) = LO_UW(1);\n"); + printf(" GPR_UW(destreg,1) = HI_UW(1);\n"); + printf(" GPR_UW(destreg,2) = LO_UW(3);\n"); + printf(" GPR_UW(destreg,3) = HI_UW(3);\n"); + printf(" }\n"); + printf("else if (op1 == 2)\n"); + printf(" {\n"); + printf(" /* NOTE: This code implements a saturate according to the\n"); + printf(" figure on page B-115 and not according to the\n"); + printf(" definition on page B-113 */\n"); + printf(" signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0);\n"); + printf(" signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2);\n"); + printf(" if ( t > SIGNED64 (0x000000007FFFFFFF) )\n"); + printf(" GPR_SD(destreg,0) = SIGNED64 (0x000000007FFFFFFF);\n"); + printf(" else if ( t < - SIGNED64 (0x0000000080000000) )\n"); + printf(" GPR_SD(destreg,0) = - SIGNED64 (0x0000000080000000);\n"); + printf(" else\n"); + printf(" GPR_SD(destreg,0) = t;\n"); + printf(" if ( u > SIGNED64 (0x000000007FFFFFFF) )\n"); + printf(" GPR_SD(destreg,1) = SIGNED64 (0x000000007FFFFFFF);\n"); + printf(" else if ( u < - SIGNED64 (0x0000000080000000) )\n"); + printf(" GPR_SD(destreg,1) = - SIGNED64 (0x0000000080000000);\n"); + printf(" else\n"); + printf(" GPR_SD(destreg,1) = u;\n"); + printf(" }\n"); + printf("else if (op1 == 3)\n"); + printf(" {\n"); + printf(" GPR_UH(destreg,0) = LO_UH(0);\n"); + printf(" GPR_UH(destreg,1) = LO_UH(2);\n"); + printf(" GPR_UH(destreg,2) = HI_UH(0);\n"); + printf(" GPR_UH(destreg,3) = HI_UH(2);\n"); + printf(" GPR_UH(destreg,4) = LO_UH(4);\n"); + printf(" GPR_UH(destreg,5) = LO_UH(6);\n"); + printf(" GPR_UH(destreg,6) = HI_UH(4);\n"); + printf(" GPR_UH(destreg,7) = HI_UH(6);\n"); + printf(" }\n"); + printf("else if (op1 == 4)\n"); + printf(" {\n"); + printf(" if (LO_SW(0) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,0) = 0x7FFF;\n"); + printf(" else if (LO_SW(0) < -0x8000)\n"); + printf(" GPR_UH(destreg,0) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,0) = LO_UH(0);\n"); + + printf(" if (LO_SW(1) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,1) = 0x7FFF;\n"); + printf(" else if (LO_SW(1) < -0x8000)\n"); + printf(" GPR_UH(destreg,1) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,1) = LO_UH(2);\n"); + + printf(" if (HI_SW(0) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,2) = 0x7FFF;\n"); + printf(" else if (HI_SW(0) < -0x8000)\n"); + printf(" GPR_UH(destreg,2) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,2) = HI_UH(0);\n"); + + printf(" if (HI_SW(1) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,3) = 0x7FFF;\n"); + printf(" else if (HI_SW(1) < -0x8000)\n"); + printf(" GPR_UH(destreg,3) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,3) = HI_UH(2);\n"); + + printf(" if (LO_SW(2) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,4) = 0x7FFF;\n"); + printf(" else if (LO_SW(2) < -0x8000)\n"); + printf(" GPR_UH(destreg,4) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,4) = LO_UH(4);\n"); + + printf(" if (LO_SW(3) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,5) = 0x7FFF;\n"); + printf(" else if (LO_SW(3) < -0x8000)\n"); + printf(" GPR_UH(destreg,5) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,5) = LO_UH(6);\n"); + + printf(" if (HI_SW(2) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,6) = 0x7FFF;\n"); + printf(" else if (HI_SW(2) < -0x8000)\n"); + printf(" GPR_UH(destreg,6) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,6) = HI_UH(4);\n"); + + printf(" if (HI_SW(3) > 0x7FFF)\n"); + printf(" GPR_UH(destreg,7) = 0x7FFF;\n"); + printf(" else if (HI_SW(3) < -0x8000)\n"); + printf(" GPR_UH(destreg,7) = 0x8000;\n"); + printf(" else\n"); + printf(" GPR_UH(destreg,7) = HI_UH(6);\n"); + + printf(" }\n"); + break; + + case PLZCW: + printf("unsigned long value;\n"); + printf("int test;\n"); + printf("int count;\n"); + printf("int i;\n"); + + printf("value = RS_UW(0);\n"); + printf("count = 0;\n"); + printf("test = !!(value & (1 << 31));\n"); + printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n"); + printf(" count++;\n"); + printf("GPR_UW(destreg,0) = count;\n"); + + printf("value = RS_UW(1);\n"); + printf("count = 0;\n"); + printf("test = !!(value & (1 << 31));\n"); + printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n"); + printf(" count++;\n"); + printf("GPR_UW(destreg,1) = count;\n"); + break; + + case PEXT5: + printf("int i;\n"); + printf("for(i=0;i> (31 - 15)) \n"); + printf(" | ((x & (31 << 19)) >> (19 - 10)) \n"); + printf(" | ((x & (31 << 11)) >> (11 - 5)) \n"); + printf(" | ((x & (31 << 3)) >> (3 - 0)); \n"); + printf(" }\n"); + break; +/* end-sanitize-r5900 */ + + case NYI: + fprintf(stderr,"Warning: Unimplemented opcode: %s\n",insn->name) ; + + printf("SignalException(ReservedInstruction,instruction);\n"); + break; + + default: + fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ; + exit(6) ; + } +} + +/*---------------------------------------------------------------------------*/ + +/* The command-line feature controls are presented in a similar style + to those offered by GCC, in the aim of providing a consistent + interface to the user. */ +typedef enum { + T_NONE, /* no argument - mask and value fields control "feature" definition */ + T_NUM, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */ + T_STRING /* string argument - optionally prcededed by '=' */ +} mactypes; + +struct { + char *name; + mactypes type; + unsigned int mask; + unsigned int value; + char *desc; +} machine_options[] = { + {"ips", T_NUM, MASK_ISA,0,"\tSelect MIPS ISA version"}, + {"cpu", T_STRING,0,0,"\t\tSelect particular MIPS architecture"}, + {"gp64", T_NONE, FEATURE_GP64,FEATURE_GP64,"\t\t\tSelect 64bit GP registers"}, + {"gp32", T_NONE, FEATURE_GP64,0,"\t\t\tSelect 32bit GP registers"}, + {"no-fp", T_NONE, FEATURE_HASFPU,0,"\t\tDisable FP simulation"}, + {"single-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),(FEATURE_FPSINGLE | FEATURE_HASFPU),"\t\tSelect single precision only FPU"}, + {"double-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),FEATURE_HASFPU,"\t\tSelect double precision FPU"}, + {0, T_NONE, 0,0} +}; + +/* The following architecture identies are those accepted by the "-mcpu" option: */ +struct architectures { + const char *name; /* ASCII string identifier for command-line, no white-space allowed */ + unsigned int idflag; /* or-ed into "isa" value */ +}; + +static const struct architectures available_architectures[] = { + {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */ + {"3900",ARCH_R3900}, /* Toshiba R3900 (TX39) */ + /* start-sanitize-tx49 */ + {"4900",ARCH_R4900}, /* Toshiba R4900 (TX49) */ + /* end-sanitize-tx49 */ + /* start-sanitize-tx19 */ + {"1900",ARCH_R3900}, /* Toshiba R1900 (TX19) */ + /* end-sanitize-tx19 */ + /* start-sanitize-r5900 */ + {"5900",ARCH_R5900}, + /* end-sanitize-r5900 */ + {0, 0} /* terminator */ +}; + +/*---------------------------------------------------------------------------*/ + +static void +usage(name) + char *name; +{ + int loop; + + fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name); + + fprintf(stderr,"\ +The output of this program is a block of 'C' code designed to be\n\ +included into the main simulation control loop of a device specific\n\ +simulator.\n"); + + fprintf(stderr,"\nOptions:\n"); + fprintf(stderr," -h --help\t\tProvide this help text\n"); + fprintf(stderr," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n"); + fprintf(stderr," -w --warnings\t\tEnable all the simulator engine warnings\n"); + + for (loop = 0; (machine_options[loop].name != 0); loop++) { + fprintf(stderr," -m%s",machine_options[loop].name); + switch (machine_options[loop].type) { + case T_NUM : + fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask); + case T_NONE : + break; + + case T_STRING : + fprintf(stderr,"=name"); + break; + + default : + fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",name,machine_options[loop].type); + exit(1); + } + fprintf(stderr,"%s\n",machine_options[loop].desc); + } + + fprintf(stderr,"\nAvailable \"-mcpu\" architectures: "); + for (loop = 0; (available_architectures[loop].name != 0); loop++) + fprintf(stderr,"%s ",available_architectures[loop].name); + fprintf(stderr,"\n\n"); + + fprintf(stderr,"\ +The \"trace\" and \"warnings\" options do not define the output stream.\n\ +They only inform the code that includes the constructed engine to provide\n\ +the required features.\n\n\ +The \"-mips0\" option forces the construction of a simulator supporting\n\ +the highest available MIPS ISA supported.\n"); + + return; +} + +/*---------------------------------------------------------------------------*/ + +int +main(argc,argv) + int argc; + char **argv; +{ + int c; + char *progname = argv[0]; + unsigned int doarch = DEF_ISA; + unsigned int features = 0; /* default state */ + + if (DEF_FP) + features |= FEATURE_HASFPU; + if (!DEF_PROC64) + features |= FEATURE_PROC32; + if (DEF_FPSINGLE) + features |= FEATURE_FPSINGLE; + + if (features & FEATURE_PROC32) + features &= ~FEATURE_GP64; + else + features |= FEATURE_GP64; + + while (1) { + int option_index = 0; + static struct option cmdline[] = { + {"fast", 0,0,'f'}, + {"help", 0,0,'h'}, + {"warnings",0,0,'w'}, + {"igen", 0,0,'i'}, + {0, 0,0,0} + }; + + c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index); + if (c == -1) + break ; /* out of the while loop */ + + switch (c) { + case 'h' : /* help */ + usage(progname); + exit(0); + + case 'f' : /* fast */ + features |= FEATURE_FAST; + break; + + case 'i' : /* igen formatted output */ + features |= FEATURE_IGEN; + break; + + case 'w' : /* warnings */ + features |= FEATURE_WARNINGS; + /* TODO: Future extension: Allow better control over the warnings generated: + disable warnings -wnone ~FEATURE_WARNINGS + all possible warnings -wall FEATURE_WARNINGS + pipeline stall occuring -wstall FEATURE_WARN_STALL + LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO + write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest + bad r31 use -wr31 FEATURE_WARN_R31 + undefined results -wresult FEATURE_WARN_RESULT + */ + break; + + case 'm' : /* machine options */ + { + int loop; + + for (loop = 0; (machine_options[loop].name != 0); loop++) + if (strncmp(machine_options[loop].name,optarg,strlen(machine_options[loop].name)) == 0) { + char *loptarg = (optarg + strlen(machine_options[loop].name)); + switch (machine_options[loop].type) { + case T_NONE : + if (*loptarg) { + fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name); + exit(1); + } + features &= ~(machine_options[loop].mask); + features |= machine_options[loop].value; + break; + + case T_NUM : + if (*loptarg && *loptarg == '=') + loptarg++; + + if (strcmp(machine_options[loop].name,"ips") == 0) { + unsigned int num; + + if (!*loptarg) { + fprintf(stderr,"%s: ISA number expected after -mips\n",progname); + exit(1); + } + + num = my_strtoul(loptarg,&loptarg,10); + + if ((num == ULONG_MAX) && (errno = ERANGE)) { + fprintf(stderr,"%s: Invalid number given to -mips option\n",progname); + exit(1); + } + + if (*loptarg) { + fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg); + exit(1); + } + + if (num > MASK_ISA) { + fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA); + exit(1); + } + + doarch = ((doarch & ~MASK_ISA) | num); + if ((num == 0) || (num > 2)) { + if ((features & FEATURE_PROC32) || !(features & FEATURE_GP64)) + fprintf(stderr,"%s: Warning: -mips%d forcing -mgp64\n",progname,num); + features |= FEATURE_GP64; + features &= ~FEATURE_PROC32; + } else { + if (!(features & FEATURE_PROC32) || (features & FEATURE_GP64)) + fprintf(stderr,"%s: Warning: -mips%d forcing -mgp32\n",progname,num); + features &= ~FEATURE_GP64; + features |= FEATURE_PROC32; + } + } else { + fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg); + exit(1); + } + break; + + case T_STRING : + if (*loptarg && *loptarg == '=') + loptarg++; + + if (strcmp(machine_options[loop].name,"cpu") == 0) { + int archloop; + + if (!*loptarg) { + fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname); + exit(1); + } + + for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) { + if ((*loptarg == 'v') || (*loptarg == 'V')) + loptarg++; + + if ((*loptarg == 'r') || (*loptarg == 'R')) + loptarg++; + + if (strcmp(available_architectures[archloop].name,loptarg) == 0) { + doarch |= available_architectures[archloop].idflag; + break; + } + } + + if (available_architectures[archloop].name == 0) { + fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg); + exit(1); + } + } else { + fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg); + exit(1); + } + break; + + default : + fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type); + exit(1); + } + break; + } + + if (machine_options[loop].name == 0) { + fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg); + exit(1); + } + } + break; + + case '?' : + /* An error message should already have been displayed */ + exit(1); + + default : + fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c); + exit(1); + } + } + + if (optind < argc) { + fprintf(stderr,"%s: Spurios non-option arguments ",progname); + while (optind < argc) + fprintf(stderr,"\"%s\" ",argv[optind++]); + fprintf(stderr,"\n"); + exit(1); + } + + if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS)) + fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n"); + + process_instructions(doarch,features) ; + return(0) ; +} + +/*---------------------------------------------------------------------------*/ + +/* We can't assume that the compiler for the build system has strtoul, + so we provide our own copy. */ + +/* + * Copyright (c) 1990 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +static unsigned long +my_strtoul(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; +{ + register const char *s = nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *) (any ? s - 1 : nptr); + return (acc); +} + +/*---------------------------------------------------------------------------*/ + +/*> EOF gencode.c <*/ diff --git a/sim/txvu/gpuif.c b/sim/txvu/gpuif.c new file mode 100644 index 00000000000..9787bf43405 --- /dev/null +++ b/sim/txvu/gpuif.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#include "sim-main.h" + +#include "device.h" +#include "gpuif.h" + +int +gpuif_io_read_buffer(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Read!\n", me->name); + return nr_bytes; +} + +int +gpuif_io_write_buffer(device *me, + const void *source, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Write!\n", me->name); + return nr_bytes; +} + +device gpuif_device = + { + "Gpuif deivce", + &gpuif_io_read_buffer, + &gpuif_io_write_buffer + }; + +void +gpuif_attach(SIM_DESC sd) +{ + sim_core_attach (sd, NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + GPUIF_REGISTER_WINDOW_START, + GPUIF_REGISTER_WINDOW_SIZE /*nr_bytes*/, + 0 /*modulo*/, + &gpuif_device, + NULL /*buffer*/); +} diff --git a/sim/txvu/gpuif.h b/sim/txvu/gpuif.h new file mode 100644 index 00000000000..d38e1fdd5ce --- /dev/null +++ b/sim/txvu/gpuif.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef GPUIF_H_ +#define GPUIF_H_ + +#include "sim-main.h" + +void gpuif_attach(SIM_DESC sd); + +#define GPUIF_REGISTER_WINDOW_START 0x10000700 + +#define GPUIF_CTRL_ADDR 0x10000700 + +#define GPUIF_REGISTER_WINDOW_END 0x10000790 +#define GPUIF_REGISTER_WINDOW_SIZE (GPUIF_REGISTER_WINDOW_END - GPUIF_REGISTER_WINDOW_START) + +#endif diff --git a/sim/txvu/hardware.c b/sim/txvu/hardware.c new file mode 100644 index 00000000000..2e87c1899e9 --- /dev/null +++ b/sim/txvu/hardware.c @@ -0,0 +1,24 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#include "gpuif.h" +#include "dma.h" +#include "pke0.h" +#include "pke1.h" +#include "vu0.h" +#include "vu1.h" + +#include "hardware.h" + +void +register_devices(SIM_DESC sd) +{ + /* Attach a bunch of devices... */ + gpuif_attach(sd); + dma_attach(sd); + pke0_attach(sd); + vu0_attach(sd); + vu1_attach(sd); + pke1_attach(sd); +} diff --git a/sim/txvu/hardware.h b/sim/txvu/hardware.h new file mode 100644 index 00000000000..b70231b1d8f --- /dev/null +++ b/sim/txvu/hardware.h @@ -0,0 +1,12 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef _HARDWARE_H_ +#define _HARDWARE_H_ + +#include "sim-main.h" + +void create_devices(SIM_DESC sd); + +#endif diff --git a/sim/txvu/interp.c b/sim/txvu/interp.c new file mode 100644 index 00000000000..52fba47c0c1 --- /dev/null +++ b/sim/txvu/interp.c @@ -0,0 +1,3457 @@ +/*> interp.c <*/ +/* Simulator for the MIPS architecture. + + This file is part of the MIPS 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. + + $Revision$ + $Author$ + $Date$ + +NOTEs: + +The IDT monitor (found on the VR4300 board), seems to lie about +register contents. It seems to treat the registers as sign-extended +32-bit values. This cause *REAL* problems when single-stepping 64-bit +code on the hardware. + +*/ + +/* The TRACE manifests enable the provision of extra features. If they + are not defined then a simpler (quicker) simulator is constructed + without the required run-time checks, etc. */ +#if 1 /* 0 to allow user build selection, 1 to force inclusion */ +#define TRACE (1) +#endif + +#include "bfd.h" +#include "sim-main.h" +#include "sim-utils.h" +#include "sim-options.h" +#include "sim-assert.h" + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#include "getopt.h" +#include "libiberty.h" +#include "bfd.h" +#include "callback.h" /* GDB simulator callback interface */ +#include "remote-sim.h" /* GDB simulator interface */ + +#include "sysdep.h" + +#ifndef PARAMS +#define PARAMS(x) +#endif + +#include "hardware.h" + +char* pr_addr PARAMS ((SIM_ADDR addr)); +char* pr_uword64 PARAMS ((uword64 addr)); + + +/* Get the simulator engine description, without including the code: */ +#define SIM_MANIFESTS +#include "oengine.c" +#undef SIM_MANIFESTS + + +/* The following reserved instruction value is used when a simulator + trap is required. NOTE: Care must be taken, since this value may be + used in later revisions of the MIPS ISA. */ +#define RSVD_INSTRUCTION (0x00000005) +#define RSVD_INSTRUCTION_MASK (0xFC00003F) + +#define RSVD_INSTRUCTION_ARG_SHIFT 6 +#define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF + + +/* Bits in the Debug register */ +#define Debug_DBD 0x80000000 /* Debug Branch Delay */ +#define Debug_DM 0x40000000 /* Debug Mode */ +#define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */ + + + + + +/*---------------------------------------------------------------------------*/ +/*-- GDB simulator interface ------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +static void ColdReset PARAMS((SIM_DESC sd)); + +/*---------------------------------------------------------------------------*/ + + + +#define DELAYSLOT() {\ + if (STATE & simDELAYSLOT)\ + sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\ + STATE |= simDELAYSLOT;\ + } + +#define JALDELAYSLOT() {\ + DELAYSLOT ();\ + STATE |= simJALDELAYSLOT;\ + } + +#define NULLIFY() {\ + STATE &= ~simDELAYSLOT;\ + STATE |= simSKIPNEXT;\ + } + +#define CANCELDELAYSLOT() {\ + DSSTATE = 0;\ + STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\ + } + +#define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0) +#define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0) + +#define K0BASE (0x80000000) +#define K0SIZE (0x20000000) +#define K1BASE (0xA0000000) +#define K1SIZE (0x20000000) +#define MONITOR_BASE (0xBFC00000) +#define MONITOR_SIZE (1 << 11) +#define MEM_SIZE (2 << 20) + +#if defined(TRACE) +static char *tracefile = "trace.din"; /* default filename for trace log */ +FILE *tracefh = NULL; +static void open_trace PARAMS((SIM_DESC sd)); +#endif /* TRACE */ + +#define OPTION_DINERO_TRACE 200 +#define OPTION_DINERO_FILE 201 + +static SIM_RC +mips_option_handler (sd, opt, arg) + SIM_DESC sd; + int opt; + char *arg; +{ + switch (opt) + { + case OPTION_DINERO_TRACE: /* ??? */ +#if defined(TRACE) + /* Eventually the simTRACE flag could be treated as a toggle, to + allow external control of the program points being traced + (i.e. only from main onwards, excluding the run-time setup, + etc.). */ + if (arg == NULL) + STATE |= simTRACE; + else if (strcmp (arg, "yes") == 0) + STATE |= simTRACE; + else if (strcmp (arg, "no") == 0) + STATE &= ~simTRACE; + else if (strcmp (arg, "on") == 0) + STATE |= simTRACE; + else if (strcmp (arg, "off") == 0) + STATE &= ~simTRACE; + else + { + fprintf (stderr, "Unreconized dinero-trace option `%s'\n", arg); + return SIM_RC_FAIL; + } + return SIM_RC_OK; +#else /* !TRACE */ + fprintf(stderr,"\ +Simulator constructed without dinero tracing support (for performance).\n\ +Re-compile simulator with \"-DTRACE\" to enable this option.\n"); + return SIM_RC_FAIL; +#endif /* !TRACE */ + + case OPTION_DINERO_FILE: +#if defined(TRACE) + if (optarg != NULL) { + char *tmp; + tmp = (char *)malloc(strlen(optarg) + 1); + if (tmp == NULL) + { + sim_io_printf(sd,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg); + return SIM_RC_FAIL; + } + else { + strcpy(tmp,optarg); + tracefile = tmp; + sim_io_printf(sd,"Placing trace information into file \"%s\"\n",tracefile); + } + } +#endif /* TRACE */ + return SIM_RC_OK; + + } + + return SIM_RC_OK; +} + +static const OPTION mips_options[] = +{ + { {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE}, + '\0', "on|off", "Enable dinero tracing", + mips_option_handler }, + { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE}, + '\0', "FILE", "Write dinero trace to FILE", + mips_option_handler }, + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + + +int interrupt_pending; + +static void +interrupt_event (SIM_DESC sd, void *data) +{ + if (SR & status_IE) + { + interrupt_pending = 0; + SignalExceptionInterrupt (); + } + else if (!interrupt_pending) + sim_events_schedule (sd, 1, interrupt_event, data); +} + +extern device gpuif_device; + +/*---------------------------------------------------------------------------*/ +/*-- GDB simulator interface ------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +SIM_DESC +sim_open (kind, cb, abfd, argv) + SIM_OPEN_KIND kind; + host_callback *cb; + struct _bfd *abfd; + char **argv; +{ + SIM_DESC sd = sim_state_alloc (kind, cb); + sim_cpu *cpu = STATE_CPU (sd, 0); + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* FIXME: watchpoints code shouldn't need this */ + STATE_WATCHPOINTS (sd)->pc = &(PC); + STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC); + STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event; + + STATE = 0; + + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) + return 0; + sim_add_option_table (sd, mips_options); + + /* Allocate core managed memory */ + + /* the monitor */ + sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE); + /* For compatibility with the old code - under this (at level one) + are the kernel spaces K0 & K1. Both of these map to a single + smaller sub region */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x", + K1BASE, K0SIZE, + MEM_SIZE, /* actual size */ + K0BASE); + + register_devices(sd); + + /* getopt will print the error message so we just have to exit if this fails. + FIXME: Hmmm... in the case of gdb we need getopt to call + print_filtered. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) + { + /* Uninstall the modules to avoid memory leaks, + file descriptor leaks, etc. */ + sim_module_uninstall (sd); + return 0; + } + + /* check for/establish the a reference program image */ + if (sim_analyze_program (sd, + (STATE_PROG_ARGV (sd) != NULL + ? *STATE_PROG_ARGV (sd) + : NULL), + abfd) != SIM_RC_OK) + { + sim_module_uninstall (sd); + return 0; + } + + /* Configure/verify the target byte order and other runtime + configuration options */ + if (sim_config (sd) != SIM_RC_OK) + { + sim_module_uninstall (sd); + return 0; + } + + if (sim_post_argv_init (sd) != SIM_RC_OK) + { + /* Uninstall the modules to avoid memory leaks, + file descriptor leaks, etc. */ + sim_module_uninstall (sd); + return 0; + } + + /* verify assumptions the simulator made about the host type system. + This macro does not return if there is a problem */ + SIM_ASSERT (sizeof(int) == (4 * sizeof(char))); + SIM_ASSERT (sizeof(word64) == (8 * sizeof(char))); + +#if defined(HASFPU) + /* Check that the host FPU conforms to IEEE 754-1985 for the SINGLE + and DOUBLE binary formats. This is a bit nasty, requiring that we + trust the explicit manifests held in the source: */ + /* TODO: We need to cope with the simulated target and the host not + having the same endianness. This will require the high and low + words of a (double) to be swapped when converting between the + host and the simulated target. */ + { + union { + unsigned int i[2]; + double d; + float f[2]; + } s; + + s.d = (double)523.2939453125; + + if ((s.i[0] == 0 && (s.f[1] != (float)4.01102924346923828125 + || s.i[1] != 0x40805A5A)) + || (s.i[1] == 0 && (s.f[0] != (float)4.01102924346923828125 + || s.i[0] != 0x40805A5A))) + { + fprintf(stderr,"The host executing the simulator does not seem to have IEEE 754-1985 std FP\n"); + return 0; + } + } +#endif /* HASFPU */ + + /* This is NASTY, in that we are assuming the size of specific + registers: */ + { + int rn; + for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) { + if (rn < 32) + cpu->register_widths[rn] = GPRLEN; + else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32))) + cpu->register_widths[rn] = GPRLEN; + else if ((rn >= 33) && (rn <= 37)) + cpu->register_widths[rn] = GPRLEN; + else if ((rn == SRIDX) || (rn == FCR0IDX) || (rn == FCR31IDX) || ((rn >= 72) && (rn <= 89))) + cpu->register_widths[rn] = 32; + else + cpu->register_widths[rn] = 0; + } + /* start-sanitize-r5900 */ + + /* set the 5900 "upper" registers to 64 bits */ + for( rn = LAST_EMBED_REGNUM+1; rn < NUM_REGS; rn++) + cpu->register_widths[rn] = 64; + /* end-sanitize-r5900 */ + } + +#if defined(TRACE) + if (STATE & simTRACE) + open_trace(sd); +#endif /* TRACE */ + + /* Write the monitor trap address handlers into the monitor (eeprom) + address space. This can only be done once the target endianness + has been determined. */ + { + unsigned loop; + /* Entry into the IDT monitor is via fixed address vectors, and + not using machine instructions. To avoid clashing with use of + the MIPS TRAP system, we place our own (simulator specific) + "undefined" instructions into the relevant vector slots. */ + for (loop = 0; (loop < MONITOR_SIZE); loop += 4) + { + address_word vaddr = (MONITOR_BASE + loop); + unsigned32 insn = (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT)); + H2T (insn); + sim_write (sd, vaddr, (char *)&insn, sizeof (insn)); + } + /* The PMON monitor uses the same address space, but rather than + branching into it the address of a routine is loaded. We can + cheat for the moment, and direct the PMON routine to IDT style + instructions within the monitor space. This relies on the IDT + monitor not using the locations from 0xBFC00500 onwards as its + entry points.*/ + for (loop = 0; (loop < 24); loop++) + { + address_word vaddr = (MONITOR_BASE + 0x500 + (loop * 4)); + unsigned32 value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */ + switch (loop) + { + case 0: /* read */ + value = 7; + break; + case 1: /* write */ + value = 8; + break; + case 2: /* open */ + value = 6; + break; + case 3: /* close */ + value = 10; + break; + case 5: /* printf */ + value = ((0x500 - 16) / 8); /* not an IDT reason code */ + break; + case 8: /* cliexit */ + value = 17; + break; + case 11: /* flush_cache */ + value = 28; + break; + } + /* FIXME - should monitor_base be SIM_ADDR?? */ + value = ((unsigned int)MONITOR_BASE + (value * 8)); + H2T (value); + sim_write (sd, vaddr, (char *)&value, sizeof (value)); + + /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */ + vaddr -= 0x300; + sim_write (sd, vaddr, (char *)&value, sizeof (value)); + } + } + + return sd; +} + +#if defined(TRACE) +static void +open_trace(sd) + SIM_DESC sd; +{ + tracefh = fopen(tracefile,"wb+"); + if (tracefh == NULL) + { + sim_io_eprintf(sd,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile); + tracefh = stderr; + } +} +#endif /* TRACE */ + +void +sim_close (sd, quitting) + SIM_DESC sd; + int quitting; +{ +#ifdef DEBUG + printf("DBG: sim_close: entered (quitting = %d)\n",quitting); +#endif + + /* "quitting" is non-zero if we cannot hang on errors */ + + /* Ensure that any resources allocated through the callback + mechanism are released: */ + sim_io_shutdown (sd); + +#if defined(TRACE) + if (tracefh != NULL && tracefh != stderr) + fclose(tracefh); + tracefh = NULL; + STATE &= ~simTRACE; +#endif /* TRACE */ + + return; +} + + +int +sim_write (sd,addr,buffer,size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + int index; + + /* Return the number of bytes written, or zero if error. */ +#ifdef DEBUG + sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size); +#endif + + /* We use raw read and write routines, since we do not want to count + the GDB memory accesses in our statistics gathering. */ + + for (index = 0; index < size; index++) + { + address_word vaddr = (address_word)addr + index; + address_word paddr; + int cca; + if (!address_translation (sd, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW)) + break; + if (sim_core_write_buffer (sd, NULL, sim_core_read_map, buffer + index, paddr, 1) != 1) + break; + } + + return(index); +} + +int +sim_read (sd,addr,buffer,size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + int index; + + /* Return the number of bytes read, or zero if error. */ +#ifdef DEBUG + sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size); +#endif /* DEBUG */ + + for (index = 0; (index < size); index++) + { + address_word vaddr = (address_word)addr + index; + address_word paddr; + int cca; + if (!address_translation (sd, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW)) + break; + if (sim_core_read_buffer (sd, NULL, sim_core_read_map, buffer + index, paddr, 1) != 1) + break; + } + + return(index); +} + +void +sim_store_register (sd,rn,memory) + SIM_DESC sd; + int rn; + unsigned char *memory; +{ + sim_cpu *cpu = STATE_CPU (sd, 0); + /* NOTE: gdb (the client) stores registers in target byte order + while the simulator uses host byte order */ +#ifdef DEBUG + sim_io_printf(sd,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory))); +#endif /* DEBUG */ + + /* Unfortunately this suffers from the same problem as the register + numbering one. We need to know what the width of each logical + register number is for the architecture being simulated. */ + + if (cpu->register_widths[rn] == 0) + sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn); + /* start-sanitize-r5900 */ + else if (rn == REGISTER_SA) + SA = T2H_8(*(uword64*)memory); + else if (rn > LAST_EMBED_REGNUM) + cpu->registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(uword64*)memory); + /* end-sanitize-r5900 */ + else if (cpu->register_widths[rn] == 32) + cpu->registers[rn] = T2H_4 (*(unsigned int*)memory); + else + cpu->registers[rn] = T2H_8 (*(uword64*)memory); + + return; +} + +void +sim_fetch_register (sd,rn,memory) + SIM_DESC sd; + int rn; + unsigned char *memory; +{ + sim_cpu *cpu = STATE_CPU (sd, 0); + /* NOTE: gdb (the client) stores registers in target byte order + while the simulator uses host byte order */ +#ifdef DEBUG + sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn])); +#endif /* DEBUG */ + + if (cpu->register_widths[rn] == 0) + sim_io_eprintf(sd,"Invalid register width for %d (register fetch ignored)\n",rn); + /* start-sanitize-r5900 */ + else if (rn == REGISTER_SA) + *((uword64 *)memory) = H2T_8(SA); + else if (rn > LAST_EMBED_REGNUM) + *((uword64 *)memory) = H2T_8(cpu->registers1[rn - LAST_EMBED_REGNUM - 1]); + /* end-sanitize-r5900 */ + else if (cpu->register_widths[rn] == 32) + *((unsigned int *)memory) = H2T_4 ((unsigned int)(cpu->registers[rn] & 0xFFFFFFFF)); + else /* 64bit register */ + *((uword64 *)memory) = H2T_8 (cpu->registers[rn]); + + return; +} + + +void +sim_info (sd,verbose) + SIM_DESC sd; + int verbose; +{ + /* Accessed from the GDB "info files" command: */ + if (STATE_VERBOSE_P (sd) || verbose) + { + + sim_io_printf (sd, "MIPS %d-bit %s endian simulator\n", + (PROCESSOR_64BIT ? 64 : 32), + (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN ? "Big" : "Little")); + +#if !defined(FASTSIM) + /* It would be a useful feature, if when performing multi-cycle + simulations (rather than single-stepping) we keep the start and + end times of the execution, so that we can give a performance + figure for the simulator. */ +#endif /* !FASTSIM */ + sim_io_printf (sd, "Number of execution cycles = %ld\n", + (long) sim_events_time (sd)); + + /* print information pertaining to MIPS ISA and architecture being simulated */ + /* things that may be interesting */ + /* instructions executed - if available */ + /* cycles executed - if available */ + /* pipeline stalls - if available */ + /* virtual time taken */ + /* profiling size */ + /* profiling frequency */ + /* profile minpc */ + /* profile maxpc */ + } + profile_print (sd, STATE_VERBOSE_P (sd), NULL, NULL); +} + + +SIM_RC +sim_create_inferior (sd, abfd, argv,env) + SIM_DESC sd; + struct _bfd *abfd; + char **argv; + char **env; +{ + +#ifdef DEBUG + printf("DBG: sim_create_inferior entered: start_address = 0x%s\n", + pr_addr(PC)); +#endif /* DEBUG */ + + ColdReset(sd); + + if (abfd != NULL) + /* override PC value set by ColdReset () */ + PC = (unsigned64) bfd_get_start_address (abfd); + +#if 0 /* def DEBUG */ + if (argv || env) + { + /* We should really place the argv slot values into the argument + registers, and onto the stack as required. However, this + assumes that we have a stack defined, which is not + necessarily true at the moment. */ + char **cptr; + sim_io_printf(sd,"sim_create_inferior() : passed arguments ignored\n"); + for (cptr = argv; (cptr && *cptr); cptr++) + printf("DBG: arg \"%s\"\n",*cptr); + } +#endif /* DEBUG */ + + return SIM_RC_OK; +} + +void +sim_do_command (sd,cmd) + SIM_DESC sd; + char *cmd; +{ + if (sim_args_command (sd, cmd) != SIM_RC_OK) + sim_io_printf (sd, "Error: \"%s\" is not a valid MIPS simulator command.\n", + cmd); +} + +/*---------------------------------------------------------------------------*/ +/*-- Private simulator support interface ------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/* Read a null terminated string from memory, return in a buffer */ +static char * +fetch_str (sd, addr) + SIM_DESC sd; + address_word addr; +{ + char *buf; + int nr = 0; + char null; + while (sim_read (sd, addr + nr, &null, 1) == 1 && null != 0) + nr++; + buf = NZALLOC (char, nr + 1); + sim_read (sd, addr, buf, nr); + return buf; +} + +/* Simple monitor interface (currently setup for the IDT and PMON monitors) */ +static void +sim_monitor(sd,cia,reason) + SIM_DESC sd; + address_word cia; + unsigned int reason; +{ +#ifdef DEBUG + printf("DBG: sim_monitor: entered (reason = %d)\n",reason); +#endif /* DEBUG */ + + /* The IDT monitor actually allows two instructions per vector + slot. However, the simulator currently causes a trap on each + individual instruction. We cheat, and lose the bottom bit. */ + reason >>= 1; + + /* The following callback functions are available, however the + monitor we are simulating does not make use of them: get_errno, + isatty, lseek, rename, system, time and unlink */ + switch (reason) + { + + case 6: /* int open(char *path,int flags) */ + { + char *path = fetch_str (sd, A0); + V0 = sim_io_open (sd, path, (int)A1); + zfree (path); + break; + } + + case 7: /* int read(int file,char *ptr,int len) */ + { + int fd = A0; + int nr = A2; + char *buf = zalloc (nr); + V0 = sim_io_read (sd, fd, buf, nr); + sim_write (sd, A1, buf, nr); + zfree (buf); + } + break; + + case 8: /* int write(int file,char *ptr,int len) */ + { + int fd = A0; + int nr = A2; + char *buf = zalloc (nr); + sim_read (sd, A1, buf, nr); + V0 = sim_io_write (sd, fd, buf, nr); + zfree (buf); + break; + } + + case 10: /* int close(int file) */ + { + V0 = sim_io_close (sd, (int)A0); + break; + } + + case 2: /* Densan monitor: char inbyte(int waitflag) */ + { + if (A0 == 0) /* waitflag == NOWAIT */ + V0 = (ut_reg)-1; + } + /* Drop through to case 11 */ + + case 11: /* char inbyte(void) */ + { + char tmp; + if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char)) + { + sim_io_error(sd,"Invalid return from character read"); + V0 = (ut_reg)-1; + } + else + V0 = (ut_reg)tmp; + break; + } + + case 3: /* Densan monitor: void co(char chr) */ + case 12: /* void outbyte(char chr) : write a byte to "stdout" */ + { + char tmp = (char)(A0 & 0xFF); + sim_io_write_stdout (sd, &tmp, sizeof(char)); + break; + } + + case 17: /* void _exit() */ + { + sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n"); + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, sim_exited, + (unsigned int)(A0 & 0xFFFFFFFF)); + break; + } + + case 28 : /* PMON flush_cache */ + break; + + case 55: /* void get_mem_info(unsigned int *ptr) */ + /* in: A0 = pointer to three word memory location */ + /* out: [A0 + 0] = size */ + /* [A0 + 4] = instruction cache size */ + /* [A0 + 8] = data cache size */ + { + address_word value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */; + H2T (value); + sim_write (sd, A0, (char *)&value, sizeof (value)); + /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */ + break; + } + + case 158 : /* PMON printf */ + /* in: A0 = pointer to format string */ + /* A1 = optional argument 1 */ + /* A2 = optional argument 2 */ + /* A3 = optional argument 3 */ + /* out: void */ + /* The following is based on the PMON printf source */ + { + address_word s = A0; + char c; + signed_word *ap = &A1; /* 1st argument */ + /* This isn't the quickest way, since we call the host print + routine for every character almost. But it does avoid + having to allocate and manage a temporary string buffer. */ + /* TODO: Include check that we only use three arguments (A1, + A2 and A3) */ + while (sim_read (sd, s++, &c, 1) && c != '\0') + { + if (c == '%') + { + char tmp[40]; + enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST; + int width = 0, trunc = 0, haddot = 0, longlong = 0; + while (sim_read (sd, s++, &c, 1) && c != '\0') + { + if (strchr ("dobxXulscefg%", s)) + break; + else if (c == '-') + fmt = FMT_LJUST; + else if (c == '0') + fmt = FMT_RJUST0; + else if (c == '~') + fmt = FMT_CENTER; + else if (c == '*') + { + if (haddot) + trunc = (int)*ap++; + else + width = (int)*ap++; + } + else if (c >= '1' && c <= '9') + { + address_word t = s; + unsigned int n; + while (sim_read (sd, s++, &c, 1) == 1 && isdigit (c)) + tmp[s - t] = c; + tmp[s - t] = '\0'; + n = (unsigned int)strtol(tmp,NULL,10); + if (haddot) + trunc = n; + else + width = n; + s--; + } + else if (c == '.') + haddot = 1; + } + switch (c) + { + case '%': + sim_io_printf (sd, "%%"); + break; + case 's': + if ((int)*ap != 0) + { + address_word p = *ap++; + char ch; + while (sim_read (sd, p++, &ch, 1) == 1 && ch != '\0') + sim_io_printf(sd, "%c", ch); + } + else + sim_io_printf(sd,"(null)"); + break; + case 'c': + sim_io_printf (sd, "%c", (int)*ap++); + break; + default: + if (c == 'l') + { + sim_read (sd, s++, &c, 1); + if (c == 'l') + { + longlong = 1; + sim_read (sd, s++, &c, 1); + } + } + if (strchr ("dobxXu", c)) + { + word64 lv = (word64) *ap++; + if (c == 'b') + sim_io_printf(sd,""); + else + { + sprintf (tmp, "%%%s%c", longlong ? "ll" : "", c); + if (longlong) + sim_io_printf(sd, tmp, lv); + else + sim_io_printf(sd, tmp, (int)lv); + } + } + else if (strchr ("eEfgG", c)) + { + double dbl = *(double*)(ap++); + sprintf (tmp, "%%%d.%d%c", width, trunc, c); + sim_io_printf (sd, tmp, dbl); + trunc = 0; + } + } + } + else + sim_io_printf(sd, "%c", c); + } + break; + } + + default: + sim_io_error (sd, "TODO: sim_monitor(%d) : PC = 0x%s\n", + reason, pr_addr(cia)); + break; + } + return; +} + +/* Store a word into memory. */ + +static void +store_word (sd, cia, vaddr, val) + SIM_DESC sd; + address_word cia; + uword64 vaddr; + t_reg val; +{ + address_word paddr; + int uncached; + + if ((vaddr & 3) != 0) + SignalExceptionAddressStore (); + else + { + if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached, + isTARGET, isREAL)) + { + const uword64 mask = 7; + uword64 memval; + unsigned int byte; + + paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)); + byte = (vaddr & mask) ^ (BigEndianCPU << 2); + memval = ((uword64) val) << (8 * byte); + StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr, + isREAL); + } + } +} + +/* Load a word from memory. */ + +static t_reg +load_word (sd, cia, vaddr) + SIM_DESC sd; + address_word cia; + uword64 vaddr; +{ + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad (); + else + { + address_word paddr; + int uncached; + + if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached, + isTARGET, isREAL)) + { + const uword64 mask = 0x7; + const unsigned int reverse = ReverseEndian ? 1 : 0; + const unsigned int bigend = BigEndianCPU ? 1 : 0; + uword64 memval; + unsigned int byte; + + paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2)); + LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr, + isDATA, isREAL); + byte = (vaddr & mask) ^ (bigend << 2); + return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32); + } + } + + return 0; +} + +/* Simulate the mips16 entry and exit pseudo-instructions. These + would normally be handled by the reserved instruction exception + code, but for ease of simulation we just handle them directly. */ + +static void +mips16_entry (sd,insn) + SIM_DESC sd; + unsigned int insn; +{ + int aregs, sregs, rreg; + +#ifdef DEBUG + printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn); +#endif /* DEBUG */ + + aregs = (insn & 0x700) >> 8; + sregs = (insn & 0x0c0) >> 6; + rreg = (insn & 0x020) >> 5; + + /* This should be checked by the caller. */ + if (sregs == 3) + abort (); + + if (aregs < 5) + { + int i; + t_reg tsp; + + /* This is the entry pseudo-instruction. */ + + for (i = 0; i < aregs; i++) + store_word ((uword64) (SP + 4 * i), GPR[i + 4]); + + tsp = SP; + SP -= 32; + + if (rreg) + { + tsp -= 4; + store_word ((uword64) tsp, RA); + } + + for (i = 0; i < sregs; i++) + { + tsp -= 4; + store_word ((uword64) tsp, GPR[16 + i]); + } + } + else + { + int i; + t_reg tsp; + + /* This is the exit pseudo-instruction. */ + + tsp = SP + 32; + + if (rreg) + { + tsp -= 4; + RA = load_word ((uword64) tsp); + } + + for (i = 0; i < sregs; i++) + { + tsp -= 4; + GPR[i + 16] = load_word ((uword64) tsp); + } + + SP += 32; + +#if defined(HASFPU) + if (aregs == 5) + { + FGR[0] = WORD64LO (GPR[4]); + FPR_STATE[0] = fmt_uninterpreted; + } + else if (aregs == 6) + { + FGR[0] = WORD64LO (GPR[5]); + FGR[1] = WORD64LO (GPR[4]); + FPR_STATE[0] = fmt_uninterpreted; + FPR_STATE[1] = fmt_uninterpreted; + } +#endif /* defined(HASFPU) */ + + PC = RA; + } +} + +/*-- trace support ----------------------------------------------------------*/ + +/* The TRACE support is provided (if required) in the memory accessing + routines. Since we are also providing the architecture specific + features, the architecture simulation code can also deal with + notifying the TRACE world of cache flushes, etc. Similarly we do + not need to provide profiling support in the simulator engine, + since we can sample in the instruction fetch control loop. By + defining the TRACE manifest, we add tracing as a run-time + option. */ + +#if defined(TRACE) +/* Tracing by default produces "din" format (as required by + dineroIII). Each line of such a trace file *MUST* have a din label + and address field. The rest of the line is ignored, so comments can + be included if desired. The first field is the label which must be + one of the following values: + + 0 read data + 1 write data + 2 instruction fetch + 3 escape record (treated as unknown access type) + 4 escape record (causes cache flush) + + The address field is a 32bit (lower-case) hexadecimal address + value. The address should *NOT* be preceded by "0x". + + The size of the memory transfer is not important when dealing with + cache lines (as long as no more than a cache line can be + transferred in a single operation :-), however more information + could be given following the dineroIII requirement to allow more + complete memory and cache simulators to provide better + results. i.e. the University of Pisa has a cache simulator that can + also take bus size and speed as (variable) inputs to calculate + complete system performance (a much more useful ability when trying + to construct an end product, rather than a processor). They + currently have an ARM version of their tool called ChARM. */ + + +void +dotrace (SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...) +{ + if (STATE & simTRACE) { + va_list ap; + fprintf(tracefh,"%d %s ; width %d ; ", + type, + pr_addr(address), + width); + va_start(ap,comment); + vfprintf(tracefh,comment,ap); + va_end(ap); + fprintf(tracefh,"\n"); + } + /* NOTE: Since the "din" format will only accept 32bit addresses, and + we may be generating 64bit ones, we should put the hi-32bits of the + address into the comment field. */ + + /* TODO: Provide a buffer for the trace lines. We can then avoid + performing writes until the buffer is filled, or the file is + being closed. */ + + /* NOTE: We could consider adding a comment field to the "din" file + produced using type 3 markers (unknown access). This would then + allow information about the program that the "din" is for, and + the MIPs world that was being simulated, to be placed into the + trace file. */ + + return; +} +#endif /* TRACE */ + +/*---------------------------------------------------------------------------*/ +/*-- simulator engine -------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +static void +ColdReset (sd) + SIM_DESC sd; +{ + /* RESET: Fixed PC address: */ + PC = UNSIGNED64 (0xFFFFFFFFBFC00000); + /* The reset vector address is in the unmapped, uncached memory space. */ + + SR &= ~(status_SR | status_TS | status_RP); + SR |= (status_ERL | status_BEV); + + /* Cheat and allow access to the complete register set immediately */ + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT + && WITH_TARGET_WORD_BITSIZE == 64) + SR |= status_FR; /* 64bit registers */ + + /* Ensure that any instructions with pending register updates are + cleared: */ + { + int loop; + for (loop = 0; (loop < PSLOTS); loop++) + PENDING_SLOT_REG[loop] = (LAST_EMBED_REGNUM + 1); + PENDING_IN = PENDING_OUT = PENDING_TOTAL = 0; + } + + /* Initialise the FPU registers to the unknown state */ + if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) + { + int rn; + for (rn = 0; (rn < 32); rn++) + FPR_STATE[rn] = fmt_uninterpreted; + } + + return; +} + +/* Description from page A-22 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Translate a virtual address to a physical address and cache + coherence algorithm describing the mechanism used to resolve the + memory reference. Given the virtual address vAddr, and whether the + reference is to Instructions ot Data (IorD), find the corresponding + physical address (pAddr) and the cache coherence algorithm (CCA) + used to resolve the reference. If the virtual address is in one of + the unmapped address spaces the physical address and the CCA are + determined directly by the virtual address. If the virtual address + is in one of the mapped address spaces then the TLB is used to + determine the physical address and access type; if the required + translation is not present in the TLB or the desired access is not + permitted the function fails and an exception is taken. + + NOTE: Normally (RAW == 0), when address translation fails, this + function raises an exception and does not return. */ + +int +address_translation(sd,cia,vAddr,IorD,LorS,pAddr,CCA,raw) + SIM_DESC sd; + address_word cia; + address_word vAddr; + int IorD; + int LorS; + address_word *pAddr; + int *CCA; + int raw; +{ + int res = -1; /* TRUE : Assume good return */ + +#ifdef DEBUG + sim_io_printf(sd,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD")); +#endif + + /* Check that the address is valid for this memory model */ + + /* For a simple (flat) memory model, we simply pass virtual + addressess through (mostly) unchanged. */ + vAddr &= 0xFFFFFFFF; + + *pAddr = vAddr; /* default for isTARGET */ + *CCA = Uncached; /* not used for isHOST */ + + return(res); +} + +/* Description from page A-23 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Prefetch data from memory. Prefetch is an advisory instruction for + which an implementation specific action is taken. The action taken + may increase performance, but must not change the meaning of the + program, or alter architecturally-visible state. */ + +void +prefetch(sd,cia,CCA,pAddr,vAddr,DATA,hint) + SIM_DESC sd; + address_word cia; + int CCA; + address_word pAddr; + address_word vAddr; + int DATA; + int hint; +{ +#ifdef DEBUG + sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint); +#endif /* DEBUG */ + + /* For our simple memory model we do nothing */ + return; +} + +/* Description from page A-22 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Load a value from memory. Use the cache and main memory as + specified in the Cache Coherence Algorithm (CCA) and the sort of + access (IorD) to find the contents of AccessLength memory bytes + starting at physical location pAddr. The data is returned in the + fixed width naturally-aligned memory element (MemElem). The + low-order two (or three) bits of the address and the AccessLength + indicate which of the bytes within MemElem needs to be given to the + processor. If the memory access type of the reference is uncached + then only the referenced bytes are read from memory and valid + within the memory element. If the access type is cached, and the + data is not present in cache, an implementation specific size and + alignment block of memory is read and loaded into the cache to + satisfy a load reference. At a minimum, the block is the entire + memory element. */ +void +load_memory(sd,cia,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD) + SIM_DESC sd; + address_word cia; + uword64* memvalp; + uword64* memval1p; + int CCA; + int AccessLength; + address_word pAddr; + address_word vAddr; + int IorD; +{ + uword64 value = 0; + uword64 value1 = 0; + +#ifdef DEBUG + sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION")); +#endif /* DEBUG */ + +#if defined(WARN_MEM) + if (CCA != uncached) + sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA); +#endif /* WARN_MEM */ + + /* If instruction fetch then we need to check that the two lo-order + bits are zero, otherwise raise a InstructionFetch exception: */ + if ((IorD == isINSTRUCTION) + && ((pAddr & 0x3) != 0) + && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0))) + SignalExceptionInstructionFetch (); + + if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) + { + /* In reality this should be a Bus Error */ + sim_io_error (sd, "AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n", + AccessLength, + (LOADDRMASK + 1) << 2, + pr_addr (pAddr)); + } + +#if defined(TRACE) + dotrace(sd,tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction")); +#endif /* TRACE */ + + /* Read the specified number of bytes from memory. Adjust for + host/target byte ordering/ Align the least significant byte + read. */ + + switch (AccessLength) + { + case AccessLength_QUADWORD : + { + unsigned_16 val = sim_core_read_aligned_16 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + value1 = VH8_16 (val); + value = VL8_16 (val); + break; + } + case AccessLength_DOUBLEWORD : + value = sim_core_read_aligned_8 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + break; + case AccessLength_SEPTIBYTE : + value = sim_core_read_misaligned_7 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + case AccessLength_SEXTIBYTE : + value = sim_core_read_misaligned_6 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + case AccessLength_QUINTIBYTE : + value = sim_core_read_misaligned_5 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + case AccessLength_WORD : + value = sim_core_read_aligned_4 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + break; + case AccessLength_TRIPLEBYTE : + value = sim_core_read_misaligned_3 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + case AccessLength_HALFWORD : + value = sim_core_read_aligned_2 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + break; + case AccessLength_BYTE : + value = sim_core_read_aligned_1 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_read_map, pAddr); + break; + default: + abort (); + } + +#ifdef DEBUG + printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n", + (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value)); +#endif /* DEBUG */ + + /* See also store_memory. */ + if (AccessLength <= AccessLength_DOUBLEWORD) + { + if (BigEndianMem) + /* for big endian target, byte (pAddr&LOADDRMASK == 0) is + shifted to the most significant byte position. */ + value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8); + else + /* For little endian target, byte (pAddr&LOADDRMASK == 0) + is already in the correct postition. */ + value <<= ((pAddr & LOADDRMASK) * 8); + } + +#ifdef DEBUG + printf("DBG: LoadMemory() : shifted value = 0x%s%s\n", + pr_uword64(value1),pr_uword64(value)); +#endif /* DEBUG */ + + *memvalp = value; + if (memval1p) *memval1p = value1; +} + + +/* Description from page A-23 of the "MIPS IV Instruction Set" manual + (revision 3.1) */ +/* Store a value to memory. The specified data is stored into the + physical location pAddr using the memory hierarchy (data caches and + main memory) as specified by the Cache Coherence Algorithm + (CCA). The MemElem contains the data for an aligned, fixed-width + memory element (word for 32-bit processors, doubleword for 64-bit + processors), though only the bytes that will actually be stored to + memory need to be valid. The low-order two (or three) bits of pAddr + and the AccessLength field indicates which of the bytes within the + MemElem data should actually be stored; only these bytes in memory + will be changed. */ + +void +store_memory(sd,cia,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr) + SIM_DESC sd; + address_word cia; + int CCA; + int AccessLength; + uword64 MemElem; + uword64 MemElem1; /* High order 64 bits */ + address_word pAddr; + address_word vAddr; +{ +#ifdef DEBUG + sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr)); +#endif /* DEBUG */ + +#if defined(WARN_MEM) + if (CCA != uncached) + sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA); +#endif /* WARN_MEM */ + + if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) + sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr)); + +#if defined(TRACE) + dotrace(sd,tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store"); +#endif /* TRACE */ + +#ifdef DEBUG + printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem)); +#endif /* DEBUG */ + + /* See also load_memory */ + if (AccessLength <= AccessLength_DOUBLEWORD) + { + if (BigEndianMem) + /* for big endian target, byte (pAddr&LOADDRMASK == 0) is + shifted to the most significant byte position. */ + MemElem >>= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8); + else + /* For little endian target, byte (pAddr&LOADDRMASK == 0) + is already in the correct postition. */ + MemElem >>= ((pAddr & LOADDRMASK) * 8); + } + +#ifdef DEBUG + printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem)); +#endif /* DEBUG */ + + switch (AccessLength) + { + case AccessLength_QUADWORD : + { + unsigned_16 val = U16_8 (MemElem1, MemElem); + sim_core_write_aligned_16 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, val); + break; + } + case AccessLength_DOUBLEWORD : + sim_core_write_aligned_8 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + case AccessLength_SEPTIBYTE : + sim_core_write_misaligned_7 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + case AccessLength_SEXTIBYTE : + sim_core_write_misaligned_6 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + case AccessLength_QUINTIBYTE : + sim_core_write_misaligned_5 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + case AccessLength_WORD : + sim_core_write_aligned_4 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + case AccessLength_TRIPLEBYTE : + sim_core_write_misaligned_3 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + case AccessLength_HALFWORD : + sim_core_write_aligned_2 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + case AccessLength_BYTE : + sim_core_write_aligned_1 (STATE_CPU (sd, 0), NULL_CIA, + sim_core_write_map, pAddr, MemElem); + break; + default: + abort (); + } + + return; +} + + +unsigned32 +ifetch32 (SIM_DESC sd, + address_word cia, + address_word vaddr) +{ + /* Copy the action of the LW instruction */ + address_word reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0); + address_word bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0); + unsigned64 value; + address_word paddr; + unsigned32 instruction; + unsigned byte; + int cca; + AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &cca, isTARGET, isREAL); + paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2))); + LoadMemory (&value, NULL, cca, AccessLength_WORD, paddr, vaddr, isINSTRUCTION, isREAL); + byte = ((vaddr & LOADDRMASK) ^ (bigend << 2)); + instruction = ((value >> (8 * byte)) & 0xFFFFFFFF); + return instruction; +} + + +/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ +/* Order loads and stores to synchronise shared memory. Perform the + action necessary to make the effects of groups of synchronizable + loads and stores indicated by stype occur in the same order for all + processors. */ +void +sync_operation(sd,cia,stype) + SIM_DESC sd; + address_word cia; + int stype; +{ +#ifdef DEBUG + sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype); +#endif /* DEBUG */ + return; +} + +/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ +/* Signal an exception condition. This will result in an exception + that aborts the instruction. The instruction operation pseudocode + will never see a return from this function call. */ + +void +signal_exception (SIM_DESC sd, + address_word cia, + int exception,...) +{ + int vector; + +#ifdef DEBUG + sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia)); +#endif /* DEBUG */ + + /* Ensure that any active atomic read/modify/write operation will fail: */ + LLBIT = 0; + + switch (exception) { + /* TODO: For testing purposes I have been ignoring TRAPs. In + reality we should either simulate them, or allow the user to + ignore them at run-time. + Same for SYSCALL */ + case Trap : + sim_io_eprintf(sd,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(cia)); + break; + + case SystemCall : + { + va_list ap; + unsigned int instruction; + unsigned int code; + + va_start(ap,exception); + instruction = va_arg(ap,unsigned int); + va_end(ap); + + code = (instruction >> 6) & 0xFFFFF; + + sim_io_eprintf(sd,"Ignoring instruction `syscall %d' (PC 0x%s)\n", + code, pr_addr(cia)); + } + break; + + case DebugBreakPoint : + if (! (Debug & Debug_DM)) + { + if (INDELAYSLOT()) + { + CANCELDELAYSLOT(); + + Debug |= Debug_DBD; /* signaled from within in delay slot */ + DEPC = cia - 4; /* reference the branch instruction */ + } + else + { + Debug &= ~Debug_DBD; /* not signaled from within a delay slot */ + DEPC = cia; + } + + Debug |= Debug_DM; /* in debugging mode */ + Debug |= Debug_DBp; /* raising a DBp exception */ + PC = 0xBFC00200; + sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA); + } + break; + + case ReservedInstruction : + { + va_list ap; + unsigned int instruction; + va_start(ap,exception); + instruction = va_arg(ap,unsigned int); + va_end(ap); + /* Provide simple monitor support using ReservedInstruction + exceptions. The following code simulates the fixed vector + entry points into the IDT monitor by causing a simulator + trap, performing the monitor operation, and returning to + the address held in the $ra register (standard PCS return + address). This means we only need to pre-load the vector + space with suitable instruction values. For systems were + actual trap instructions are used, we would not need to + perform this magic. */ + if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION) + { + sim_monitor(sd, cia, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) ); + /* NOTE: This assumes that a branch-and-link style + instruction was used to enter the vector (which is the + case with the current IDT monitor). */ + sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, RA); + } + /* Look for the mips16 entry and exit instructions, and + simulate a handler for them. */ + else if ((cia & 1) != 0 + && (instruction & 0xf81f) == 0xe809 + && (instruction & 0x0c0) != 0x0c0) + { + mips16_entry (instruction); + sim_engine_restart (sd, NULL, NULL, NULL_CIA); + } + /* else fall through to normal exception processing */ + sim_io_eprintf(sd,"ReservedInstruction 0x%08X at PC = 0x%s\n",instruction,pr_addr(cia)); + } + + case BreakPoint: +#ifdef DEBUG + sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia)); +#endif /* DEBUG */ + /* Keep a copy of the current A0 in-case this is the program exit + breakpoint: */ + { + va_list ap; + unsigned int instruction; + va_start(ap,exception); + instruction = va_arg(ap,unsigned int); + va_end(ap); + /* Check for our special terminating BREAK: */ + if ((instruction & 0x03FFFFC0) == 0x03ff0000) { + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, cia, + sim_exited, (unsigned int)(A0 & 0xFFFFFFFF)); + } + } + if (STATE & simDELAYSLOT) + PC = cia - 4; /* reference the branch instruction */ + else + PC = cia; + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, cia, + sim_stopped, SIM_SIGTRAP); + + default: + /* Store exception code into current exception id variable (used + by exit code): */ + + /* TODO: If not simulating exceptions then stop the simulator + execution. At the moment we always stop the simulation. */ + + /* See figure 5-17 for an outline of the code below */ + if (! (SR & status_EXL)) + { + CAUSE = (exception << 2); + if (STATE & simDELAYSLOT) + { + STATE &= ~simDELAYSLOT; + CAUSE |= cause_BD; + EPC = (cia - 4); /* reference the branch instruction */ + } + else + EPC = cia; + /* FIXME: TLB et.al. */ + vector = 0x180; + } + else + { + CAUSE = (exception << 2); + vector = 0x180; + } + SR |= status_EXL; + /* Store exception code into current exception id variable (used + by exit code): */ + if (SR & status_BEV) + PC = (signed)0xBFC00200 + 0x180; + else + PC = (signed)0x80000000 + 0x180; + + switch ((CAUSE >> 2) & 0x1F) + { + case Interrupt: + /* Interrupts arrive during event processing, no need to + restart */ + return; + + case TLBModification: + case TLBLoad: + case TLBStore: + case AddressLoad: + case AddressStore: + case InstructionFetch: + case DataReference: + /* The following is so that the simulator will continue from the + exception address on breakpoint operations. */ + PC = EPC; + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIM_SIGBUS); + + case ReservedInstruction: + case CoProcessorUnusable: + PC = EPC; + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIM_SIGILL); + + case IntegerOverflow: + case FPE: + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIM_SIGFPE); + + case Trap: + case Watch: + case SystemCall: + PC = EPC; + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIM_SIGTRAP); + + case BreakPoint: + PC = EPC; + sim_engine_abort (sd, STATE_CPU (sd, 0), NULL_CIA, + "FATAL: Should not encounter a breakpoint\n"); + + default : /* Unknown internal exception */ + PC = EPC; + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, + sim_stopped, SIM_SIGABRT); + + } + + case SimulatorFault: + { + va_list ap; + char *msg; + va_start(ap,exception); + msg = va_arg(ap,char *); + va_end(ap); + sim_engine_abort (sd, STATE_CPU (sd, 0), NULL_CIA, + "FATAL: Simulator error \"%s\"\n",msg); + } + } + + return; +} + +#if defined(WARN_RESULT) +/* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ +/* This function indicates that the result of the operation is + undefined. However, this should not affect the instruction + stream. All that is meant to happen is that the destination + register is set to an undefined result. To keep the simulator + simple, we just don't bother updating the destination register, so + the overall result will be undefined. If desired we can stop the + simulator by raising a pseudo-exception. */ +#define UndefinedResult() undefined_result (sd,cia) +static void +undefined_result(sd,cia) + SIM_DESC sd; + address_word cia; +{ + sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia)); +#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */ + state |= simSTOP; +#endif + return; +} +#endif /* WARN_RESULT */ + +void +cache_op(sd,cia,op,pAddr,vAddr,instruction) + SIM_DESC sd; + address_word cia; + int op; + address_word pAddr; + address_word vAddr; + unsigned int instruction; +{ +#if 1 /* stop warning message being displayed (we should really just remove the code) */ + static int icache_warning = 1; + static int dcache_warning = 1; +#else + static int icache_warning = 0; + static int dcache_warning = 0; +#endif + + /* If CP0 is not useable (User or Supervisor mode) and the CP0 + enable bit in the Status Register is clear - a coprocessor + unusable exception is taken. */ +#if 0 + sim_io_printf(sd,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia)); +#endif + + switch (op & 0x3) { + case 0: /* instruction cache */ + switch (op >> 2) { + case 0: /* Index Invalidate */ + case 1: /* Index Load Tag */ + case 2: /* Index Store Tag */ + case 4: /* Hit Invalidate */ + case 5: /* Fill */ + case 6: /* Hit Writeback */ + if (!icache_warning) + { + sim_io_eprintf(sd,"Instruction CACHE operation %d to be coded\n",(op >> 2)); + icache_warning = 1; + } + break; + + default: + SignalException(ReservedInstruction,instruction); + break; + } + break; + + case 1: /* data cache */ + switch (op >> 2) { + case 0: /* Index Writeback Invalidate */ + case 1: /* Index Load Tag */ + case 2: /* Index Store Tag */ + case 3: /* Create Dirty */ + case 4: /* Hit Invalidate */ + case 5: /* Hit Writeback Invalidate */ + case 6: /* Hit Writeback */ + if (!dcache_warning) + { + sim_io_eprintf(sd,"Data CACHE operation %d to be coded\n",(op >> 2)); + dcache_warning = 1; + } + break; + + default: + SignalException(ReservedInstruction,instruction); + break; + } + break; + + default: /* unrecognised cache ID */ + SignalException(ReservedInstruction,instruction); + break; + } + + return; +} + +/*-- FPU support routines ---------------------------------------------------*/ + +#if defined(HASFPU) /* Only needed when building FPU aware simulators */ + +/* Numbers are held in normalized form. The SINGLE and DOUBLE binary + formats conform to ANSI/IEEE Std 754-1985. */ +/* SINGLE precision floating: + * seeeeeeeefffffffffffffffffffffff + * s = 1bit = sign + * e = 8bits = exponent + * f = 23bits = fraction + */ +/* SINGLE precision fixed: + * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii + * s = 1bit = sign + * i = 31bits = integer + */ +/* DOUBLE precision floating: + * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff + * s = 1bit = sign + * e = 11bits = exponent + * f = 52bits = fraction + */ +/* DOUBLE precision fixed: + * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii + * s = 1bit = sign + * i = 63bits = integer + */ + +/* Extract sign-bit: */ +#define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0) +#define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0) +/* Extract biased exponent: */ +#define FP_S_be(v) (((v) >> 23) & 0xFF) +#define FP_D_be(v) (((v) >> 52) & 0x7FF) +/* Extract unbiased Exponent: */ +#define FP_S_e(v) (FP_S_be(v) - 0x7F) +#define FP_D_e(v) (FP_D_be(v) - 0x3FF) +/* Extract complete fraction field: */ +#define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23)) +#define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52)) +/* Extract numbered fraction bit: */ +#define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0) +#define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0) + +/* Explicit QNaN values used when value required: */ +#define FPQNaN_SINGLE (0x7FBFFFFF) +#define FPQNaN_WORD (0x7FFFFFFF) +#define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF) +#define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF) + +/* Explicit Infinity values used when required: */ +#define FPINF_SINGLE (0x7F800000) +#define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000) + +#if 1 /* def DEBUG */ +#define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor"))) +#define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "" : (((v) == fmt_uninterpreted) ? "" : "")))))) +#endif /* DEBUG */ + +uword64 +value_fpr(sd,cia,fpr,fmt) + SIM_DESC sd; + address_word cia; + int fpr; + FP_formats fmt; +{ + uword64 value = 0; + int err = 0; + + /* Treat unused register values, as fixed-point 64bit values: */ + if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown)) +#if 1 + /* If request to read data as "uninterpreted", then use the current + encoding: */ + fmt = FPR_STATE[fpr]; +#else + fmt = fmt_long; +#endif + + /* For values not yet accessed, set to the desired format: */ + if (FPR_STATE[fpr] == fmt_uninterpreted) { + FPR_STATE[fpr] = fmt; +#ifdef DEBUG + printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt)); +#endif /* DEBUG */ + } + if (fmt != FPR_STATE[fpr]) { + sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia)); + FPR_STATE[fpr] = fmt_unknown; + } + + if (FPR_STATE[fpr] == fmt_unknown) { + /* Set QNaN value: */ + switch (fmt) { + case fmt_single: + value = FPQNaN_SINGLE; + break; + + case fmt_double: + value = FPQNaN_DOUBLE; + break; + + case fmt_word: + value = FPQNaN_WORD; + break; + + case fmt_long: + value = FPQNaN_LONG; + break; + + default: + err = -1; + break; + } + } else if (SizeFGR() == 64) { + switch (fmt) { + case fmt_single: + case fmt_word: + value = (FGR[fpr] & 0xFFFFFFFF); + break; + + case fmt_uninterpreted: + case fmt_double: + case fmt_long: + value = FGR[fpr]; + break; + + default : + err = -1; + break; + } + } else { + switch (fmt) { + case fmt_single: + case fmt_word: + value = (FGR[fpr] & 0xFFFFFFFF); + break; + + case fmt_uninterpreted: + case fmt_double: + case fmt_long: + if ((fpr & 1) == 0) { /* even registers only */ + value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF)); + } else { + SignalException(ReservedInstruction,0); + } + break; + + default : + err = -1; + break; + } + } + + if (err) + SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()"); + +#ifdef DEBUG + printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(cia),SizeFGR()); +#endif /* DEBUG */ + + return(value); +} + +void +store_fpr(sd,cia,fpr,fmt,value) + SIM_DESC sd; + address_word cia; + int fpr; + FP_formats fmt; + uword64 value; +{ + int err = 0; + +#ifdef DEBUG + printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(cia),SizeFGR()); +#endif /* DEBUG */ + + if (SizeFGR() == 64) { + switch (fmt) { + case fmt_uninterpreted_32: + fmt = fmt_uninterpreted; + case fmt_single : + case fmt_word : + FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF)); + FPR_STATE[fpr] = fmt; + break; + + case fmt_uninterpreted_64: + fmt = fmt_uninterpreted; + case fmt_uninterpreted: + case fmt_double : + case fmt_long : + FGR[fpr] = value; + FPR_STATE[fpr] = fmt; + break; + + default : + FPR_STATE[fpr] = fmt_unknown; + err = -1; + break; + } + } else { + switch (fmt) { + case fmt_uninterpreted_32: + fmt = fmt_uninterpreted; + case fmt_single : + case fmt_word : + FGR[fpr] = (value & 0xFFFFFFFF); + FPR_STATE[fpr] = fmt; + break; + + case fmt_uninterpreted_64: + fmt = fmt_uninterpreted; + case fmt_uninterpreted: + case fmt_double : + case fmt_long : + if ((fpr & 1) == 0) { /* even register number only */ + FGR[fpr+1] = (value >> 32); + FGR[fpr] = (value & 0xFFFFFFFF); + FPR_STATE[fpr + 1] = fmt; + FPR_STATE[fpr] = fmt; + } else { + FPR_STATE[fpr] = fmt_unknown; + FPR_STATE[fpr + 1] = fmt_unknown; + SignalException(ReservedInstruction,0); + } + break; + + default : + FPR_STATE[fpr] = fmt_unknown; + err = -1; + break; + } + } +#if defined(WARN_RESULT) + else + UndefinedResult(); +#endif /* WARN_RESULT */ + + if (err) + SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()"); + +#ifdef DEBUG + printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_addr(FGR[fpr]),DOFMT(fmt)); +#endif /* DEBUG */ + + return; +} + +int +NaN(op,fmt) + uword64 op; + FP_formats fmt; +{ + int boolean = 0; + switch (fmt) { + case fmt_single: + case fmt_word: + { + sim_fpu wop; + sim_fpu_32to (&wop, op); + boolean = sim_fpu_is_nan (&wop); + break; + } + case fmt_double: + case fmt_long: + { + sim_fpu wop; + sim_fpu_64to (&wop, op); + boolean = sim_fpu_is_nan (&wop); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG +printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +int +Infinity(op,fmt) + uword64 op; + FP_formats fmt; +{ + int boolean = 0; + +#ifdef DEBUG + printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + sim_fpu_32to (&wop, op); + boolean = sim_fpu_is_infinity (&wop); + break; + } + case fmt_double: + { + sim_fpu wop; + sim_fpu_64to (&wop, op); + boolean = sim_fpu_is_infinity (&wop); + break; + } + default: + printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt)); + break; + } + +#ifdef DEBUG + printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +int +Less(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + int boolean = 0; + + /* Argument checking already performed by the FPCOMPARE code */ + +#ifdef DEBUG + printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + boolean = sim_fpu_is_lt (&wop1, &wop2); + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + boolean = sim_fpu_is_lt (&wop1, &wop2); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +int +Equal(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + int boolean = 0; + + /* Argument checking already performed by the FPCOMPARE code */ + +#ifdef DEBUG + printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + boolean = sim_fpu_is_eq (&wop1, &wop2); + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + boolean = sim_fpu_is_eq (&wop1, &wop2); + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt)); +#endif /* DEBUG */ + + return(boolean); +} + +uword64 +AbsoluteValue(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + unsigned32 ans; + sim_fpu_32to (&wop, op); + sim_fpu_abs (&wop, &wop); + sim_fpu_to32 (&ans, &wop); + result = ans; + break; + } + case fmt_double: + { + sim_fpu wop; + unsigned64 ans; + sim_fpu_64to (&wop, op); + sim_fpu_abs (&wop, &wop); + sim_fpu_to64 (&ans, &wop); + result = ans; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + return(result); +} + +uword64 +Negate(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + unsigned32 ans; + sim_fpu_32to (&wop, op); + sim_fpu_neg (&wop, &wop); + sim_fpu_to32 (&ans, &wop); + result = ans; + break; + } + case fmt_double: + { + sim_fpu wop; + unsigned64 ans; + sim_fpu_64to (&wop, op); + sim_fpu_neg (&wop, &wop); + sim_fpu_to64 (&ans, &wop); + result = ans; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + return(result); +} + +uword64 +Add(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_add (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_add (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +Sub(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_sub (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + } + break; + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_sub (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + } + break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +Multiply(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_mul (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_mul (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +Divide(op1,op2,fmt) + uword64 op1; + uword64 op2; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + sim_fpu_div (&ans, &wop1, &wop2); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + sim_fpu_div (&ans, &wop1, &wop2); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 UNUSED +Recip(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop, op); + sim_fpu_inv (&ans, &wop); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop, op); + sim_fpu_inv (&ans, &wop); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +SquareRoot(op,fmt) + uword64 op; + FP_formats fmt; +{ + uword64 result = 0; + +#ifdef DEBUG + printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op)); +#endif /* DEBUG */ + + /* The registers must specify FPRs valid for operands of type + "fmt". If they are not valid, the result is undefined. */ + + /* The format type should already have been checked: */ + switch (fmt) { + case fmt_single: + { + sim_fpu wop; + sim_fpu ans; + unsigned32 res; + sim_fpu_32to (&wop, op); + sim_fpu_sqrt (&ans, &wop); + sim_fpu_to32 (&res, &ans); + result = res; + break; + } + case fmt_double: + { + sim_fpu wop; + sim_fpu ans; + unsigned64 res; + sim_fpu_64to (&wop, op); + sim_fpu_sqrt (&ans, &wop); + sim_fpu_to64 (&res, &ans); + result = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt)); +#endif /* DEBUG */ + + return(result); +} + +uword64 +convert(sd,cia,rm,op,from,to) + SIM_DESC sd; + address_word cia; + int rm; + uword64 op; + FP_formats from; + FP_formats to; +{ + sim_fpu wop; + sim_fpu_round round; + unsigned32 result32; + unsigned64 result64; + +#ifdef DEBUG + printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC)); +#endif /* DEBUG */ + + switch (rm) + { + case FP_RM_NEAREST: + /* Round result to nearest representable value. When two + representable values are equally near, round to the value + that has a least significant bit of zero (i.e. is even). */ + round = sim_fpu_round_near; + break; + case FP_RM_TOZERO: + /* Round result to the value closest to, and not greater in + magnitude than, the result. */ + round = sim_fpu_round_zero; + break; + case FP_RM_TOPINF: + /* Round result to the value closest to, and not less than, + the result. */ + round = sim_fpu_round_up; + break; + + case FP_RM_TOMINF: + /* Round result to the value closest to, and not greater than, + the result. */ + round = sim_fpu_round_down; + break; + default: + round = 0; + fprintf (stderr, "Bad switch\n"); + abort (); + } + + /* Convert the input to sim_fpu internal format */ + switch (from) + { + case fmt_double: + sim_fpu_64to (&wop, op); + break; + case fmt_single: + sim_fpu_32to (&wop, op); + break; + case fmt_word: + sim_fpu_i32to (&wop, op, round); + break; + case fmt_long: + sim_fpu_i64to (&wop, op, round); + break; + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + + /* Convert sim_fpu format into the output */ + /* The value WOP is converted to the destination format, rounding + using mode RM. When the destination is a fixed-point format, then + a source value of Infinity, NaN or one which would round to an + integer outside the fixed point range then an IEEE Invalid + Operation condition is raised. */ + switch (to) + { + case fmt_single: + sim_fpu_round_32 (&wop, round, 0); + sim_fpu_to32 (&result32, &wop); + result64 = result32; + break; + case fmt_double: + sim_fpu_round_64 (&wop, round, 0); + sim_fpu_to64 (&result64, &wop); + break; + case fmt_word: + sim_fpu_to32i (&result32, &wop, round); + result64 = result32; + break; + case fmt_long: + sim_fpu_to64i (&result64, &wop, round); + break; + default: + result64 = 0; + fprintf (stderr, "Bad switch\n"); + abort (); + } + +#ifdef DEBUG + printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to)); +#endif /* DEBUG */ + + return(result64); +} +#endif /* HASFPU */ + + +/*-- co-processor support routines ------------------------------------------*/ + +static int UNUSED +CoProcPresent(coproc_number) + unsigned int coproc_number; +{ + /* Return TRUE if simulator provides a model for the given co-processor number */ + return(0); +} + +void +cop_lw(sd,cia,coproc_num,coproc_reg,memword) + SIM_DESC sd; + address_word cia; + int coproc_num, coproc_reg; + unsigned int memword; +{ + switch (coproc_num) { +#if defined(HASFPU) + case 1: +#ifdef DEBUG + printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword)); +#endif + StoreFPR(coproc_reg,fmt_word,(uword64)memword); + FPR_STATE[coproc_reg] = fmt_uninterpreted; + break; +#endif /* HASFPU */ + + default: +#if 0 /* this should be controlled by a configuration option */ + sim_io_printf(sd,"COP_LW(%d,%d,0x%08X) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(cia)); +#endif + break; + } + + return; +} + +void +cop_ld(sd,cia,coproc_num,coproc_reg,memword) + SIM_DESC sd; + address_word cia; + int coproc_num, coproc_reg; + uword64 memword; +{ + switch (coproc_num) { +#if defined(HASFPU) + case 1: + StoreFPR(coproc_reg,fmt_uninterpreted,memword); + break; +#endif /* HASFPU */ + + default: +#if 0 /* this message should be controlled by a configuration option */ + sim_io_printf(sd,"COP_LD(%d,%d,0x%s) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(cia)); +#endif + break; + } + + return; +} + +unsigned int +cop_sw(sd,cia,coproc_num,coproc_reg) + SIM_DESC sd; + address_word cia; + int coproc_num, coproc_reg; +{ + unsigned int value = 0; + + switch (coproc_num) { +#if defined(HASFPU) + case 1: +#if 1 + { + FP_formats hold; + hold = FPR_STATE[coproc_reg]; + FPR_STATE[coproc_reg] = fmt_word; + value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted); + FPR_STATE[coproc_reg] = hold; + } +#else +#if 1 + value = (unsigned int)ValueFPR(coproc_reg,FPR_STATE[coproc_reg]); +#else +#ifdef DEBUG + printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(FPR_STATE[coproc_reg])); +#endif /* DEBUG */ + value = (unsigned int)ValueFPR(coproc_reg,fmt_single); +#endif +#endif + break; +#endif /* HASFPU */ + + default: +#if 0 /* should be controlled by configuration option */ + sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia)); +#endif + break; + } + + return(value); +} + +uword64 +cop_sd(sd,cia,coproc_num,coproc_reg) + SIM_DESC sd; + address_word cia; + int coproc_num, coproc_reg; +{ + uword64 value = 0; + switch (coproc_num) { +#if defined(HASFPU) + case 1: +#if 1 + value = ValueFPR(coproc_reg,fmt_uninterpreted); +#else +#if 1 + value = ValueFPR(coproc_reg,FPR_STATE[coproc_reg]); +#else +#ifdef DEBUG + printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(FPR_STATE[coproc_reg])); +#endif /* DEBUG */ + value = ValueFPR(coproc_reg,fmt_double); +#endif +#endif + break; +#endif /* HASFPU */ + + default: +#if 0 /* should be controlled by configuration option */ + sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia)); +#endif + break; + } + + return(value); +} + +void +decode_coproc(sd,cia,instruction) + SIM_DESC sd; + address_word cia; + unsigned int instruction; +{ + int coprocnum = ((instruction >> 26) & 3); + + switch (coprocnum) + { + case 0: /* standard CPU control and cache registers */ + { + int code = ((instruction >> 21) & 0x1F); + /* R4000 Users Manual (second edition) lists the following CP0 + instructions: + DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000) + DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000) + MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000) + MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000) + TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001) + TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010) + TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110) + TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000) + CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii) + ERET Exception return (VR4100 = 01000010000000000000000000011000) + */ + if (((code == 0x00) || (code == 0x04)) && ((instruction & 0x7FF) == 0)) + { + int rt = ((instruction >> 16) & 0x1F); + int rd = ((instruction >> 11) & 0x1F); + + switch (rd) /* NOTEs: Standard CP0 registers */ + { + /* 0 = Index R4000 VR4100 VR4300 */ + /* 1 = Random R4000 VR4100 VR4300 */ + /* 2 = EntryLo0 R4000 VR4100 VR4300 */ + /* 3 = EntryLo1 R4000 VR4100 VR4300 */ + /* 4 = Context R4000 VR4100 VR4300 */ + /* 5 = PageMask R4000 VR4100 VR4300 */ + /* 6 = Wired R4000 VR4100 VR4300 */ + /* 8 = BadVAddr R4000 VR4100 VR4300 */ + /* 9 = Count R4000 VR4100 VR4300 */ + /* 10 = EntryHi R4000 VR4100 VR4300 */ + /* 11 = Compare R4000 VR4100 VR4300 */ + /* 12 = SR R4000 VR4100 VR4300 */ + case 12: + if (code == 0x00) + GPR[rt] = SR; + else + SR = GPR[rt]; + break; + /* 13 = Cause R4000 VR4100 VR4300 */ + case 13: + if (code == 0x00) + GPR[rt] = CAUSE; + else + CAUSE = GPR[rt]; + break; + /* 14 = EPC R4000 VR4100 VR4300 */ + /* 15 = PRId R4000 VR4100 VR4300 */ +#ifdef SUBTARGET_R3900 + /* 16 = Debug */ + case 16: + if (code == 0x00) + GPR[rt] = Debug; + else + Debug = GPR[rt]; + break; +#else + /* 16 = Config R4000 VR4100 VR4300 */ + case 16: + if (code == 0x00) + GPR[rt] = C0_CONFIG; + else + C0_CONFIG = GPR[rt]; + break; +#endif +#ifdef SUBTARGET_R3900 + /* 17 = Debug */ + case 17: + if (code == 0x00) + GPR[rt] = DEPC; + else + DEPC = GPR[rt]; + break; +#else + /* 17 = LLAddr R4000 VR4100 VR4300 */ +#endif + /* 18 = WatchLo R4000 VR4100 VR4300 */ + /* 19 = WatchHi R4000 VR4100 VR4300 */ + /* 20 = XContext R4000 VR4100 VR4300 */ + /* 26 = PErr or ECC R4000 VR4100 VR4300 */ + /* 27 = CacheErr R4000 VR4100 */ + /* 28 = TagLo R4000 VR4100 VR4300 */ + /* 29 = TagHi R4000 VR4100 VR4300 */ + /* 30 = ErrorEPC R4000 VR4100 VR4300 */ + GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */ + /* CPR[0,rd] = GPR[rt]; */ + default: + if (code == 0x00) + sim_io_printf(sd,"Warning: MFC0 %d,%d ignored (architecture specific)\n",rt,rd); + else + sim_io_printf(sd,"Warning: MTC0 %d,%d ignored (architecture specific)\n",rt,rd); + } + } + else if (code == 0x10 && (instruction & 0x3f) == 0x18) + { + /* ERET */ + if (SR & status_ERL) + { + /* Oops, not yet available */ + sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet"); + PC = EPC; + SR &= ~status_ERL; + } + else + { + PC = EPC; + SR &= ~status_EXL; + } + } + else if (code == 0x10 && (instruction & 0x3f) == 0x10) + { + /* RFE */ + } + else if (code == 0x10 && (instruction & 0x3f) == 0x1F) + { + /* DERET */ + Debug &= ~Debug_DM; + DELAYSLOT(); + DSPC = DEPC; + } + else + sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia)); + /* TODO: When executing an ERET or RFE instruction we should + clear LLBIT, to ensure that any out-standing atomic + read/modify/write sequence fails. */ + } + break; + + case 2: /* undefined co-processor */ + sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia)); + break; + + case 1: /* should not occur (FPU co-processor) */ + case 3: /* should not occur (FPU co-processor) */ + SignalException(ReservedInstruction,instruction); + break; + } + + return; +} + +/*-- instruction simulation -------------------------------------------------*/ + +/* When the IGEN simulator is being built, the function below is be + replaced by a generated version. However, WITH_IGEN == 2 indicates + that the fubction below should be compiled but under a different + name (to allow backward compatibility) */ + +#if (WITH_IGEN != 1) +#if (WITH_IGEN > 1) +void old_engine_run PARAMS ((SIM_DESC sd, int next_cpu_nr, int siggnal)); +void +old_engine_run (sd, next_cpu_nr, siggnal) +#else +void +sim_engine_run (sd, next_cpu_nr, siggnal) +#endif + SIM_DESC sd; + int next_cpu_nr; /* ignore */ + int siggnal; /* ignore */ +{ +#if !defined(FASTSIM) + unsigned int pipeline_count = 1; +#endif + +#ifdef DEBUG + if (STATE_MEMORY (sd) == NULL) { + printf("DBG: simulate() entered with no memory\n"); + exit(1); + } +#endif /* DEBUG */ + +#if 0 /* Disabled to check that everything works OK */ + /* The VR4300 seems to sign-extend the PC on its first + access. However, this may just be because it is currently + configured in 32bit mode. However... */ + PC = SIGNEXTEND(PC,32); +#endif + + /* main controlling loop */ + while (1) { + /* vaddr is slowly being replaced with cia - current instruction + address */ + address_word cia = (uword64)PC; + address_word vaddr = cia; + address_word paddr; + int cca; + unsigned int instruction; /* uword64? what's this used for? FIXME! */ + +#ifdef DEBUG + { + printf("DBG: state = 0x%08X :",state); + if (state & simHALTEX) printf(" simHALTEX"); + if (state & simHALTIN) printf(" simHALTIN"); + printf("\n"); + } +#endif /* DEBUG */ + + DSSTATE = (STATE & simDELAYSLOT); +#ifdef DEBUG + if (dsstate) + sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC)); +#endif /* DEBUG */ + + /* Fetch the next instruction from the simulator memory: */ + if (AddressTranslation(cia,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) { + if ((vaddr & 1) == 0) { + /* Copy the action of the LW instruction */ + unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0); + unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0); + uword64 value; + unsigned int byte; + paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2))); + LoadMemory(&value,NULL,cca,AccessLength_WORD,paddr,vaddr,isINSTRUCTION,isREAL); + byte = ((vaddr & LOADDRMASK) ^ (bigend << 2)); + instruction = ((value >> (8 * byte)) & 0xFFFFFFFF); + } else { + /* Copy the action of the LH instruction */ + unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 1) : 0); + unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 1) : 0); + uword64 value; + unsigned int byte; + paddr = (((paddr & ~ (uword64) 1) & ~LOADDRMASK) + | (((paddr & ~ (uword64) 1) & LOADDRMASK) ^ (reverse << 1))); + LoadMemory(&value,NULL,cca, AccessLength_HALFWORD, + paddr & ~ (uword64) 1, + vaddr, isINSTRUCTION, isREAL); + byte = (((vaddr &~ (uword64) 1) & LOADDRMASK) ^ (bigend << 1)); + instruction = ((value >> (8 * byte)) & 0xFFFF); + } + } else { + fprintf(stderr,"Cannot translate address for PC = 0x%s failed\n",pr_addr(PC)); + exit(1); + } + +#ifdef DEBUG + sim_io_printf(sd,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction,pr_addr(PC)); +#endif /* DEBUG */ + + /* This is required by exception processing, to ensure that we can + cope with exceptions in the delay slots of branches that may + already have changed the PC. */ + if ((vaddr & 1) == 0) + PC += 4; /* increment ready for the next fetch */ + else + PC += 2; + /* NOTE: If we perform a delay slot change to the PC, this + increment is not requuired. However, it would make the + simulator more complicated to try and avoid this small hit. */ + + /* Currently this code provides a simple model. For more + complicated models we could perform exception status checks at + this point, and set the simSTOP state as required. This could + also include processing any hardware interrupts raised by any + I/O model attached to the simulator context. + + Support for "asynchronous" I/O events within the simulated world + could be providing by managing a counter, and calling a I/O + specific handler when a particular threshold is reached. On most + architectures a decrement and check for zero operation is + usually quicker than an increment and compare. However, the + process of managing a known value decrement to zero, is higher + than the cost of using an explicit value UINT_MAX into the + future. Which system is used will depend on how complicated the + I/O model is, and how much it is likely to affect the simulator + bandwidth. + + If events need to be scheduled further in the future than + UINT_MAX event ticks, then the I/O model should just provide its + own counter, triggered from the event system. */ + + /* MIPS pipeline ticks. To allow for future support where the + pipeline hit of individual instructions is known, this control + loop manages a "pipeline_count" variable. It is initialised to + 1 (one), and will only be changed by the simulator engine when + executing an instruction. If the engine does not have access to + pipeline cycle count information then all instructions will be + treated as using a single cycle. NOTE: A standard system is not + provided by the default simulator because different MIPS + architectures have different cycle counts for the same + instructions. + + [NOTE: pipeline_count has been replaced the event queue] */ + + /* shuffle the floating point status pipeline state */ + ENGINE_ISSUE_PREFIX_HOOK(); + +/* NOTE: For multi-context simulation environments the "instruction" + variable should be local to this routine. */ + +/* Shorthand accesses for engine. Note: If we wanted to use global + variables (and a single-threaded simulator engine), then we can + create the actual variables with these names. */ + + if (!(STATE & simSKIPNEXT)) { + /* Include the simulator engine */ +#include "oengine.c" +#if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT) +#error "Mismatch between run-time simulator code and simulation engine" +#endif +#if (WITH_TARGET_WORD_BITSIZE != GPRLEN) +#error "Mismatch between configure WITH_TARGET_WORD_BITSIZE and gencode GPRLEN" +#endif +#if ((WITH_FLOATING_POINT == HARD_FLOATING_POINT) != defined (HASFPU)) +#error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU" +#endif + +#if defined(WARN_LOHI) + /* Decrement the HI/LO validity ticks */ + if (HIACCESS > 0) + HIACCESS--; + if (LOACCESS > 0) + LOACCESS--; + /* start-sanitize-r5900 */ + if (HI1ACCESS > 0) + HI1ACCESS--; + if (LO1ACCESS > 0) + LO1ACCESS--; + /* end-sanitize-r5900 */ +#endif /* WARN_LOHI */ + + /* For certain MIPS architectures, GPR[0] is hardwired to zero. We + should check for it being changed. It is better doing it here, + than within the simulator, since it will help keep the simulator + small. */ + if (ZERO != 0) { +#if defined(WARN_ZERO) + sim_io_eprintf(sd,"The ZERO register has been updated with 0x%s (PC = 0x%s) (reset back to zero)\n",pr_addr(ZERO),pr_addr(cia)); +#endif /* WARN_ZERO */ + ZERO = 0; /* reset back to zero before next instruction */ + } + } else /* simSKIPNEXT check */ + STATE &= ~simSKIPNEXT; + + /* If the delay slot was active before the instruction is + executed, then update the PC to its new value: */ + if (DSSTATE) { +#ifdef DEBUG + printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC)); +#endif /* DEBUG */ + PC = DSPC; + CANCELDELAYSLOT(); + } + + if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */ + /* Deal with pending register updates: */ +#ifdef DEBUG + printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total); +#endif /* DEBUG */ + if (PENDING_OUT != PENDING_IN) { + int loop; + int index = PENDING_OUT; + int total = PENDING_TOTAL; + if (PENDING_TOTAL == 0) { + fprintf(stderr,"FATAL: Mis-match on pending update pointers\n"); + exit(1); + } + for (loop = 0; (loop < total); loop++) { +#ifdef DEBUG + printf("DBG: BEFORE index = %d, loop = %d\n",index,loop); +#endif /* DEBUG */ + if (PENDING_SLOT_REG[index] != (LAST_EMBED_REGNUM + 1)) { +#ifdef DEBUG + printf("pending_slot_count[%d] = %d\n",index,PENDING_SLOT_COUNT[index]); +#endif /* DEBUG */ + if (--(PENDING_SLOT_COUNT[index]) == 0) { +#ifdef DEBUG + printf("pending_slot_reg[%d] = %d\n",index,PENDING_SLOT_REG[index]); + printf("pending_slot_value[%d] = 0x%s\n",index,pr_addr(PENDING_SLOT_VALUE[index])); +#endif /* DEBUG */ + if (PENDING_SLOT_REG[index] == COCIDX) { +#if defined(HASFPU) + SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); +#else + ; +#endif + } else { + REGISTERS[PENDING_SLOT_REG[index]] = PENDING_SLOT_VALUE[index]; +#if defined(HASFPU) + /* The only time we have PENDING updates to FPU + registers, is when performing binary transfers. This + means we should update the register type field. */ + if ((PENDING_SLOT_REG[index] >= FGRIDX) && (PENDING_SLOT_REG[index] < (FGRIDX + 32))) + FPR_STATE[PENDING_SLOT_REG[index] - FGRIDX] = fmt_uninterpreted; +#endif /* HASFPU */ + } +#ifdef DEBUG + printf("registers[%d] = 0x%s\n",PENDING_SLOT_REG[index],pr_addr(REGISTERS[PENDING_SLOT_REG[index]])); +#endif /* DEBUG */ + PENDING_SLOT_REG[index] = (LAST_EMBED_REGNUM + 1); + PENDING_OUT++; + if (PENDING_OUT == PSLOTS) + PENDING_OUT = 0; + PENDING_TOTAL--; + } + } +#ifdef DEBUG + printf("DBG: AFTER index = %d, loop = %d\n",index,loop); +#endif /* DEBUG */ + index++; + if (index == PSLOTS) + index = 0; + } + } +#ifdef DEBUG + printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL); +#endif /* DEBUG */ + } + +#if !defined(FASTSIM) + if (sim_events_tickn (sd, pipeline_count)) + { + /* cpu->cia = cia; */ + sim_events_process (sd); + } +#else + if (sim_events_tick (sd)) + { + /* cpu->cia = cia; */ + sim_events_process (sd); + } +#endif /* FASTSIM */ + } +} +#endif + + +/* This code copied from gdb's utils.c. Would like to share this code, + but don't know of a common place where both could get to it. */ + +/* Temporary storage using circular buffer */ +#define NUMCELLS 16 +#define CELLSIZE 32 +static char* +get_cell() +{ + static char buf[NUMCELLS][CELLSIZE]; + static int cell=0; + if (++cell>=NUMCELLS) cell=0; + return buf[cell]; +} + +/* Print routines to handle variable size regs, etc */ + +/* Eliminate warning from compiler on 32-bit systems */ +static int thirty_two = 32; + +char* +pr_addr(addr) + SIM_ADDR addr; +{ + char *paddr_str=get_cell(); + switch (sizeof(addr)) + { + case 8: + sprintf(paddr_str,"%08lx%08lx", + (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); + break; + case 4: + sprintf(paddr_str,"%08lx",(unsigned long)addr); + break; + case 2: + sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff)); + break; + default: + sprintf(paddr_str,"%x",addr); + } + return paddr_str; +} + +char* +pr_uword64(addr) + uword64 addr; +{ + char *paddr_str=get_cell(); + sprintf(paddr_str,"%08lx%08lx", + (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); + return paddr_str; +} + + +/*---------------------------------------------------------------------------*/ +/*> EOF interp.c <*/ diff --git a/sim/txvu/m16.igen b/sim/txvu/m16.igen new file mode 100644 index 00000000000..7496ce1de28 --- /dev/null +++ b/sim/txvu/m16.igen @@ -0,0 +1,2692 @@ +// +// MIPS Architecture: +// +// CPU Instruction Set (mips16) +// + +// The instructions in this section are ordered according +// to http://www.sgi.com/MIPS/arch/MIPS16/mips16.pdf. + + +// FIXME: Instead of having the code for mips16 instructions here. +// these instructions should instead call the corresponding 32bit +// instruction (or a function implementing that instructions code). + + + +011101,26.INSTR_INDEX:NORMAL:32::JALX +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + unsigned_word op1 = (((instruction >> 0) & 0x03FFFFFF) << 2); + op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */ + { + int destreg = 31; + GPR[destreg] = (PC + 4); /* NOTE: The PC is already 4 ahead within the simulator */ + op1 ^= 1; + /* NOTE: ??? Gdb gets confused if the PC is sign-extended, + so we just truncate it to 32 bits here. */ + op1 = VL4_8(op1); + /* NOTE: The jump occurs AFTER the next instruction has been executed */ + DELAY_SLOT (op1); + /* JALDELAYSLOT(); FIXME */ + } +} + + +// Load and Store Instructions + + +10000,xxx,ddd,55555:RRI:16::LB +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 0; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_BYTE,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0x000000FF),8)); + } + } + } +} + + +10100,xxx,ddd,55555:RRI:16::LBU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 0; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_BYTE,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (((memval >> (8 * byte)) & 0x000000FF)); + } + } + } +} + + +10001,xxx,ddd,HHHHH:RRI:16::LH +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 1; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 1) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 1; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_HALFWORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0x0000FFFF),16)); + } + } + } +} + + +10101,xxx,ddd,HHHHH:RRI:16::LHU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 1; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 1) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 1; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_HALFWORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (((memval >> (8 * byte)) & 0x0000FFFF)); + } + } + } +} + + +10011,xxx,ddd,WWWWW:RRI:16::LW +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 2; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0xFFFFFFFF),32)); + } + } + } +} + + +10110,ddd,VVVVVVVV,P:RI:16::LWPC +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + int offset = (instruction >> 0) & 0xff; + signed_word op1 = ((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (unsigned64) 1) & ~ (unsigned64) 0x3; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 2; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0xFFFFFFFF),32)); + } + } + } +} + + +10010,ddd,VVVVVVVV,s:RI:16::LWSP +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + int offset = (instruction >> 0) & 0xff; + signed_word op1 = 29; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 2; + } + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0xFFFFFFFF),32)); + } + } + } +} + + +10111,xxx,ddd,WWWWW:RRI:16::LWU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 2; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (((memval >> (8 * byte)) & 0xFFFFFFFF)); + } + } + } +} + + +00111,xxx,ddd,DDDDD:RRI:16::LD +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 3; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 4; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = memval; + } + } + } +} + + +11111100,ddd,5.RD,P:RI64:16::LDPC +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + signed_word op1 = ((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (unsigned64) 1) & ~ (unsigned64) 0x7; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 3; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 4; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = memval; + } + } + } +} + + +11111000,ddd,5.RD,s:RI64:16::LDSP +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + signed_word op1 = 29; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 3; + } + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 4; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = memval; + } + } + } +} + + +11000,xxx,yyy,55555:RRI:16::SB +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 0; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + byte = ((vaddr & mask) ^ (bigend << shift)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_BYTE,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +11001,xxx,yyy,HHHHH:RRI:16::SH +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 1; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 1) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 1; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + byte = ((vaddr & mask) ^ (bigend << shift)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_HALFWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +11011,xxx,yyy,WWWWW:RRI:16::SW +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 2; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +11010,yyy,VVVVVVVV,s:RI:16::SWSP +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op2 = (instruction >> 8) & 0x7; + int offset = (instruction >> 0) & 0xff; + signed_word op1 = 29; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 2; + } + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +01100010,VVVVVVVV,Q,s:I8:16::SWRASP +*mips16: +{ + unsigned32 instruction = instruction_0; + int offset = (instruction >> 0) & 0xff; + signed_word op2 = 31; + signed_word op1 = 29; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 2; + } + op2 = GPR[op2]; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +01111,xxx,yyy,DDDDD:RRI:16::SD +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 3; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = op2; + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +11111001,yyy,5.RD,s:RI64:16::SDSP +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op2 = (instruction >> 5) & 0x7; + int offset = (instruction >> 0) & 0x1f; + signed_word op1 = 29; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 3; + } + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = op2; + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +11111010,CCCCCCCC,s,Q:I64:16::SDRASP +*mips16: +{ + unsigned32 instruction = instruction_0; + int offset = (instruction >> 0) & 0xff; + signed_word op1 = 29; + signed_word op2 = 31; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + offset <<= 3; + } + op1 = GPR[op1]; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = op2; + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +// ALU Immediate Instructions + + +01101,ddd,UUUUUUUU,Z:RI:16::LI +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + int op2 = (instruction >> 0) & 0xff; + signed_word op1 = 0; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + have_extendval = 0; + } + else + { + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if (destreg != 0) + GPR[destreg] = (op1 | op2); + } +} + + +01000,xxx,ddd,04444:RRI_A:16::ADDIU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int op2 = (instruction >> 0) & 0xf; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + op2 |= ((extendval & 0xf) << 11) | (extendval & 0x7f0); + if (op2 >= 0x4000) + op2 -= 0x8000; + have_extendval = 0; + } + else + { + if (op2 >= 0x8) + op2 -= 0x10; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 + op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +01001,www,kkkkkkkk:RI:16::ADDIU8 +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg; + int op2 = (instruction >> 0) & 0xff; + if (op1 < 2) + op1 += 16; + destreg = op1; + op1 = GPR[op1]; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + if (op2 >= 0x80) + op2 -= 0x100; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 + op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +01100011,KKKKKKKK,S:I8:16::ADJSP +*mips16: +{ + unsigned32 instruction = instruction_0; + int op2 = (instruction >> 0) & 0xff; + signed_word op1 = 29; + int destreg; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + if (op2 >= 0x80) + op2 -= 0x100; + op2 <<= 3; + } + destreg = op1; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 + op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +00001,ddd,AAAAAAAA,P:RI:16::ADDIUPC +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + int op2 = (instruction >> 0) & 0xff; + signed_word op1 = ((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (unsigned64) 1) & ~ (unsigned64) 0x3; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + op2 <<= 2; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 + op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +00000,ddd,AAAAAAAA,s:RI:16::ADDIUSP +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + int op2 = (instruction >> 0) & 0xff; + signed_word op1 = 29; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + op2 <<= 2; + } + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 + op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +01000,xxx,ddd,14444:RRI_A:16::DADDIU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = (instruction >> 5) & 0x7; + int op2 = (instruction >> 0) & 0xf; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + op2 |= ((extendval & 0xf) << 11) | (extendval & 0x7f0); + if (op2 >= 0x4000) + op2 -= 0x8000; + have_extendval = 0; + } + else + { + if (op2 >= 0x8) + op2 -= 0x10; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 temp = (unsigned64)(op1 + op2); + word64 tempS = (word64)temp; + GPR[destreg] = (unsigned64)temp; + } +} + + +11111101,www,jjjjj:RI64:16::DADDIU5 +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 5) & 0x7; + int destreg; + int op2 = (instruction >> 0) & 0x1f; + if (op1 < 2) + op1 += 16; + destreg = op1; + op1 = GPR[op1]; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + if (op2 >= 0x10) + op2 -= 0x20; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 temp = (unsigned64)(op1 + op2); + word64 tempS = (word64)temp; + GPR[destreg] = (unsigned64)temp; + } +} + + +11111011,KKKKKKKK,S:I64:16::DADJSP +*mips16: +{ + unsigned32 instruction = instruction_0; + int op2 = (instruction >> 0) & 0xff; + signed_word op1 = 29; + int destreg; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + if (op2 >= 0x80) + op2 -= 0x100; + op2 <<= 3; + } + destreg = op1; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 temp = (unsigned64)(op1 + op2); + word64 tempS = (word64)temp; + GPR[destreg] = (unsigned64)temp; + } +} + + +11111110,ddd,EEEEE,P:RI64:16::DADDIUPC +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 5) & 0x7; + int op2 = (instruction >> 0) & 0x1f; + signed_word op1 = ((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (unsigned64) 1) & ~ (unsigned64) 0x3; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + op2 <<= 2; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 temp = (unsigned64)(op1 + op2); + word64 tempS = (word64)temp; + GPR[destreg] = (unsigned64)temp; + } +} + + +11111111,ddd,EEEEE,s:RI64:16::DADDIUSP +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 5) & 0x7; + int op2 = (instruction >> 0) & 0x1f; + signed_word op1 = 29; + if (destreg < 2) + destreg += 16; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + op2 <<= 2; + } + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 temp = (unsigned64)(op1 + op2); + word64 tempS = (word64)temp; + GPR[destreg] = (unsigned64)temp; + } +} + + +01010,xxx,88888888,T:RI:16::SLTI +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int op2 = (instruction >> 0) & 0xff; + int destreg = 24; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if ((word64)op1 < (word64)op2) + GPR[destreg] = 1; + else + GPR[destreg] = 0; + } +} + + +01011,xxx,88888888,T:RI:16::SLTIU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int op2 = (instruction >> 0) & 0xff; + int destreg = 24; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (op2 >= 0x8000) + op2 -= 0x10000; + have_extendval = 0; + } + else + { + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if ((unsigned64)op1 < (unsigned64)op2) + GPR[destreg] = 1; + else + GPR[destreg] = 0; + } +} + + +11101,xxx,yyy,01010,T:RR:16::CMP +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg = 24; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = (op1 ^ op2); + } +} + + +01110,xxx,UUUUUUUU,T:RI:16::CMPI +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int op2 = (instruction >> 0) & 0xff; + int destreg = 24; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + { + op2 |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + have_extendval = 0; + } + else + { + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = (op1 ^ op2); + } +} + + +// Two/Three Operand, Register-Type + + +11100,xxx,yyy,ddd,01:RRR:16::ADDU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg = (instruction >> 2) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 + op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +11100,xxx,yyy,ddd,11:RRR:16::SUBU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg = (instruction >> 2) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 - op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +11100,xxx,yyy,ddd,00:RRR:16::DADDU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg = (instruction >> 2) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 temp = (unsigned64)(op1 + op2); + word64 tempS = (word64)temp; + GPR[destreg] = (unsigned64)temp; + } +} + + +11100,xxx,yyy,ddd,10:RRR:16::DSUBU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg = (instruction >> 2) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (destreg < 2) + destreg += 16; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 temp = (unsigned64)(op1 - op2); + word64 tempS = (word64)temp; + GPR[destreg] = (unsigned64)temp; + } +} + + +11101,xxx,yyy,00010,T:RR:16::SLT +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg = 24; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if ((word64)op1 < (word64)op2) + GPR[destreg] = 1; + else + GPR[destreg] = 0; + } +} + + +11101,xxx,yyy,00011,T:RR:16::SLTU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg = 24; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if ((unsigned64)op1 < (unsigned64)op2) + GPR[destreg] = 1; + else + GPR[destreg] = 0; + } +} + + +11101,ddd,yyy,01011,Z:RR:16::NEG +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + signed_word op1 = 0; + if (destreg < 2) + destreg += 16; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int temp = (unsigned int)(op1 - op2); + signed int tempS = (signed int)temp; + GPR[destreg] = SIGNEXTEND(((unsigned64)temp),32); + } +} + + +11101,www,yyy,01100:RR:16::AND +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + destreg = op1; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = (op1 & op2); + } +} + + +11101,www,yyy,01101:RR:16::OR +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + destreg = op1; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if (destreg != 0) + GPR[destreg] = (op1 | op2); + } +} + + +11101,www,yyy,01110:RR:16::XOR +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + destreg = op1; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = (op1 ^ op2); + } +} + + +11101,ddd,yyy,01111,Z:RR:16::NOT +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + signed_word op1 = 0; + if (destreg < 2) + destreg += 16; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if (destreg != 0) + GPR[destreg] = ~(op1 | op2); + } +} + + +01100111,ddd,XXXXX,z:I8_MOVR32:16::MOVR32 +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 5) & 0x7; + signed_word op1 = (instruction >> 0) & 0x1f; + signed_word op2 = 0; + if (destreg < 2) + destreg += 16; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if (destreg != 0) + GPR[destreg] = (op1 | op2); + } +} + + +01100101,YYYYY,xxx,z:I8_MOV32R:16::MOV32R +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 3) & 0x1f; + signed_word op1 = (instruction >> 0) & 0x7; + signed_word op2 = 0; + destreg = (destreg >> 2) | ((destreg & 3) << 3); + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + if (destreg != 0) + GPR[destreg] = (op1 | op2); + } +} + + +00110,ddd,yyy,sss,00:ISHIFT:16::SLL +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int op1 = (instruction >> 2) & 0x7; + if (destreg < 2) + destreg += 16; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + op1 = (extendval >> 6) & 0x1f; + have_extendval = 0; + } + else + { + if (op1 == 0) + op1 = 8; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = ((unsigned64)op2 << op1); + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } +} + + +00110,ddd,yyy,sss,10:ISHIFT:16::SRL +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int op1 = (instruction >> 2) & 0x7; + if (destreg < 2) + destreg += 16; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + op1 = (extendval >> 6) & 0x1f; + have_extendval = 0; + } + else + { + if (op1 == 0) + op1 = 8; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = ((unsigned64)(op2 & 0xFFFFFFFF) >> op1); + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } +} + + +00110,ddd,yyy,sss,11:ISHIFT:16::SRA +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int op1 = (instruction >> 2) & 0x7; + if (destreg < 2) + destreg += 16; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + op1 = (extendval >> 6) & 0x1f; + have_extendval = 0; + } + else + { + if (op1 == 0) + op1 = 8; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int highbit = (unsigned int)1 << 31; + GPR[destreg] = ((unsigned64)(op2 & 0xFFFFFFFF) >> op1); + GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((unsigned int)1 << op1) - 1) << (32 - op1)) : 0); + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } +} + + +11101,xxx,vvv,00100:RR:16::SLLV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + op1 &= 0x1F; + GPR[destreg] = ((unsigned64)op2 << op1); + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } +} + + +11101,xxx,vvv,00110:RR:16::SRLV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + op1 &= 0x1F; + GPR[destreg] = ((unsigned64)(op2 & 0xFFFFFFFF) >> op1); + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } +} + + +11101,xxx,vvv,00111:RR:16::SRAV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned int highbit = (unsigned int)1 << 31; + op1 &= 0x1F; + GPR[destreg] = ((unsigned64)(op2 & 0xFFFFFFFF) >> op1); + GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((unsigned int)1 << op1) - 1) << (32 - op1)) : 0); + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } +} + + +00110,ddd,yyy,[[[,01:ISHIFT:16::DSLL +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int op1 = (instruction >> 2) & 0x7; + if (destreg < 2) + destreg += 16; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + { + op1 = ((extendval >> 6) & 0x1f) | (extendval & 0x20); + have_extendval = 0; + } + else + { + if (op1 == 0) + op1 = 8; + } + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = ((unsigned64)op2 << op1); + } +} + + +11101,XXX,vvv,01000:RR:16::DSRL +*mips16: +{ + unsigned32 instruction = instruction_0; + int op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (have_extendval) + { + op1 = ((extendval >> 6) & 0x1f) | (extendval & 0x20); + have_extendval = 0; + } + else + { + if (op1 == 0) + op1 = 8; + } + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = ((unsigned64)(op2) >> op1); + } +} + + +11101,xxx,vvv,10011:RR:16::DSRA +*mips16: +{ + unsigned32 instruction = instruction_0; + int op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (have_extendval) + { + op1 = ((extendval >> 6) & 0x1f) | (extendval & 0x20); + have_extendval = 0; + } + else + { + if (op1 == 0) + op1 = 8; + } + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 highbit = (unsigned64)1 << 63; + GPR[destreg] = ((unsigned64)(op2) >> op1); + GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((unsigned64)1 << op1) - 1) << (64 - op1)) : 0); + } +} + + +11101,xxx,vvv,10100:RR:16::DSLLV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + op1 &= 0x3F; + GPR[destreg] = ((unsigned64)op2 << op1); + } +} + + +11101,xxx,vvv,10110:RR:16::DSRLV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + op1 &= 0x3F; + GPR[destreg] = ((unsigned64)(op2) >> op1); + } +} + + +11101,xxx,vvv,10111:RR:16::DSRAV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + int destreg; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + destreg = op2; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + unsigned64 highbit = (unsigned64)1 << 63; + op1 &= 0x3F; + GPR[destreg] = ((unsigned64)(op2) >> op1); + GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((unsigned64)1 << op1) - 1) << (64 - op1)) : 0); + } +} + + +// Multiply /Divide Instructions + + +11101,xxx,yyy,11000:RR:16::MULT +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Multiplication"); + { + unsigned64 temp = ((word64) op1 * (word64) op2); + LO = SIGNEXTEND((unsigned64)VL4_8(temp),32); + HI = SIGNEXTEND((unsigned64)VH4_8(temp),32); + } + } +} + + +11101,xxx,yyy,11001:RR:16::MULTU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Multiplication"); + { + unsigned64 temp = ((unsigned64)(op1 & 0xffffffff) * (unsigned64)(op2 & 0xffffffff)); + LO = SIGNEXTEND((unsigned64)VL4_8(temp),32); + HI = SIGNEXTEND((unsigned64)VH4_8(temp),32); + } + } +} + + +11101,xxx,yyy,11010:RR:16::DIV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Division"); + { + int d1 = op1; + int d2 = op2; + if (d2 == 0) + { + LO = SIGNEXTEND(0x80000000,32); + HI = SIGNEXTEND(0,32); + } + else if (d2 == -1 && d1 == 0x80000000) + { + LO = SIGNEXTEND(0x80000000,32); + HI = SIGNEXTEND(0,32); + } + else + { + LO = SIGNEXTEND((d1 / d2),32); + HI = SIGNEXTEND((d1 % d2),32); + } + } + } +} + + +11101,xxx,yyy,11011:RR:16::DIVU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Division"); + { + unsigned int d1 = op1; + unsigned int d2 = op2; + if (d2 == 0) + { + LO = SIGNEXTEND(0x80000000,32); + HI = SIGNEXTEND(0,32); + } + else if (d2 == -1 && d1 == 0x80000000) + { + LO = SIGNEXTEND(0x80000000,32); + HI = SIGNEXTEND(0,32); + } + else + { + LO = SIGNEXTEND((d1 / d2),32); + HI = SIGNEXTEND((d1 % d2),32); + } + } + } +} + + +11101,ddd,00010000:RR:16::MFHI +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + if (destreg < 2) + destreg += 16; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = HI; + HIACCESS = 3; /* 3rd instruction will be safe */ + } +} + + +11101,ddd,00010010:RR:16::MFLO +*mips16: +{ + unsigned32 instruction = instruction_0; + int destreg = (instruction >> 8) & 0x7; + if (destreg < 2) + destreg += 16; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = LO; + LOACCESS = 3; /* 3rd instruction will be safe */ + } +} + + +11101,xxx,yyy,11100:RR:16::DMULT +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Multiplication"); + { + unsigned64 mid; + unsigned64 midhi; + unsigned64 temp; + int sign = 0; + if (op1 < 0) { op1 = - op1; ++sign; } + if (op2 < 0) { op2 = - op2; ++sign; } + LO = ((unsigned64)VL4_8(op1) * VL4_8(op2)); + HI = ((unsigned64)VH4_8(op1) * VH4_8(op2)); + mid = ((unsigned64)VH4_8(op1) * VL4_8(op2)); + midhi = SET64HI(VL4_8(mid)); + temp = (LO + midhi); + if ((temp == midhi) ? (LO != 0) : (temp < midhi)) + HI += 1; + HI += VH4_8(mid); + mid = ((unsigned64)VL4_8(op1) * VH4_8(op2)); + midhi = SET64HI(VL4_8(mid)); + LO = (temp + midhi); + if ((LO == midhi) ? (temp != 0) : (LO < midhi)) + HI += 1; + HI += VH4_8(mid); + if (sign & 1) { LO = - LO; HI = (LO == 0 ? 0 : -1) - HI; } + } + } +} + + +11101,xxx,yyy,11101:RR:16::DMULTU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Multiplication"); + { + unsigned64 mid; + unsigned64 midhi; + unsigned64 temp; + LO = ((unsigned64)VL4_8(op1) * VL4_8(op2)); + HI = ((unsigned64)VH4_8(op1) * VH4_8(op2)); + mid = ((unsigned64)VH4_8(op1) * VL4_8(op2)); + midhi = SET64HI(VL4_8(mid)); + temp = (LO + midhi); + if ((temp == midhi) ? (LO != 0) : (temp < midhi)) + HI += 1; + HI += VH4_8(mid); + mid = ((unsigned64)VL4_8(op1) * VH4_8(op2)); + midhi = SET64HI(VL4_8(mid)); + LO = (temp + midhi); + if ((LO == midhi) ? (temp != 0) : (LO < midhi)) + HI += 1; + HI += VH4_8(mid); + } + } +} + + +11101,xxx,yyy,11110:RR:16::DDIV +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Division"); + { + word64 d1 = op1; + word64 d2 = op2; + if (d2 == 0) + { + LO = SIGNED64 (0x8000000000000000); + HI = 0; + } + else if (d2 == -1 && d1 == SIGNED64 (0x8000000000000000)) + { + LO = SIGNED64 (0x8000000000000000); + HI = 0; + } + else + { + LO = (d1 / d2); + HI = (d1 % d2); + } + } + } +} + + +11101,xxx,yyy,11111:RR:16::DDIVU +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + signed_word op2 = (instruction >> 5) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (op2 < 2) + op2 += 16; + op2 = GPR[op2]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + CHECKHILO("Division"); + { + unsigned64 d1 = op1; + unsigned64 d2 = op2; + if (d2 == 0) + { + LO = SIGNED64 (0x8000000000000000); + HI = 0; + } + else if (d2 == -1 && d1 == SIGNED64 (0x8000000000000000)) + { + LO = SIGNED64 (0x8000000000000000); + HI = 0; + } + else + { + LO = (d1 / d2); + HI = (d1 % d2); + } + } + } +} + + +// Jump and Branch Instructions + + +// JALX +// JAL +00011,aaaaaaaaaaa:I:16::JAL +*mips16: +{ + unsigned32 instruction = instruction_0; + unsigned_word op1 = (instruction >> 0) & 0x7ff; + { + address_word paddr; + int uncached; + if (AddressTranslation (PC &~ (unsigned64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL)) + { + unsigned64 memval; + unsigned int reverse = (ReverseEndian ? 3 : 0); + unsigned int bigend = (BigEndianCPU ? 3 : 0); + unsigned int byte; + paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1))); + LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL); + byte = (((PC &~ (unsigned64) 1) & 0x7) ^ (bigend << 1)); + memval = (memval >> (8 * byte)) & 0xffff; + op1 = (((op1 & 0x1f) << 23) + | ((op1 & 0x3e0) << 13) + | (memval << 2)); + if ((instruction & 0x400) == 0) + op1 |= 1; + PC += 2; + } + } + op1 |= PC & ~ (unsigned64) 0x0fffffff; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + int destreg = 31; + GPR[destreg] = (PC + 2); /* NOTE: The PC is already 2 ahead within the simulator */ + /* NOTE: ??? Gdb gets confused if the PC is sign-extended, + so we just truncate it to 32 bits here. */ + op1 = VL4_8(op1); + /* NOTE: The jump occurs AFTER the next instruction has been executed */ + DELAY_SLOT op1; + JALDELAYSLOT(); + } +} + + +11101,xxx,00000000:RR:16::JR +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + /* NOTE: ??? Gdb gets confused if the PC is sign-extended, + so we just truncate it to 32 bits here. */ + op1 = VL4_8(op1); + /* NOTE: The jump occurs AFTER the next instruction has been executed */ + DELAY_SLOT op1; + DELAYSLOT(); + } +} + + +1110100000100000,r:RR:16::JRRA +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = 31; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + /* NOTE: ??? Gdb gets confused if the PC is sign-extended, + so we just truncate it to 32 bits here. */ + op1 = VL4_8(op1); + /* NOTE: The jump occurs AFTER the next instruction has been executed */ + DELAY_SLOT op1; + DELAYSLOT(); + } +} + + +11101,xxx,01000000,R:RR:16::JALR +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int destreg = 31; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + GPR[destreg] = (PC + 2); /* NOTE: The PC is already 2 ahead within the simulator */ + /* NOTE: ??? Gdb gets confused if the PC is sign-extended, + so we just truncate it to 32 bits here. */ + op1 = VL4_8(op1); + /* NOTE: The jump occurs AFTER the next instruction has been executed */ + DELAY_SLOT op1; + DELAYSLOT(); + } +} + + +00100,xxx,pppppppp,z:RI:16::BEQZ +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int offset = (instruction >> 0) & 0xff; + signed_word op2 = 0; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + if (offset >= 0x80) + offset -= 0x100; + } + offset *= 2; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + int condition = (op1 == op2); + if (condition) + PC = PC + offset; + } +} + + +00101,xxx,pppppppp,z:RI:16::BNEZ +*mips16: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = (instruction >> 8) & 0x7; + int offset = (instruction >> 0) & 0xff; + signed_word op2 = 0; + if (op1 < 2) + op1 += 16; + op1 = GPR[op1]; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + if (offset >= 0x80) + offset -= 0x100; + } + offset *= 2; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + int condition = (op1 != op2); + if (condition) + PC = PC + offset; + } +} + + +01100000,pppppppp,t,z:I8:16::BTEQZ +*mips16: +{ + unsigned32 instruction = instruction_0; + int offset = (instruction >> 0) & 0xff; + signed_word op1 = 24; + signed_word op2 = 0; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + if (offset >= 0x80) + offset -= 0x100; + } + offset *= 2; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + int condition = (op1 == op2); + if (condition) + PC = PC + offset; + } +} + + +01100001,pppppppp,t,z:I8:16::BTNEZ +*mips16: +{ + unsigned32 instruction = instruction_0; + int offset = (instruction >> 0) & 0xff; + signed_word op1 = 24; + signed_word op2 = 0; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + if (offset >= 0x80) + offset -= 0x100; + } + offset *= 2; + op1 = GPR[op1]; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + int condition = (op1 != op2); + if (condition) + PC = PC + offset; + } +} + + +00010,qqqqqqqqqqq,z,Z:I:16::B +*mips16: +{ + unsigned32 instruction = instruction_0; + int offset = (instruction >> 0) & 0x7ff; + signed_word op2 = 0; + signed_word op1 = 0; + if (have_extendval) + { + offset |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0); + if (offset >= 0x8000) + offset -= 0x10000; + have_extendval = 0; + } + else + { + if (offset >= 0x400) + offset -= 0x800; + } + offset *= 2; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + int condition = (op1 == op2); + if (condition) + PC = PC + offset; + } +} + + +// Special Instructions + + +// See the front of the mips16 doc +11110,eeeeeeeeeee:I:16::EXTEND +*mips16: +{ + unsigned32 instruction = instruction_0; + int ext = (instruction >> 0) & 0x7ff; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + extendval = ext; + have_extendval = 1; + } +} + + +01100,******,00101:RR:16::BREAK +*mips16: +{ + unsigned32 instruction = instruction_0; + if (have_extendval) + SignalException (ReservedInstruction, instruction); + { + SignalException(BreakPoint,instruction); + } +} + diff --git a/sim/txvu/mdmx.igen b/sim/txvu/mdmx.igen new file mode 100644 index 00000000000..b77f5eef60e --- /dev/null +++ b/sim/txvu/mdmx.igen @@ -0,0 +1,1298 @@ +// Media Instructions +// ------------------ + +// Ref: http://www.sgi.com/MIPS/arch/ISA5/MDMXspec.pdf + +// Note: For OB instructions, the sel field is deduced by special +// handling of the "vt" operand. +// If vt is: +// of the form $vt[0], then sel is 0000 +// of the form $vt[1], then sel is 0001 +// of the form $vt[2], then sel is 0010 +// of the form $vt[3], then sel is 0011 +// of the form $vt[4], then sel is 0100 +// of the form $vt[5], then sel is 0101 +// of the form $vt[6], then sel is 0110 +// of the form $vt[7], then sel is 0111 +// Normal register specifier, then sel is 1011 +// Constant, then sel is 1111 +// +// VecAcc is the Vector Accumulator. +// This accumulator is organized as 8X24 bit (192 bit) register. +// This accumulator holds only signed values. + + +// Verify that the instruction is valid for the curent Architecture +// If valid, return the scale (log nr bits) of a vector element +// as determined by SEL. + +:function:::int:get_scale:int sel +{ +#if 0 + switch (my_index X STATE_ARCHITECTURE) + { + } +#endif + switch (sel & 0x7) + { + case 0: + case 2: + case 4: + case 6: + /* octal byte - ssss0 */ + return 0; + case 1: + case 5: + /* quad halfword - sss01 */ + return 1; + case 3: + /* bi word - ss011 */ + semantic_illegal (sd, cia); + return 2; + case 7: + /* long - ss111 */ + semantic_illegal (sd, cia); + return 3; + default: + abort (); + return -1; + } +} + + +// Fetch/Store VALUE in ELEMENT of vector register FPR. +// The the of the element determined by SCALE. + +:function:::signed:value_vr:int scale, int fpr, int el +{ + switch (FPR_STATE[fpr]) + { + case fmt_uninterpreted: + FPR_STATE[fpr] = fmt_long; + break; + case fmt_long: + case fmt_unknown: + break; + default: + sim_io_eprintf(sd, "Vector %d format invalid (PC = 0x%08lx)\n", + fpr, (long) cia); + FPR_STATE[fpr] = fmt_unknown; + } + switch (scale) + { + case 0: + { + signed8 value = *A1_8 (&FGR[fpr], 7 - el); + return value; + } + case 1: + { + signed16 value = *A2_8 (&FGR[fpr], 3 - el); + return value; + } + default: + abort; + } + return 0; +} + +:function:::void:store_vr:int scale, int fpr, int element, signed value +{ + switch (FPR_STATE[fpr]) + { + case fmt_uninterpreted: + FPR_STATE[fpr] = fmt_long; + break; + case fmt_long: + case fmt_unknown: + break; + default: + sim_io_eprintf(sd, "Vector %d format invalid (PC = 0x%08lx)\n", + fpr, (long) cia); + FPR_STATE[fpr] = fmt_unknown; + } + switch (scale) + { + case 0: + { + *A1_8 (&FGR[fpr], 7 - element) = value; + break; + } + case 1: + { + *A2_8 (&FGR[fpr], 3 - element) = value; + break; + } + default: + abort (); + } +} + + +// Select a value from onr of FGR[VT][ELEMENT], VT and GFR[VT][CONST] +// according to SEL + +:function:::unsigned:select_vr:int sel, int vt, int element +{ + switch (sel) + { + /* element select - 0xxxx */ + case 0x00: /* 0 xxx 0 */ + case 0x02: + case 0x04: + case 0x06: + case 0x08: + case 0x0a: + case 0x0c: + case 0x0e: + return value_vr (SD_, 0, vt, sel >> 1); + case 0x01: /* 0 xx 01 */ + case 0x05: + case 0x09: + case 0x0d: + return value_vr (SD_, 1, vt, sel >> 2); + case 0x03: /* 0 x 011 */ + case 0x0b: + return value_vr (SD_, 2, vt, sel >> 3); + case 0x07: /* 0 x 111 */ + case 0x0f: + return value_vr (SD_, 3, vt, sel >> 4); + + /* select vector - 10xxx */ + case 0x16: /* 10 11 0 */ + return value_vr (SD_, 0, vt, element); + case 0x15: /* 10 1 01 */ + return value_vr (SD_, 1, vt, element); + case 0x13: /* 10 011 */ + return value_vr (SD_, 2, vt, element); + case 0x17: /* 10 111 */ + return value_vr (SD_, 3, vt, element); + + /* select immediate - 11xxx */ + case 0x1e: /* 11 11 0 */ + case 0x1d: /* 11 1 01 */ + case 0x1b: /* 11 011 */ + case 0x1f: /* 11 111 */ + return vt; + + } + return 0; +} + + +// Saturate (clamp) the signed value to (8 << SCALE) bits. + +:function:::signed:Clamp:int scale, signed value +{ + switch (scale) + { + case 0: + { + if (value != (signed8) value) + { + if (value > 0) + return 0x7f; + else + return 0x80; + } + return value & 0xff; + } + case 1: + { + if (value != (signed16) value) + { + if (value > 0) + return 0x7fff; + else + return 0x8000; + } + return value & 0xffff; + } + default: + abort (); + return 0; + } +} + + +// Access a single bit of the floating point CC register. + +:function:::void:store_cc:int i, int value +{ + SETFCC (i, value); +} + +:function:::int:value_cc:int i +{ + return GETFCC (i); +} + + +// Read/write the accumulator + +:function:::signed64:value_acc:int scale, int element +{ + signed64 value = 0; + switch (scale) + { + case 0: + value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 0]; + value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 1] << 8; + value |= (signed64) (signed8) CPU->acc [element * 3 + 2] << 16; + break; + case 1: + value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 0]; + value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 1] << 8; + value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 2] << 16; + value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 3] << 24; + value |= (unsigned64) (unsigned8) CPU->acc [element * 3 + 4] << 32; + value |= (signed64) (signed8) CPU->acc [element * 3 + 5] << 40; + break; + } + return value; +} + +:function:::void:store_acc:int scale, int element, signed64 value +{ + switch (scale) + { + case 0: + CPU->acc [element * 3 + 0] = value >> 0; + CPU->acc [element * 3 + 1] = value >> 8; + CPU->acc [element * 3 + 2] = value >> 16; + break; + case 1: + CPU->acc [element * 3 + 0] = value >> 0; + CPU->acc [element * 3 + 1] = value >> 8; + CPU->acc [element * 3 + 2] = value >> 16; + CPU->acc [element * 3 + 3] = value >> 24; + CPU->acc [element * 3 + 4] = value >> 32; + CPU->acc [element * 3 + 5] = value >> 40; + break; + } +} + + +// Formatting + +:%s::::VT:int sel, int vt +{ + static char buf[20]; + if (sel < 8) + sprintf (buf, "v%d[%d]", vt, sel); + else if (sel == 0x13) + sprintf (buf, "v%d", vt); + else if (sel == 0x1f) + sprintf (buf, "%d", vt); + else + sprintf (buf, "(invalid)"); + return buf; +} + +:%s::::SEL:int sel +{ + switch (sel & 7) + { + case 0: + case 2: + case 4: + case 6: + return "ob"; + case 1: + case 5: + return "qh"; + case 3: + return "bw"; + default: + return "l"; + } +} + + +// Vector Add. + +010010,5.SEL,5.VT,5.VS,5.VD,001011::::ADD.fmt +"add.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + Clamp (SD_, scale, + (value_vr (SD_, scale, VS, i) + + select_vr (SD_, SEL, VT, i)))); +} + + +// Accumulate Vector Add + +010010,5.SEL,5.VT,5.VS,1,0000,110111::::ADDA.fmt +"adda.%s v, v" +*mdmx: +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + (value_acc (SD_, scale, i) + + (signed64) value_vr (SD_, scale, VS, i) + + (signed64) select_vr (SD_, SEL, VT, i))); +} + + +// Load Vector Add + +010010,5.SEL,5.VT,5.VS,0,0000,110111::::ADDA.fmt +"addl.%s v, v" +*mdmx: +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + ((signed64) value_vr (SD_, scale, VS, i) + + (signed64) select_vr (SD_, SEL, VT, i))); +} + + + +// Vector align, Constant Alignment + +:function:::void:ByteAlign:int vd, int imm, int vs, int vt +{ + int s = imm * 8; + unsigned64 rs = value_fpr (sd, cia, vs, fmt_long); + unsigned64 rt = value_fpr (sd, cia, vt, fmt_long); + unsigned64 rd; + if (BigEndianCPU) + { + /* (vs || vt) [127 - S .. 64 - S] */ + if (s == 0) + rd = rs; + else + rd = (MOVED64 (rs, 64 - s, 0, 63, s) + | EXTRACTED64 (rt, 63, 64 - s)); + } + else + { + /* (vs || vt) [63 + S .. S] */ + if (s == 0) + rd = rt; + else + rd = (MOVED64 (rs, s, 0, 63, 64 - s) + | EXTRACTED64 (rt, 63, s)); + } + store_fpr (sd, cia, vd, rd, fmt_long); +} + +010010,00,3.IMM,5.VT,5.VS,5.VD,0110,X,0::::ALNI.fmt +"alni.%s v, v, v, " +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + ByteAlign (SD_, VD, IMM, VS, VT); +} + + + +// Vector align, Variable Alignment + +010010,5.RS,5.VT,5.VS,5.VD,0110,X,1::::ALNV.fmt +"alnv.%s v, v, v, r" +*mdmx: +{ + ByteAlign (SD_, VD, GPR[RS], VS, VT); +} + + + +// Vector And. + +010010,5.SEL,5.VT,5.VS,5.VD,001100::::AND.fmt +"and.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_vr (SD_, scale, VS, i) + & select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Compare Equal. + + +010010,5.SEL,5.VT,5.VS,00000,000001::::C.EQ.fmt +"c.EQ.%s v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_cc (SD_, i, + (value_vr (SD_, scale, VS, i) + == select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Compare Less Than or Equal. + +010010,5.SEL,5.VT,5.VS,00000,000101::::C.LE.fmt +"c.le.%s v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_cc (SD_, i, + (value_vr (SD_, scale, VS, i) + <= select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Compare Less Than. + +010010,5.SEL,5.VT,5.VS,00000,000100::::C.LT.fmt +"c.lt.%s v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_cc (SD_, i, + (value_vr (SD_, scale, VS, i) + < select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Maximum. + +:function:::signed:Max:int scale, signed l, signed r +{ + if (l < r) + return r; + else + return l; +} + +010010,5.SEL,5.VT,5.VS,5.VD,000111::::MAX.fmt +"max.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + Max (SD_, scale, + value_vr (SD_, scale, VS, i), + select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Minimum. + +:function:::signed:Min:int scale, signed l, signed r +{ + if (l < r) + return l; + else + return r; +} + +010010,5.SEL,5.VT,5.VS,5.VD,000110::::MIN.fmt +"min.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + Min (SD_, scale, + value_vr (SD_, scale, VS, i), + select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Sign. + +:function:::signed:Sign:int scale, signed l, signed r +{ + if (l >= 0) + return r; + else if (r >= 0) + return -r; + else + { + /* watch for overflow of MIN_INT */ + switch (scale) + { + case 0: + if ((r & 0xff) == 0x80) + return 0x7ff; + else + return -r; + case 1: + if ((r & 0xffff) == 0x8000) + return 0x7ffff; + else + return -r; + default: + abort (); + } + return -r; + } +} + +010010,5.SEL,5.VT,5.VS,5.VD,000110::::MSGN.fmt +"msgn.%s v, v, %s" +*mdmx: +{ + int i; + int scale = get_scale (SD_, SEL); + if ((SEL & 1) != 1) + /* only QH allowed */ + semantic_illegal (sd, cia); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + Sign (SD_, scale, + value_vr (SD_, scale, VS, i), + select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Multiply. + +010010,5.SEL,5.VT,5.VS,5.VD,110000::::MUL.fmt +"mul.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + Clamp (SD_, scale, + (value_vr (SD_, scale, VS, i) + * select_vr (SD_, SEL, VT, i)))); +} + + + +// Accumulate Vector Multiply + +010010,5.SEL,5.VT,5.VS,00000,110011::::MULA.fmt +"mula.%s v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + (value_acc (SD_, scale, i) + + ((signed64) value_vr (SD_, scale, VS, i) + * (signed64) select_vr (SD_, SEL, VT, i)))); +} + + + +// Add Vector Multiply to Accumulator. + +010010,5.SEL,5.VT,5.VS,10000,110011::::MULL.fmt +"mull.%s v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + ((signed64) value_vr (SD_, scale, VS, i) + * (signed64) select_vr (SD_, SEL, VT, i))); +} + + + +// Subtract Vector Multiply from Accumulator + +010010,5.SEL,5.VT,5.VS,00000,110010::::MULS.fmt +"muls.%s v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + (value_acc (SD_, scale, i) + - ((signed64) value_vr (SD_, scale, VS, i) + * (signed64) select_vr (SD_, SEL, VT, i)))); +} + + + +// Load Negative Vector Multiply + +010010,5.SEL,5.VT,5.VS,10000,110010::::MULSL.fmt +"mulsl.%s v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + - ((signed64) value_vr (SD_, scale, VS, i) + * (signed64) select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Nor. + +010010,5.SEL,5.VT,5.VS,5.VD,001111::::NOR.fmt +"nor.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + ~(value_vr (SD_, scale, VS, i) + | select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Or. + +010010,5.SEL,5.VT,5.VS,5.VD,001110::::OR.fmt +"or.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_vr (SD_, scale, VS, i) + | select_vr (SD_, SEL, VT, i))); +} + + + +// Select Vector Elements - False + +010010,5.SEL,5.VT,5.VS,5.VD,000010::::PICKF.fmt +"pickf.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_cc (SD_, i) == 0 + ? value_vr (SD_, scale, VS, i) + : select_vr (SD_, SEL, VT, i))); +} + + + +// Select Vector Elements - True + +010010,5.SEL,5.VT,5.VS,5.VD,000011::::PICKT.fmt +"pickt.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_cc (SD_, i) != 0 + ? value_vr (SD_, scale, VS, i) + : select_vr (SD_, SEL, VT, i))); +} + + + +// Scale, Round and Clamp Accumulator + +:%s::::RND:int rnd +{ + switch (rnd) + { + case 0: + return "zu"; + case 1: + return "nau"; + case 2: + return "neu"; + case 4: + return "rzs"; + case 5: + return "nas"; + case 6: + return "nes"; + default: + return "(invalid)"; + } +} + +:function:::signed:ScaleRoundClamp:int scale, int rnd, signed val, signed shift +{ + int halfway = (1 << (shift - 1)); + /* must be positive */ + if (shift < 0) + return 0; + /* too much shift? */ + switch (scale) + { + case 0: + if (shift >= 24) + return 0; + break; + case 1: + if (shift >= 48) + return 0; + break; + default: + abort (); + } + /* round */ + switch (rnd & 3) + { + case 0: /* round towards zero */ + break; + case 1: /* nearest, halfaway rounds away from zero */ + if (val >= 0) + val += halfway; + else + val -= halfway; + break; + case 2: /* nearest, halfway rounds to even! */ + if (val >= 0) + { + if (val & (halfway << 1)) + val += halfway; + else + val += (halfway - 1); + } + else + { + if (val & (halfway << 1)) + val -= halfway; + else + val -= (halfway - 1); + } + default: + abort (); + } + /* shift */ + val >>= shift; + /* clamp */ + switch (rnd & 4) + { + case 0: + /* unsigned clamp */ + if (val < 0) + val = 0; + else + switch (scale) + { + case 0: + if (val > 0xff) + val = 0xff; + break; + case 1: + if (val > 0xffff) + val = 0xffff; + break; + } + break; + case 8: + /* normal signed clamp */ + val = Clamp (_SD, scale, val); + break; + } + return val; +} + +010010,5.SEL,5.VT,00000,5.VD,100,3.RND::::Rx.fmt +"r%s.%s v, v" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + ScaleRoundClamp (SD_, scale, RND, + value_acc (SD_, scale, i), + select_vr (SD_, SEL, VT, i))); +} + + + +// Vector Read Accumulator Low. + +010010,0000,1.SEL,00000,00000,5.VD,111111::::RACL.fmt +"racl.%s v" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + EXTRACTED (value_acc (SD_, scale, i), + (8 << scale) - 1, + 0)); +} + + + +// Vector Read Accumulator Middle. + +010010,0100,1.SEL,00000,00000,5.VD,111111::::RACM.fmt +"racm.%s v" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + EXTRACTED (value_acc (SD_, scale, i), + (16 << scale) - 1, + (8 << scale) - 0)); +} + + + +// Vector Read Accumulator High. + +010010,1000,1.SEL,00000,00000,5.VD,111111::::RACH.fmt +"rach.%s v" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + EXTRACTED (value_acc (SD_, scale, i), + (24 << scale) - 1, + (16 << scale) - 0)); +} + + + +// Vector Element Shuffle. + +010010,0000,0,5.VT,5.VS,5.VD,011111::::SHFL.UPUH.fmt +"shfl.upuh.%s v, v, " +*mdmx: +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < 4; i++) + { + store_vr (SD_, 1, VD, i, + value_vr (SD_, 0, VS, i + 4) & 0xff); + } +} + +010010,0001,0,5.VT,5.VS,5.VD,011111::::SHFL.UPUL.fmt +"shfl.upul.%s v, v, " +*mdmx: +{ + int i; + for (i = 0; i < 4; i++) + { + store_vr (SD_, 1, VD, i, + value_vr (SD_, 0, VS, i) & 0xff); + } +} + +010010,0000,0,5.VT,5.VS,5.VD,011111::::SHFL.UPSH.fmt +"shfl.upsh.%s v, v, " +*mdmx: +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < 4; i++) + { + store_vr (SD_, 1, VD, i, + value_vr (SD_, 0, VS, i + 4)); + } +} + +010010,0001,0,5.VT,5.VS,5.VD,011111::::SHFL.UPSL.fmt +"shfl.upsl.%s v, v, " +*mdmx: +{ + int i; + for (i = 0; i < 4; i++) + { + store_vr (SD_, 1, VD, i, + value_vr (SD_, 0, VS, i)); + } +} + +010010,0100,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.PACH.fmt +"shfl.pach.%s v, v, " +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (4 >> scale); i++) + { + store_vr (SD_, scale, VD, i, + value_vr (SD_, scale, VT, i * 2 + 1)); + store_vr (SD_, scale, VD, 1 + (4 >> scale), + value_vr (SD_, scale, VS, i * 2 + 1)); + } +} + +010010,0101,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.PACL.fmt +"shfl.pacl.%s v, v, " +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (4 >> scale); i++) + { + store_vr (SD_, scale, VD, i, + value_vr (SD_, scale, VT, i * 2)); + store_vr (SD_, scale, VD, 1 + (4 >> scale), + value_vr (SD_, scale, VS, i * 2)); + } +} + +010010,0110,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.MIXH.fmt +"shfl.mixh.%s v, v, " +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (4 >> scale); i++) + { + store_vr (SD_, scale, VD, i * 2, + value_vr (SD_, scale, VT, i + (4 >> scale))); + store_vr (SD_, scale, VD, i * 2 + 1, + value_vr (SD_, scale, VS, i + (4 >> scale))); + } +} + +010010,0111,1.SEL,5.VT,5.VS,5.VD,011111::::SHFL.MIXL.fmt +"shfl.mixl.%s v, v, " +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (4 >> scale); i++) + { + store_vr (SD_, scale, VD, i * 2, + value_vr (SD_, scale, VT, i)); + store_vr (SD_, scale, VD, i * 2 + 1, + value_vr (SD_, scale, VS, i)); + } +} + +010010,100,01,5.VT,5.VS,5.VD,011111::::SHFL.BFLA.fmt +"shfl.bfla.qh v, v, " +*mdmx: +{ + store_vr (SD_, 1, VD, 0, + value_vr (SD_, 1, VT, 1)); + store_vr (SD_, 1, VD, 1, + value_vr (SD_, 1, VS, 0)); + store_vr (SD_, 1, VD, 2, + value_vr (SD_, 1, VT, 3)); + store_vr (SD_, 1, VD, 3, + value_vr (SD_, 1, VS, 2)); +} + +010010,101,01,5.VT,5.VS,5.VD,011111::::SHFL.BFLB.fmt +"shfl.bflb.qh v, v, " +*mdmx: +{ + store_vr (SD_, 1, VD, 0, + value_vr (SD_, 1, VT, 3)); + store_vr (SD_, 1, VD, 1, + value_vr (SD_, 1, VS, 2)); + store_vr (SD_, 1, VD, 2, + value_vr (SD_, 1, VT, 1)); + store_vr (SD_, 1, VD, 3, + value_vr (SD_, 1, VS, 0)); +} + +010010,101,01,5.VT,5.VS,5.VD,011111::::SHFL.REPA.fmt +"shfl.repa.qh v, v, " +*mdmx: +{ + store_vr (SD_, 1, VD, 0, + value_vr (SD_, 1, VT, 2)); + store_vr (SD_, 1, VD, 1, + value_vr (SD_, 1, VT, 3)); + store_vr (SD_, 1, VD, 2, + value_vr (SD_, 1, VS, 2)); + store_vr (SD_, 1, VD, 3, + value_vr (SD_, 1, VS, 3)); +} + +010010,101,01,5.VT,5.VS,5.VD,011111::::SHFL.REPB.fmt +"shfl.repb.qh v, v, " +*mdmx: +{ + store_vr (SD_, 1, VD, 0, + value_vr (SD_, 1, VT, 0)); + store_vr (SD_, 1, VD, 1, + value_vr (SD_, 1, VT, 1)); + store_vr (SD_, 1, VD, 2, + value_vr (SD_, 1, VS, 0)); + store_vr (SD_, 1, VD, 3, + value_vr (SD_, 1, VS, 1)); +} + + + +// Vector Shift Left Logical + +010010,5.SEL,5.VT,5.VS,5.VD,010000::::SLL.fmt +"sll.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + int mask = (4 << scale) - 1; + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_vr (SD_, scale, VS, i) + << (select_vr (SD_, SEL, VT, i) & mask))); +} + + + +// Vector Shift Right Arithmetic + +010010,5.SEL,5.VT,5.VS,5.VD,010011::::SRA.fmt +"sra.%s v, v, %s" +*mdmx: +{ + int i; + int mask = (4 << scale) - 1; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_vr (SD_, scale, VS, i) + >> (select_vr (SD_, SEL, VT, i) & mask))); +} + + + +// Vector Shift Right Logical. + +010010,5.SEL,5.VT,5.VS,5.VD,010010::::SRL.fmt +"srl.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + int mask = (4 << scale) - 1; + int zeros = (1 << (8 << scale)) - 1; + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + ((value_vr (SD_, scale, VS, i) & zeros) + >> (select_vr (SD_, SEL, VT, i) & mask))); +} + + + +// Vector Subtract. + +010010,5.SEL,5.VT,5.VS,5.VD,001010::::SUB.fmt +"sub.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_vr (SD_, scale, VS, i) + - select_vr (SD_, SEL, VT, i))); +} + + + +// Accumulate Vector Difference + +010010,5.SEL,5.VT,5.VS,0,0000,110110::::SUBA.fmt +"suba.%s v, v, %s" +*mdmx: +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, VD, i, + (value_acc (SD, scale, i) + + (signed64) value_vr (SD_, scale, VS, i) + - (signed64) select_vr (SD_, SEL, VT, i))); +} + + + +// Load Vector Difference + +010010,5.SEL,5.VT,5.VS,1,0000,110110::::SUBL.fmt +"subl.%s v, v, %s" +*mdmx: +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, VD, i, + ((signed64) value_vr (SD_, scale, VS, i) + - (signed64) select_vr (SD_, SEL, VT, i))); +} + + + +// Write Accumulator High. + +010010,1000,1.SEL,00000,5.VS,00000,111110::::WACH.fmt +"wach.%s v" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + (((signed64) value_vr (SD_, scale, VS, i) << (16 << scale)) + | MASKED (value_acc (SD_, scale, i), (16 << scale) - 1, 0))); +} + + + +// Vector Write Accumulator Low. + +010010,0000,1.SEL,5.VT,5.VS,00000,111110::::WACL.fmt +"wacl.%s v, " +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_acc (SD_, scale, i, + (((signed64) value_vr (SD_, scale, VS, i) << (16 << scale)) + | MASKED (value_vr (SD_, scale, VT, i), + (16 << scale) - 1, 0))); +} + + + +// Vector Xor. + +010010,5.SEL,5.VT,5.VS,5.VD,001101::::XOR.fmt +"xor.%s v, v, %s" +*mdmx: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + int i; + int scale = get_scale (SD_, SEL); + for (i = 0; i < (8 >> scale); i++) + store_vr (SD_, scale, VD, i, + (value_vr (SD_, scale, VS, i) + ^ select_vr (SD_, SEL, VT, i))); +} diff --git a/sim/txvu/mips.dc b/sim/txvu/mips.dc new file mode 100644 index 00000000000..98da0244c9e --- /dev/null +++ b/sim/txvu/mips.dc @@ -0,0 +1,16 @@ +# most instructions +# ------ options ------ : Fst : Lst : ff : fl : fe : word : --- fmt --- : model ... +# { : mask : value : word } + +# Top level - create a very big switch statement. + + padded-switch,combine : 31 : 26 : : : : : : + + switch,combine : 5 : 0 : : : : : : + + switch,combine : 20 : 16 : : : : : : + + switch,combine : 25 : 21 : : : : : : + + switch,combine : 10 : 6 : : : : : : + diff --git a/sim/txvu/mips.igen b/sim/txvu/mips.igen new file mode 100644 index 00000000000..bfe94302f32 --- /dev/null +++ b/sim/txvu/mips.igen @@ -0,0 +1,5209 @@ +// ::= +// { "+" } +// ":" +// ":" +// ":" +// ":" +// +// { } +// { } +// +// + + +// IGEN config - mips16 +:option:16::insn-bit-size:16 +:option:16::hi-bit-nr:15 +:option:16::insn-specifying-widths:true +:option:16::gen-delayed-branch:false + +// IGEN config - mips32/64.. +:option:32::insn-bit-size:32 +:option:32::hi-bit-nr:31 +:option:32::insn-specifying-widths:true +:option:32::gen-delayed-branch:false + + +// Generate separate simulators for each target +// :option:::multi-sim:true + + +// Models known by this simulator +:model:::mipsI:mipsI: +:model:::mipsII:mipsII: +:model:::mipsIII:mipsIII: +:model:::mipsIV:mipsIV: +:model:::mips16:mips16: +// start-sanitize-r5900 +:model:::r5900:r5900: +// end-sanitize-r5900 +:model:::r3900:r3900: +// start-sanitize-tx19 +:model:::tx19:tx19: +// end-sanitize-tx19 +// start-sanitize-vr5400 +:model:::vr5400:vr5400: +:model:::mdmx:mdmx: +// end-sanitize-vr5400 +:model:::vr5000:vr5000: + + + +// Pseudo instructions known by IGEN +:internal::::illegal: +{ + SignalException (ReservedInstruction, 0); +} + + +// Pseudo instructions known by interp.c +// For grep - RSVD_INSTRUCTION, RSVD_INSTRUCTION_MASK +000000,5.*,5.*,5.*,5.OP,000101:SPECIAL:32::RSVD +"rsvd " +{ + SignalException (ReservedInstruction, instruction_0); +} + + + +// +// Mips Architecture: +// +// CPU Instruction Set (mipsI - mipsIV) +// + + +000000,5.RS,5.RT,5.RD,00000,100000:SPECIAL:32::ADD +"add r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + ALU32_BEGIN (GPR[RS]); + ALU32_ADD (GPR[RT]); + ALU32_END (GPR[RD]); +} + + +001000,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ADDI +"addi r, r, IMMEDIATE" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + ALU32_BEGIN (GPR[RS]); + ALU32_ADD (EXTEND16 (IMMEDIATE)); + ALU32_END (GPR[RT]); +} + + +001001,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ADDIU +"add r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + signed32 temp = GPR[RS] + EXTEND16 (IMMEDIATE); + GPR[RT] = EXTEND32 (temp); +} + + +000000,5.RS,5.RT,5.RD,00000,100001:SPECIAL:32::ADDU +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + signed32 temp = GPR[RS] + GPR[RT]; + GPR[RD] = EXTEND32 (temp); +} + + +000000,5.RS,5.RT,5.RD,00000,100100:SPECIAL:32::AND +"and r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = GPR[RS] & GPR[RT]; +} + + +001100,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ANDI +"and r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RT] = GPR[RS] & IMMEDIATE; +} + + +000100,5.RS,5.RT,16.OFFSET:NORMAL:32::BEQ +"beq r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) + DELAY_SLOT (NIA + offset); +} + + +010100,5.RS,5.RT,16.OFFSET:NORMAL:32::BEQL +"beql r, r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000001,5.RS,00001,16.OFFSET:REGIMM:32::BGEZ +"bgez r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] >= 0) + DELAY_SLOT (NIA + offset); +} + + +000001,5.RS!31,10001,16.OFFSET:REGIMM:32::BGEZAL +"bgezal r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + RA = (CIA + 8); + if ((signed_word) GPR[RS] >= 0) + DELAY_SLOT (NIA + offset); +} + + +000001,5.RS!31,10011,16.OFFSET:REGIMM:32::BGEZALL +"bgezall r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + RA = (CIA + 8); + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] >= 0) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000001,5.RS,00011,16.OFFSET:REGIMM:32::BGEZL +"bgezl r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] >= 0) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000111,5.RS,00000,16.OFFSET:NORMAL:32::BGTZ +"bgtz r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] > 0) + DELAY_SLOT (NIA + offset); +} + + +010111,5.RS,00000,16.OFFSET:NORMAL:32::BGTZL +"bgtzl r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] > 0) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000110,5.RS,00000,16.OFFSET:NORMAL:32::BLEZ +"blez r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] <= 0) + DELAY_SLOT (NIA + offset); +} + + +010110,5.RS,00000,16.OFFSET:NORMAL:32::BLEZL +"bgezl r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] <= 0) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000001,5.RS,00000,16.OFFSET:REGIMM:32::BLTZ +"bltz r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] < 0) + DELAY_SLOT (NIA + offset); +} + + +000001,5.RS!31,10000,16.OFFSET:REGIMM:32::BLTZAL +"bltzal r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + RA = (CIA + 8); + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] < 0) + DELAY_SLOT (NIA + offset); +} + + +000001,5.RS!31,10010,16.OFFSET:REGIMM:32::BLTZALL +"bltzall r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + RA = (CIA + 8); + if ((signed_word) GPR[RS] < 0) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000001,5.RS,00010,16.OFFSET:REGIMM:32::BLTZL +"bltzl r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + /* NOTE: The branch occurs AFTER the next instruction has been + executed */ + if ((signed_word) GPR[RS] < 0) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000101,5.RS,5.RT,16.OFFSET:NORMAL:32::BNE +"bne r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) + DELAY_SLOT (NIA + offset); +} + + +010101,5.RS,5.RT,16.OFFSET:NORMAL:32::BNEL +"bnel r, r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word offset = EXTEND16 (OFFSET) << 2; + if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) + DELAY_SLOT (NIA + offset); + else + NULLIFY_NEXT_INSTRUCTION (); +} + + +000000,20.CODE,001101:SPECIAL:32::BREAK +"break" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + SignalException(BreakPoint, instruction_0); +} + + +0100,ZZ!0!1!3,26.COP_FUN:NORMAL:32::COPz +"cop " +*mipsI,mipsII,mipsIII,mipsIV: +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + DecodeCoproc (instruction_0); +} + + +000000,5.RS,5.RT,5.RD,00000,101100:SPECIAL:64::DADD +"dadd r, r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + ALU64_BEGIN (GPR[RS]); + ALU64_ADD (GPR[RT]); + ALU64_END (GPR[RT]); +} + + +011000,5.RS,5.RT,16.IMMEDIATE:NORMAL:64::DADDI +"daddi r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + ALU64_BEGIN (GPR[RS]); + ALU64_ADD (EXTEND16 (IMMEDIATE)); + ALU64_END (GPR[RT]); +} + + +011001,5.RS,5.RT,16.IMMEDIATE:NORMAL:64::DADDIU +"daddu r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RT] = GPR[RS] + EXTEND16 (IMMEDIATE); +} + + +000000,5.RS,5.RT,5.RD,00000,101101:SPECIAL:64::DADDU +"daddu r, r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = GPR[RS] + GPR[RT]; +} + + +000000,5.RS,5.RT,0000000000011110:SPECIAL:64::DDIV +"ddiv r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + CHECKHILO ("Division"); + { + signed64 n = GPR[RS]; + signed64 d = GPR[RT]; + if (d == 0) + { + LO = SIGNED64 (0x8000000000000000); + HI = 0; + } + else if (d == -1 && n == SIGNED64 (0x8000000000000000)) + { + LO = SIGNED64 (0x8000000000000000); + HI = 0; + } + else + { + LO = (n / d); + HI = (n % d); + } + } +} + + + +000000,5.RS,5.RT,0000000000,011111:SPECIAL:64::DDIVU +"ddivu r, r" +*mipsIII: +*mipsIV: +*r3900: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + CHECKHILO ("Division"); + { + unsigned64 n = GPR[RS]; + unsigned64 d = GPR[RT]; + if (d == 0) + { + LO = SIGNED64 (0x8000000000000000); + HI = 0; + } + else + { + LO = (n / d); + HI = (n % d); + } + } +} + + +000000,5.RS,5.RT,0000000000011010:SPECIAL:32::DIV +"div r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + CHECKHILO("Division"); + { + signed32 n = GPR[RS]; + signed32 d = GPR[RT]; + if (d == 0) + { + LO = EXTEND32 (0x80000000); + HI = EXTEND32 (0); + } + else if (d == -1 && d == 0x80000000) + { + LO = EXTEND32 (0x80000000); + HI = EXTEND32 (0); + } + else + { + LO = EXTEND32 (n / d); + HI = EXTEND32 (n % d); + } + } +} + + +000000,5.RS,5.RT,0000000000011011:SPECIAL:32::DIVU +"divu r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + CHECKHILO ("Division"); + { + unsigned32 n = GPR[RS]; + unsigned32 d = GPR[RT]; + if (d == 0) + { + LO = EXTEND32 (0x80000000); + HI = EXTEND32 (0); + } + else + { + LO = EXTEND32 (n / d); + HI = EXTEND32 (n % d); + } + } +} + + +:function:::void:do_dmult:int rs, int rt, int rd, int signed_p +{ + unsigned64 lo; + unsigned64 hi; + unsigned64 m00; + unsigned64 m01; + unsigned64 m10; + unsigned64 m11; + unsigned64 mid; + int sign; + unsigned64 op1 = GPR[rs]; + unsigned64 op2 = GPR[rt]; + CHECKHILO ("Multiplication"); + /* make signed multiply unsigned */ + sign = 0; + if (signed_p) + { + if (op1 < 0) + { + op1 = - op1; + ++sign; + } + if (op2 < 0) + { + op2 = - op2; + ++sign; + } + } + /* multuply out the 4 sub products */ + m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2)); + m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2)); + m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2)); + m11 = ((unsigned64) VH4_8 (op1) * (unsigned64) VH4_8 (op2)); + /* add the products */ + mid = ((unsigned64) VH4_8 (m00) + + (unsigned64) VL4_8 (m10) + + (unsigned64) VL4_8 (m01)); + lo = U8_4 (mid, m00); + hi = (m11 + + (unsigned64) VH4_8 (mid) + + (unsigned64) VH4_8 (m01) + + (unsigned64) VH4_8 (m10)); + /* fix the sign */ + if (sign & 1) + { + lo = -lo; + if (lo == 0) + hi = -hi; + else + hi = -hi - 1; + } + /* save the result HI/LO (and a gpr) */ + LO = lo; + HI = hi; + if (rd != 0) + GPR[rd] = lo; +} + + +000000,5.RS,5.RT,0000000000011100:SPECIAL:64::DMULT +"dmult r, r" +*mipsIII,mipsIV: +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + do_dmult (SD_, RS, RT, 0, 1); +} + +000000,5.RS,5.RT,5.RD,00000011100:SPECIAL:64::DMULT +"dmult r, r":RD == 0 +"dmult r, r, r" +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + do_dmult (SD_, RS, RT, RD, 1); +} + + + +000000,5.RS,5.RT,0000000000011101:SPECIAL:64::DMULTU +"dmultu r, r" +*mipsIII,mipsIV: +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + do_dmult (SD_, RS, RT, 0, 0); +} + +000000,5.RS,5.RT,5.RD,00000011101:SPECIAL:64::DMULTU +"dmultu r, r, r":RD == 0 +"dmultu r, r" +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + do_dmult (SD_, RS, RT, RD, 0); +} + + + +00000000000,5.RT,5.RD,5.SHIFT,111000:SPECIAL:64::DSLL +"dsll r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = SHIFT; + GPR[RD] = GPR[RT] << s; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111100:SPECIAL:64::DSLL32 +"dsll32 r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = 32 + SHIFT; + GPR[RD] = GPR[RT] << s; +} + + +000000,5.RS,5.RT,5.RD,00000010100:SPECIAL:64::DSLLV +"dsllv r, r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = MASKED64 (GPR[RS], 5, 0); + GPR[RD] = GPR[RT] << s; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111011:SPECIAL:64::DSRA +"dsra r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = SHIFT; + GPR[RD] = ((signed64) GPR[RT]) >> s; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111111:SPECIAL:64::DSRA32 +"dsra32 r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = 32 + SHIFT; + GPR[RD] = ((signed64) GPR[RT]) >> s; +} + + +000000,5.RS,5.RT,5.RD,00000010111:SPECIAL:64::DSRAV +"dsra32 r, r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = MASKED64 (GPR[RS], 5, 0); + GPR[RD] = ((signed64) GPR[RT]) >> s; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111010:SPECIAL:64::DSRL +"dsrav r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = SHIFT; + GPR[RD] = (unsigned64) GPR[RT] >> s; +} + + +00000000000,5.RT,5.RD,5.SHIFT,111110:SPECIAL:64::DSRL32 +"dsrl32 r, r, " +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = 32 + SHIFT; + GPR[RD] = (unsigned64) GPR[RT] >> s; +} + + +000000,5.RS,5.RT,5.RD,00000010110:SPECIAL:64::DSRLV +"dsrl32 r, r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = MASKED64 (GPR[RS], 5, 0); + GPR[RD] = (unsigned64) GPR[RT] >> s; +} + + +000000,5.RS,5.RT,5.RD,00000101110:SPECIAL:64::DSUB +"dsub r, r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + ALU64_BEGIN (GPR[RS]); + ALU64_SUB (GPR[RT]); + ALU64_END (GPR[RD]); +} + + +000000,5.RS,5.RT,5.RD,00000101111:SPECIAL:64::DSUBU +"dsubu r, r, r" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = GPR[RS] - GPR[RT]; +} + + +000010,26.INSTR_INDEX:NORMAL:32::J +"j " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + /* NOTE: The region used is that of the delay slot NIA and NOT the + current instruction */ + address_word region = (NIA & MASK (63, 28)); + DELAY_SLOT (region | (INSTR_INDEX << 2)); +} + + +000011,26.INSTR_INDEX:NORMAL:32::JAL +"jal " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + /* NOTE: The region used is that of the delay slot and NOT the + current instruction */ + address_word region = (NIA & MASK (63, 28)); + GPR[31] = CIA + 8; + DELAY_SLOT (region | (INSTR_INDEX << 2)); +} + + +000000,5.RS,00000,5.RD,00000001001:SPECIAL:32::JALR +"jalr r":RD == 31 +"jalr r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word temp = GPR[RS]; + GPR[RD] = CIA + 8; + DELAY_SLOT (temp); +} + + +000000,5.RS,000000000000000001000:SPECIAL:32::JR +"jr r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + DELAY_SLOT (GPR[RS]); +} + + +100000,5.BASE,5.RT,16.OFFSET:NORMAL:32::LB +"lb r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((uword64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + uword64 memval = 0; + uword64 memval1 = 0; + uword64 mask = 0x7; + unsigned int shift = 0; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_BYTE,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0x000000FF),8)); + } + } + } +} + + +100100,5.BASE,5.RT,16.OFFSET:NORMAL:32::LBU +"lbu r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 0; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_BYTE,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (((memval >> (8 * byte)) & 0x000000FF)); + } + } + } +} + + +110111,5.BASE,5.RT,16.OFFSET:NORMAL:64::LD +"ld r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = memval; + } + } + } +} + + +1101,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:64::LDCz +"ldc r, (r)" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + COP_LD(((instruction >> 26) & 0x3),destreg,memval);; + } + } + } +} + + +011010,5.BASE,5.RT,16.OFFSET:NORMAL:64::LDL +"ldl r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 7; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + byte = ((vaddr & mask) ^ bigend); + if (!BigEndianMem) + paddr &= ~mask; + LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = ((memval << ((7 - byte) * 8)) | (GPR[destreg] & (((unsigned64)1 << ((7 - byte) * 8)) - 1))); + } + } + } +} + + +011011,5.BASE,5.RT,16.OFFSET:NORMAL:64::LDR +"ldr r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 7; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + byte = ((vaddr & mask) ^ bigend); + if (BigEndianMem) + paddr &= ~mask; + LoadMemory(&memval,&memval1,uncached,(7 - byte),paddr,vaddr,isDATA,isREAL); + { + unsigned64 srcmask; + if (byte == 0) + srcmask = 0; + else + srcmask = ((unsigned64)-1 << (8 * (8 - byte))); + GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte))); + } + } + } + } +} + + +100001,5.BASE,5.RT,16.OFFSET:NORMAL:32::LH +"lh r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 1) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 1; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_HALFWORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0x0000FFFF),16)); + } + } + } +} + + +100101,5.BASE,5.RT,16.OFFSET:NORMAL:32::LHU +"lhu r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 1) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 1; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_HALFWORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (((memval >> (8 * byte)) & 0x0000FFFF)); + } + } + } +} + + +110000,5.BASE,5.RT,16.OFFSET:NORMAL:32::LL +"ll r, (r)" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0xFFFFFFFF),32)); + LLBIT = 1; + } + } + } +} + + +110100,5.BASE,5.RT,16.OFFSET:NORMAL:64::LLD +"lld r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = memval; + LLBIT = 1; + } + } + } +} + + +001111,00000,5.RT,16.IMMEDIATE:NORMAL:32::LUI +"lui r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RT] = EXTEND32 (IMMEDIATE << 16); +} + + +100011,5.BASE,5.RT,16.OFFSET:NORMAL:32::LW +"lw r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (SIGNEXTEND(((memval >> (8 * byte)) & 0xFFFFFFFF),32)); + } + } + } +} + + +1100,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWCz +"lwc r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + COP_LW(((instruction >> 26) & 0x3),destreg,(unsigned int)((memval >> (8 * byte)) & 0xFFFFFFFF)); + } + } + } +} + + +100010,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWL +"lwl r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 3; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + byte = ((vaddr & mask) ^ bigend); + if (!BigEndianMem) + paddr &= ~mask; + LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL); + if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) { + memval >>= 32; + } + GPR[destreg] = ((memval << ((3 - byte) * 8)) | (GPR[destreg] & (((unsigned64)1 << ((3 - byte) * 8)) - 1))); + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } + } + } +} + + +100110,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWR +"lwr r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 3; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + byte = ((vaddr & mask) ^ bigend); + if (BigEndianMem) + paddr &= ~mask; + LoadMemory(&memval,&memval1,uncached,(3 - byte),paddr,vaddr,isDATA,isREAL); + if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) { + memval >>= 32; + } + { + unsigned64 srcmask; + if (byte == 0) + srcmask = 0; + else + srcmask = ((unsigned64)-1 << (8 * (4 - byte))); + GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte))); + } + GPR[destreg] = SIGNEXTEND(GPR[destreg],32); + } + } + } +} + + +100111,5.BASE,5.RT,16.OFFSET:NORMAL:32::LWU +"lwu r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + GPR[destreg] = (((memval >> (8 * byte)) & 0xFFFFFFFF)); + } + } + } +} + + +000000,0000000000,5.RD,00000,010000:SPECIAL:32::MFHI +"mfhi r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = HI; +#if 0 + HIACCESS = 3; +#endif +} + + +000000,0000000000,5.RD,00000,010010:SPECIAL:32::MFLO +"mflo r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = LO; +#if 0 + LOACCESS = 3; /* 3rd instruction will be safe */ +#endif +} + + +000000,5.RS,5.RT,5.RD,00000001011:SPECIAL:32::MOVN +"movn r, r, r" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + if (GPR[RT] != 0) + GPR[RD] = GPR[RS]; +} + + +000000,5.RS,5.RT,5.RD,00000001010:SPECIAL:32::MOVZ +"movz r, r, r" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + if (GPR[RT] == 0) + GPR[RD] = GPR[RS]; +} + + +000000,5.RS,000000000000000,010001:SPECIAL:32::MTHI +"mthi r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ +#if 0 + if (HIACCESS != 0) + sim_io_eprintf (sd, "MT (move-to) over-writing HI register value\n"); +#endif + HI = GPR[RS]; +#if 0 + HIACCESS = 3; /* 3rd instruction will be safe */ +#endif +} + + +000000,5.RS,000000000000000010011:SPECIAL:32::MTLO +"mtlo r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ +#if 0 + if (LOACCESS != 0) + sim_io_eprintf (sd, "MT (move-to) over-writing LO register value\n"); +#endif + LO = GPR[RS]; +#if 0 + LOACCESS = 3; /* 3rd instruction will be safe */ +#endif +} + + +000000,5.RS,5.RT,00000,00000011000:SPECIAL:32::MULT +"mult r, r" +*mipsI,mipsII,mipsIII,mipsIV: +{ + signed64 prod; + CHECKHILO ("Multiplication"); + prod = (((signed64)(signed32) GPR[RS]) + * ((signed64)(signed32) GPR[RT])); + LO = EXTEND32 (VL4_8 (prod)); + HI = EXTEND32 (VH4_8 (prod)); +} +000000,5.RS,5.RT,5.RD,00000011000:SPECIAL:32::MULT +"mult r, r, r" +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + signed64 prod; + CHECKHILO ("Multiplication"); + prod = (((signed64)(signed32) GPR[RS]) + * ((signed64)(signed32) GPR[RT])); + LO = EXTEND32 (VL4_8 (prod)); + HI = EXTEND32 (VH4_8 (prod)); + if (RD != 0) + GPR[RD] = LO; +} + + +000000,5.RS,5.RT,00000,00000011001:SPECIAL:32::MULTU +"multu r, r" +*mipsI,mipsII,mipsIII,mipsIV: +{ + unsigned64 prod; + CHECKHILO ("Multiplication"); + prod = (((unsigned64)(unsigned32) GPR[RS]) + * ((unsigned64)(unsigned32) GPR[RT])); + LO = EXTEND32 (VL4_8 (prod)); + HI = EXTEND32 (VH4_8 (prod)); +} +000000,5.RS,5.RT,5.RD,00000011001:SPECIAL:32::MULTU +"multu r, r, r" +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned64 prod; + CHECKHILO ("Multiplication"); + prod = (((unsigned64)(unsigned32) GPR[RS]) + * ((unsigned64)(unsigned32) GPR[RT])); + LO = EXTEND32 (VL4_8 (prod)); + HI = EXTEND32 (VH4_8 (prod)); + if (RD != 0) + GPR[RD] = LO; +} + + +000000,5.RS,5.RT,5.RD,00000,100111:SPECIAL:32::NOR +"nor r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = ~ (GPR[RS] | GPR[RT]); +} + + +000000,5.RS,5.RT,5.RD,00000,100101:SPECIAL:32::OR +"or r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = (GPR[RS] | GPR[RT]); +} + + +001101,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::ORI +"ori r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RT] = (GPR[RS] | IMMEDIATE); +} + + +110011,5.RS,nnnnn,16.OFFSET:NORMAL:32::PREF +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int hint = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + Prefetch(uncached,paddr,vaddr,isDATA,hint); + } + } +} + +101000,5.BASE,5.RT,16.OFFSET:NORMAL:32::SB +"sb r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 0; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + byte = ((vaddr & mask) ^ (bigend << shift)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_BYTE,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +111000,5.BASE,5.RT,16.OFFSET:NORMAL:32::SC +"sc r, (r)" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = ((unsigned64) op2 << (8 * byte)); + if (LLBIT) + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + GPR[(instruction >> 16) & 0x0000001F] = LLBIT; + } + } + } +} + + +111100,5.BASE,5.RT,16.OFFSET:NORMAL:64::SCD +"scd r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = op2; + if (LLBIT) + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + GPR[(instruction >> 16) & 0x0000001F] = LLBIT; + } + } + } +} + + +111111,5.BASE,5.RT,16.OFFSET:NORMAL:64::SD +"sd r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = op2; + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +1111,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:64::SDCz +"sdc r, (r)" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = (unsigned64)COP_SD(((instruction >> 26) & 0x3),destreg); + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +101100,5.BASE,5.RT,16.OFFSET:NORMAL:64::SDL +"sdl r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 7; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + byte = ((vaddr & mask) ^ bigend); + if (!BigEndianMem) + paddr &= ~mask; + memval = (op2 >> (8 * (7 - byte))); + StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL); + } + } + } +} + + +101101,5.BASE,5.RT,16.OFFSET:NORMAL:64::SDR +"sdr r, (r)" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word paddr; + int uncached; + unsigned64 memval; + unsigned64 mask = 7; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + address_word vaddr = (GPR[BASE] + EXTEND16 (OFFSET)); + AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL); + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + if (BigEndianMem) + paddr &= ~mask; + byte = ((vaddr & mask) ^ bigend); + memval = (GPR[RT] << (byte * 8)); + StoreMemory(uncached,(AccessLength_DOUBLEWORD - byte),memval,0,paddr,vaddr,isREAL); +} + + +101001,5.BASE,5.RT,16.OFFSET:NORMAL:32::SH +"sh r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 1) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 1; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + byte = ((vaddr & mask) ^ (bigend << shift)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_HALFWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +00000000000,5.RT,5.RD,5.SHIFT,000000:SPECIAL:32::SLL +"sll r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = SHIFT; + unsigned32 temp = (GPR[RT] << s); + GPR[RD] = EXTEND32 (temp); +} + + +000000,5.RS,5.RT,5.RD,00000000100:SPECIAL:32::SLLV +"sllv r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = MASKED (GPR[RS], 4, 0); + unsigned32 temp = (GPR[RT] << s); + GPR[RD] = EXTEND32 (temp); +} + + +000000,5.RS,5.RT,5.RD,00000101010:SPECIAL:32::SLT +"slt r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = ((signed_word) GPR[RS] < (signed_word) GPR[RT]); +} + + +001010,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::SLTI +"slti r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RT] = ((signed_word) GPR[RS] < (signed_word) EXTEND16 (IMMEDIATE)); +} + + +001011,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::SLTIU +"sltiu r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RT] = ((unsigned_word) GPR[RS] < (unsigned_word) EXTEND16 (IMMEDIATE)); +} + +000000,5.RS,5.RT,5.RD,00000101011:SPECIAL:32::SLTU +"sltu r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = ((unsigned_word) GPR[RS] < (unsigned_word) GPR[RT]); +} + + +000000,00000,5.RT,5.RD,5.SHIFT,000011:SPECIAL:32::SRA +"sra r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = SHIFT; + signed32 temp = (signed32) GPR[RT] >> s; + GPR[RD] = EXTEND32 (temp); +} + + +000000,5.RS,5.RT,5.RD,00000000111:SPECIAL:32::SRAV +"srav r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = MASKED (GPR[RS], 4, 0); + signed32 temp = (signed32) GPR[RT] >> s; + GPR[RD] = EXTEND32 (temp); +} + + +000000,00000,5.RT,5.RD,5.SHIFT,000010:SPECIAL:32::SRL +"srl r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = SHIFT; + unsigned32 temp = (unsigned32) GPR[RT] >> s; + GPR[RD] = EXTEND32 (temp); +} + + +000000,5.RS,5.RT,5.RD,00000000110:SPECIAL:32::SRLV +"srlv r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + int s = MASKED (GPR[RS], 4, 0); + unsigned32 temp = (unsigned32) GPR[RT] >> s; + GPR[RD] = EXTEND32 (temp); +} + + +000000,5.RS,5.RT,5.RD,00000100010:SPECIAL:32::SUB +"sub r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + ALU32_BEGIN (GPR[RS]); + ALU32_SUB (GPR[RT]); + ALU32_END (GPR[RD]); +} + + +000000,5.RS,5.RT,5.RD,00000100011:SPECIAL:32::SUBU +"subu r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = EXTEND32 (GPR[RS] - GPR[RT]); +} + + +101011,5.BASE,5.RT,16.OFFSET:NORMAL:32::SW +"sw r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = ((unsigned64) op2 << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +1110,ZZ!0!1!3,5.BASE,5.RT,16.OFFSET:NORMAL:32::SWCz +"swc r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = (((unsigned64)COP_SW(((instruction >> 26) & 0x3),destreg)) << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +101010,5.BASE,5.RT,16.OFFSET:NORMAL:32::SWL +"swl r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 3; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + byte = ((vaddr & mask) ^ bigend); + if (!BigEndianMem) + paddr &= ~mask; + memval = (op2 >> (8 * (3 - byte))); + if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) { + memval <<= 32; + } + StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL); + } + } + } +} + + +101110,5.BASE,5.RT,16.OFFSET:NORMAL:32::SWR +"swr r, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned64 memval = 0; + unsigned64 mask = 3; + unsigned int reverse = (ReverseEndian ? mask : 0); + unsigned int bigend = (BigEndianCPU ? mask : 0); + int byte; + address_word paddr; + int uncached; + address_word vaddr = (GPR[BASE] + EXTEND16 (OFFSET)); + AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL); + paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse)); + if (BigEndianMem) + paddr &= ~mask; + byte = ((vaddr & mask) ^ bigend); + memval = (GPR[RT] << (byte * 8)); + if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) + memval <<= 32; + StoreMemory(uncached,(AccessLength_WORD - byte),memval,0,paddr,vaddr,isREAL); +} + + +000000000000000000000,5.STYPE,001111:SPECIAL:32::SYNC +"sync":STYPE == 0 +"sync " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + SyncOperation (STYPE); +} + + +000000,20.CODE,001100:SPECIAL:32::SYSCALL +"syscall " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + SignalException(SystemCall, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110100:SPECIAL:32::TEQ +"teq r, r" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] == (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01100,16.IMMEDIATE:REGIMM:32::TEQI +"teqi r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] == (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110000:SPECIAL:32::TGE +"tge r, r" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] >= (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01000,16.IMMEDIATE:REGIMM:32::TGEI +"tgei r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] >= (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01001,16.IMMEDIATE:REGIMM:32::TGEIU +"tgeiu r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((unsigned_word) GPR[RS] >= (unsigned_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110001:SPECIAL:32::TGEU +"tgeu r, r" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((unsigned_word) GPR[RS] >= (unsigned_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110010:SPECIAL:32::TLT +"tlt r, r" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] < (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01010,16.IMMEDIATE:REGIMM:32::TLTI +"tlti r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] < (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01011,16.IMMEDIATE:REGIMM:32::TLTIU +"tltiu r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((unsigned_word) GPR[RS] < (unsigned_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110011:SPECIAL:32::TLTU +"tltu r, r" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((unsigned_word) GPR[RS] < (unsigned_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,10.CODE,110110:SPECIAL:32::TNE +"tne r, r" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] != (signed_word) GPR[RT]) + SignalException(Trap, instruction_0); +} + + +000001,5.RS,01110,16.IMMEDIATE:REGIMM:32::TNEI +"tne r, " +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if ((signed_word) GPR[RS] != (signed_word) EXTEND16 (IMMEDIATE)) + SignalException(Trap, instruction_0); +} + + +000000,5.RS,5.RT,5.RD,00000100110:SPECIAL:32::XOR +"xor r, r, r" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RD] = GPR[RS] ^ GPR[RT]; +} + + +001110,5.RS,5.RT,16.IMMEDIATE:NORMAL:32::XORI +"xori r, r, " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + GPR[RT] = GPR[RS] ^ IMMEDIATE; +} + + +// +// MIPS Architecture: +// +// FPU Instruction Set (COP1 & COP1X) +// + + +:%s::::FMT:int fmt +{ + switch (fmt) + { + case fmt_single: return "s"; + case fmt_double: return "d"; + case fmt_word: return "w"; + case fmt_long: return "l"; + default: return "?"; + } +} + +:%s::::X:int x +{ + switch (x) + { + case 0: return "f"; + case 1: return "t"; + default: return "?"; + } +} + +:%s::::TF:int tf +{ + if (tf) + return "t"; + else + return "f"; +} + +:%s::::ND:int nd +{ + if (nd) + return "l"; + else + return ""; +} + +:%s::::COND:int cond +{ + switch (cond) + { + case 00: return "f"; + case 01: return "un"; + case 02: return "eq"; + case 03: return "ueq"; + case 04: return "olt"; + case 05: return "ult"; + case 06: return "ole"; + case 07: return "ule"; + case 010: return "sf"; + case 011: return "ngle"; + case 012: return "seq"; + case 013: return "ngl"; + case 014: return "lt"; + case 015: return "nge"; + case 016: return "le"; + case 017: return "ngt"; + default: return "?"; + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000101:COP1:32,f::ABS.fmt +"abs.%s f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format)); + } +} + + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000000:COP1:32,f::ADD +"add.%s f, f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction, instruction); + else + StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + + +// BC1F +// BC1FL +// BC1T +// BC1TL + +010001,01000,3.0,1.ND,1.TF,16.OFFSET:COP1S:32,f::BC1 +"bc1%s%s " +*mipsI,mipsII,mipsIII: +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + if (PREVCOC1() == TF) + { + DELAY_SLOT (NIA + (EXTEND16 (OFFSET) << 2)); + } + else if (ND) + { + NULLIFY_NEXT_INSTRUCTION (); + } +} + +010001,01000,3.CC,1.ND,1.TF,16.OFFSET:COP1S:32,f::BC1 +"bc1%s%s ":CC == 0 +"bc1%s%s , " +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if (GETFCC(CC) == TF) + { + DELAY_SLOT (NIA + (EXTEND16 (OFFSET) << 2)); + } + else if (ND) + { + NULLIFY_NEXT_INSTRUCTION (); + } +} + + + +// C.EQ.S +// C.EQ.D +// ... + +:function:::void:do_c_cond_fmt:int fmt, int ft, int fs, int cc, int cond, instruction_word insn +{ + if ((fmt != fmt_single) && (fmt != fmt_double)) + SignalException (ReservedInstruction, insn); + else + { + int less; + int equal; + int unordered; + int condition; + unsigned64 ofs = ValueFPR (fs, fmt); + unsigned64 oft = ValueFPR (ft, fmt); + if (NaN (ofs, fmt) || NaN (oft, fmt)) + { + if (FCSR & FP_ENABLE (IO)) + { + FCSR |= FP_CAUSE (IO); + SignalExceptionFPE (); + } + less = 0; + equal = 0; + unordered = 1; + } + else + { + less = Less (ofs, oft, fmt); + equal = Equal (ofs, oft, fmt); + unordered = 0; + } + condition = (((cond & (1 << 2)) && less) + || ((cond & (1 << 1)) && equal) + || ((cond & (1 << 0)) && unordered)); + SETFCC (cc, condition); + } +} + +010001,10,3.FMT,5.FT,5.FS,3.0,00,11,4.COND:COP1:32::C.cond.fmt +*mipsI,mipsII,mipsIII: +"c.%s.%s f, f": +{ + do_c_cond_fmt (SD_, FMT, FT, FS, 0, COND, instruction_0); +} + +010001,10,3.FMT,5.FT,5.FS,3.CC,00,11,4.COND:COP1:32::C.cond.fmt +"c.%s.%s f, f":CC == 0 +"c.%s.%s , f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + do_c_cond_fmt (SD_, FMT, FT, FS, CC, COND, instruction_0); +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001010:COP1:64::CEIL.L.fmt +"ceil.l.%s f, f" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_TOPINF,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001110:COP1:32::CEIL.W +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_TOPINF,ValueFPR(fs,format),format,fmt_word)); + } +} + + +// CFC1 +// CTC1 +010001,00,X,10,5.RT,5.FS,00000000000:COP1S:32::CxC1 +"c%sc1 r, f" +*mipsI: +*mipsII: +*mipsIII: +{ + if (X) + { + if (FS == 0) + PENDING_FILL((FS + FCR0IDX),VL4_8(GPR[RT])); + else if (FS == 31) + PENDING_FILL((FS + FCR31IDX),VL4_8(GPR[RT])); + /* else NOP */ + PENDING_FILL(COCIDX,0); /* special case */ + } + else + { /* control from */ + if (FS == 0) + PENDING_FILL(RT,SIGNEXTEND(FCR0,32)); + else if (FS == 31) + PENDING_FILL(RT,SIGNEXTEND(FCR31,32)); + /* else NOP */ + } +} +010001,00,X,10,5.RT,5.FS,00000000000:COP1S:32::CxC1 +"c%sc1 r, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if (X) + { + if (FS == 0) + FCR0 = VL4_8(GPR[RT]); + else if (FS == 31) + FCR31 = VL4_8(GPR[RT]); + /* else NOP */ + SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); + } + else + { /* control from */ + if (FS == 0) + GPR[RT] = SIGNEXTEND (FCR0, 32); + else if (FS == 31) + GPR[RT] = SIGNEXTEND (FCR31, 32); + /* else NOP */ + } +} + + +// +// FIXME: Does not correctly differentiate between mips* +// +010001,10,3.FMT,00000,5.FS,5.FD,100001:COP1:32::CVT.D.fmt +"cvt.d.%s f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_double) | 0) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_double,Convert(GETRM(),ValueFPR(fs,format),format,fmt_double)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,100101:COP1:64::CVT.L.fmt +"cvt.l.%s f, f" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_long) | ((format == fmt_long) || (format == fmt_word))) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(GETRM(),ValueFPR(fs,format),format,fmt_long)); + } +} + + +// +// FIXME: Does not correctly differentiate between mips* +// +010001,10,3.FMT,00000,5.FS,5.FD,100000:COP1:32::CVT.S.fmt +"cvt.s.%s f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_single) | 0) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_single,Convert(GETRM(),ValueFPR(fs,format),format,fmt_single)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,100100:COP1:32::CVT.W.fmt +"cvt.w.%s f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format == fmt_word) | ((format == fmt_long) || (format == fmt_word))) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(GETRM(),ValueFPR(fs,format),format,fmt_word)); + } +} + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000011:COP1:32::DIV.fmt +"div.%s f, f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + +// DMFC1 +// DMTC1 +010001,00,X,01,5.RT,5.FS,00000000000:COP1S:64::DMxC1 +"dm%sc1 r, f" +*mipsIII: +{ + if (X) + { + if (SizeFGR() == 64) + PENDING_FILL((FS + FGRIDX),GPR[RT]); + else if ((FS & 0x1) == 0) + { + PENDING_FILL(((FS + 1) + FGRIDX),VH4_8(GPR[RT])); + PENDING_FILL((FS + FGRIDX),VL4_8(GPR[RT])); + } + } + else + { + if (SizeFGR() == 64) + PENDING_FILL(RT,FGR[FS]); + else if ((FS & 0x1) == 0) + PENDING_FILL(RT,(SET64HI(FGR[FS+1]) | FGR[FS])); + else + PENDING_FILL(RT,SET64HI(0xDEADC0DE) | 0xBAD0BAD0); + } +} +010001,00,X,01,5.RT,5.FS,00000000000:COP1S:64::DMxC1 +"dm%sc1 r, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if (X) + { + if (SizeFGR() == 64) + StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]); + else if ((FS & 0x1) == 0) + StoreFPR (FS, fmt_uninterpreted_64, SET64HI (FGR[FS+1]) | FGR[FS]); + } + else + { + if (SizeFGR() == 64) + GPR[RT] = FGR[FS]; + else if ((FS & 0x1) == 0) + GPR[RT] = SET64HI (FGR[FS+1]) | FGR[FS]; + else + GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0; + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001011:COP1:64::FLOOR.L.fmt +"floor.l.%s f, f" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_TOMINF,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001111:COP1:32::FLOOR.W.fmt +"floor.w.%s f, f" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_TOMINF,ValueFPR(fs,format),format,fmt_word)); + } +} + + +110101,5.BASE,5.FT,16.OFFSET:COP1:64::LDC1 +"ldc1 f, (r)" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word vaddr = GPR[BASE] + EXTEND16 (OFFSET); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + unsigned64 memval; + AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL); + LoadMemory(&memval,0,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + COP_LD(((instruction_0 >> 26) & 0x3),FT,memval);; + } +} + + +010011,5.BASE,5.INDEX,5.0,5.FD,000001:COP1X:64::LDXC1 +"ldxc1 f, r(r)" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + op2); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + LoadMemory(&memval,&memval1,uncached,AccessLength_DOUBLEWORD,paddr,vaddr,isDATA,isREAL); + COP_LD(1,destreg,memval);; + } + } + } +} + + + +110001,5.BASE,5.FT,16.OFFSET:COP1:32::LWC1 +"lwc1 f, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = EXTEND16 (OFFSET); + int destreg UNUSED = ((instruction >> 16) & 0x0000001F); + signed_word op1 UNUSED = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((uword64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + uword64 memval = 0; + uword64 memval1 = 0; + uword64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte UNUSED; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + COP_LW(((instruction >> 26) & 0x3),destreg,(unsigned int)((memval >> (8 * byte)) & 0xFFFFFFFF)); + } + } + } +} + + +010011,5.BASE,5.INDEX,5.0,5.FD,000000:COP1X:32::LWXC1 +"lwxc1 f, r(r)" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + op2); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 2; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift))); + LoadMemory(&memval,&memval1,uncached,AccessLength_WORD,paddr,vaddr,isDATA,isREAL); + byte = ((vaddr & mask) ^ (bigend << shift)); + COP_LW(1,destreg,(unsigned int)((memval >> (8 * byte)) & 0xFFFFFFFF)); + } + } + } +} + + + +// +// FIXME: Not correct for mips* +// +010011,5.FR,5.FT,5.FS,5.FD,100,001:COP1X:32::MADD.D +"madd.d f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Add(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double)); + } +} + + +010011,5.FR,5.FT,5.FS,5.FD,100,000:COP1X:32::MADD.S +"madd.s f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Add(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single)); + } +} + + +// MFC1 +// MTC1 +010001,00,X,00,5.RT,5.FS,00000000000:COP1S:32::MxC1 +"m%sc1 r, f" +*mipsI: +*mipsII: +*mipsIII: +{ + if (X) + { /*MTC1*/ + if (SizeFGR() == 64) + PENDING_FILL ((FS + FGRIDX), (SET64HI(0xDEADC0DE) | VL4_8(GPR[RT]))); + else + PENDING_FILL ((FS + FGRIDX), VL4_8(GPR[RT])); + } + else /*MFC1*/ + PENDING_FILL (RT, SIGNEXTEND(FGR[FS],32)); +} +010001,00,X,00,5.RT,5.FS,00000000000:COP1S:32::MxC1 +"m%sc1 r, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + if (X) + /*MTC1*/ + StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT])); + else /*MFC1*/ + GPR[RT] = SIGNEXTEND(FGR[FS],32); +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000110:COP1:32::MOV.fmt +"mov.%s f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + StoreFPR(destreg,format,ValueFPR(fs,format)); + } +} + + +// MOVF +000000,5.RS,3.CC,0,1.TF,5.RD,00000000001:SPECIAL:32::MOVtf +"mov%s r, r, " +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + if (GETFCC(CC) == TF) + GPR[RD] = GPR[RS]; +} + + +// MOVF.fmt +010001,10,3.FMT,3.CC,0,1.TF,5.FS,5.FD,010001:COP1:32::MOVtf.fmt +"mov%s.%s f, f, " +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + int format = ((instruction >> 21) & 0x00000007); + { + if (GETFCC(CC) == TF) + StoreFPR (FD, format, ValueFPR (FS, format)); + else + StoreFPR (FD, format, ValueFPR (FD, format)); + } +} + + +010001,10,3.FMT,5.RT,5.FS,5.FD,010011:COP1:32::MOVN.fmt +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + StoreFPR(destreg,format,ValueFPR(fs,format)); + } +} + + +// MOVT see MOVtf + + +// MOVT.fmt see MOVtf.fmt + + + +010001,10,3.FMT,5.RT,5.FS,5.FD,010010:COP1:32::MOVZ.fmt +"movz.%s f, f, r" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + StoreFPR(destreg,format,ValueFPR(fs,format)); + } +} + + +// MSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,101,001:COP1X:32::MSUB.D +"msub.d f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Sub(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double)); + } +} + + +// MSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,101000:COP1X:32::MSUB.S +"msub.s f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Sub(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single)); + } +} + + +// MTC1 see MxC1 + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000010:COP1:32::MUL.fmt +"mul.%s f, f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000111:COP1:32::NEG.fmt +"neg.%s f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format)); + } +} + + +// NMADD.fmt +010011,5.FR,5.FT,5.FS,5.FD,110001:COP1X:32::NMADD.D +"nmadd.d f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Negate(Add(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double),fmt_double)); + } +} + + +// NMADD.fmt +010011,5.FR,5.FT,5.FS,5.FD,110000:COP1X:32::NMADD.S +"nmadd.s f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Negate(Add(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single),fmt_single)); + } +} + + +// NMSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,111001:COP1X:32::NMSUB.D +"nmsub.d f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_double,Negate(Sub(Multiply(ValueFPR(fs,fmt_double),ValueFPR(ft,fmt_double),fmt_double),ValueFPR(fr,fmt_double),fmt_double),fmt_double)); + } +} + + +// NMSUB.fmt +010011,5.FR,5.FT,5.FS,5.FD,111000:COP1X:32::NMSUB.S +"nmsub.s f, f, f, f" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int fr = ((instruction >> 21) & 0x0000001F); + { + StoreFPR(destreg,fmt_single,Negate(Sub(Multiply(ValueFPR(fs,fmt_single),ValueFPR(ft,fmt_single),fmt_single),ValueFPR(fr,fmt_single),fmt_single),fmt_single)); + } +} + + +010011,5.BASE,5.INDEX,5.HINT,00000001111:COP1X:32::PREFX +"prefx , r(r)" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int fs = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + (unsigned64)op2); + address_word paddr; + int uncached; + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + Prefetch(uncached,paddr,vaddr,isDATA,fs); + } +} + +010001,10,3.FMT,00000,5.FS,5.FD,010101:COP1:32::RECIP.fmt +*mipsIV: +"recip.%s f, f" +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001000:COP1:64::ROUND.L.fmt +"round.l.%s f, f" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_NEAREST,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001100:COP1:32::ROUND.W.fmt +"round.w.%s f, f" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_NEAREST,ValueFPR(fs,format),format,fmt_word)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,010110:COP1:32::RSQRT.fmt +*mipsIV: +"rsqrt.%s f, f" +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Recip(SquareRoot(ValueFPR(fs,format),format),format)); + } +} + + +111101,5.BASE,5.FT,16.OFFSET:COP1:64::SDC1 +"sdc1 f, (r)" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + address_word vaddr = GPR[BASE] + EXTEND16 (OFFSET); + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + address_word paddr; + unsigned64 memval; + AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL); + memval = (unsigned64) COP_SD(((instruction_0 >> 26) & 0x3),FT); + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,0,paddr,vaddr,isREAL); + } +} + + + +010011,5.RS,5.RT,vvvvv,00000001001:COP1X:64::SDXC1 +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int fs = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + op2); + address_word paddr; + int uncached; + if ((vaddr & 7) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = (unsigned64)COP_SD(1,fs); + { + StoreMemory(uncached,AccessLength_DOUBLEWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,000100:COP1:32::SQRT.fmt +"sqrt.%s f, f" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,(SquareRoot(ValueFPR(fs,format),format))); + } +} + + +010001,10,3.FMT,5.FT,5.FS,5.FD,000001:COP1:32::SUB.fmt +"sub.%s f, f, f" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int ft = ((instruction >> 16) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format)); + } +} + + + +111001,5.BASE,5.FT,16.OFFSET:COP1:32::SWC1 +"swc1 f, (r)" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = EXTEND16 (OFFSET); + int destreg UNUSED = ((instruction >> 16) & 0x0000001F); + signed_word op1 UNUSED = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((uword64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + uword64 memval = 0; + uword64 memval1 = 0; + uword64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = (((uword64)COP_SW(((instruction >> 26) & 0x3),destreg)) << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +010011,5.BASE,5.INDEX,5.FS,00000,001000:COP1X:32::SWXC1 +"swxc1 f, r(r)" +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +{ + unsigned32 instruction = instruction_0; + int fs = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + op2); + address_word paddr; + int uncached; + if ((vaddr & 3) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int byte; + paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2))); + byte = ((vaddr & mask) ^ (BigEndianCPU << 2)); + memval = (((unsigned64)COP_SW(1,fs)) << (8 * byte)); + { + StoreMemory(uncached,AccessLength_WORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001001:COP1:64::TRUNC.L.fmt +"trunc.l.%s f, f" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_long,Convert(FP_RM_TOZERO,ValueFPR(fs,format),format,fmt_long)); + } +} + + +010001,10,3.FMT,00000,5.FS,5.FD,001101:COP1:32::TRUNC.W +"trunc.w.%s f, f" +*mipsII: +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 6) & 0x0000001F); + int fs = ((instruction >> 11) & 0x0000001F); + int format = ((instruction >> 21) & 0x00000007); + { + if ((format != fmt_single) && (format != fmt_double)) + SignalException(ReservedInstruction,instruction); + else + StoreFPR(destreg,fmt_word,Convert(FP_RM_TOZERO,ValueFPR(fs,format),format,fmt_word)); + } +} + + +// +// MIPS Architecture: +// +// System Control Instruction Set (COP0) +// + + +010000,01000,00000,16.OFFSET:COP0:32::BC0F +"bc0f " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,01000,00010,16.OFFSET:COP0:32::BC0FL +"bc0fl " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,01000,00001,16.OFFSET:COP0:32::BC0T +"bc0t " +*mipsI,mipsII,mipsIII,mipsIV: +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + + +010000,01000,00011,16.OFFSET:COP0:32::BC0TL +"bc0tl " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +101111,5.BASE,5.OP,16.OFFSET:NORMAL:32::CACHE +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int hint = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = (op1 + offset); + address_word paddr; + int uncached; + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + CacheOp(hint,vaddr,paddr,instruction); + } +} + + +010000,10000,000000000000000,111001:COP0:32::DI +"di" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,10000,000000000000000,111000:COP0:32::EI +"ei" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,10000,000000000000000,011000:COP0:32::ERET +"eret" +*mipsIII: +*mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,00000,5.RT,5.RD,00000,6.REGX:COP0:32::MFC0 +"mfc0 r, r # " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + DecodeCoproc (instruction_0); +} + +010000,00100,5.RT,5.RD,00000,6.REGX:COP0:32::MTC0 +"mtc0 r, r # " +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + DecodeCoproc (instruction_0); +} + + +010000,10000,000000000000000,001000:COP0:32::TLBP +"tlbp" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,10000,000000000000000,000001:COP0:32::TLBR +"tlbr" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,10000,000000000000000,000010:COP0:32::TLBWI +"tlbwi" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +010000,10000,000000000000000,000110:COP0:32::TLBWR +"tlbwr" +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 + + +:include:::m16.igen +// start-sanitize-vr5400 +:include::vr5400:vr5400.igen +:include:::mdmx.igen +// end-sanitize-vr5400 +// start-sanitize-r5900 +:include::r5900:r5900.igen +// end-sanitize-r5900 + +// start-sanitize-cygnus-never + +// // FIXME FIXME FIXME What is this instruction? +// 111011,5.RS,5.RT,16.OFFSET:NORMAL:32:: +// *mipsI: +// *mipsII: +// *mipsIII: +// *mipsIV: +// // start-sanitize-r5900 +// *r5900: +// // end-sanitize-r5900 +// *r3900: +// // start-sanitize-tx19 +// *tx19: +// // end-sanitize-tx19 +// { +// unsigned32 instruction = instruction_0; +// signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); +// signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; +// signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; +// { +// if (CoProcPresent(3)) +// SignalException(CoProcessorUnusable); +// else +// SignalException(ReservedInstruction,instruction); +// } +// } + +// end-sanitize-cygnus-never +// start-sanitize-cygnus-never + +// // FIXME FIXME FIXME What is this? +// 11100,******,00001:RR:16::SDBBP +// *mips16: +// { +// unsigned32 instruction = instruction_0; +// if (have_extendval) +// SignalException (ReservedInstruction, instruction); +// { +// SignalException(DebugBreakPoint,instruction); +// } +// } + +// end-sanitize-cygnus-never +// start-sanitize-cygnus-never + +// // FIXME FIXME FIXME What is this? +// 000000,********************,001110:SPECIAL:32::SDBBP +// *r3900: +// { +// unsigned32 instruction = instruction_0; +// { +// SignalException(DebugBreakPoint,instruction); +// } +// } + +// end-sanitize-cygnus-never +// start-sanitize-cygnus-never + +// // FIXME FIXME FIXME This apparently belongs to the vr4100 which +// // isn't yet reconized by this simulator. +// 000000,5.RS,5.RT,0000000000101000:SPECIAL:32::MADD16 +// *vr4100: +// { +// unsigned32 instruction = instruction_0; +// signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; +// signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; +// { +// CHECKHILO("Multiply-Add"); +// { +// unsigned64 temp = (op1 * op2); +// temp += (SET64HI(VL4_8(HI)) | VL4_8(LO)); +// LO = SIGNEXTEND((unsigned64)VL4_8(temp),32); +// HI = SIGNEXTEND((unsigned64)VH4_8(temp),32); +// } +// } +// } + +// end-sanitize-cygnus-never +// start-sanitize-cygnus-never + +// // FIXME FIXME FIXME This apparently belongs to the vr4100 which +// // isn't yet reconized by this simulator. +// 000000,5.RS,5.RT,0000000000101001:SPECIAL:64::DMADD16 +// *vr4100: +// { +// unsigned32 instruction = instruction_0; +// signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; +// signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; +// { +// CHECKHILO("Multiply-Add"); +// { +// unsigned64 temp = (op1 * op2); +// LO = LO + temp; +// } +// } +// } + +// end-sanitize-cygnus-never diff --git a/sim/txvu/pke0.c b/sim/txvu/pke0.c new file mode 100644 index 00000000000..be48cffcb63 --- /dev/null +++ b/sim/txvu/pke0.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#include "sim-main.h" + +#include "device.h" +#include "pke0.h" + +int +pke0_io_read_buffer(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Read!\n", me->name); + return nr_bytes; +} + +int +pke0_io_write_buffer(device *me, + const void *source, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Write!\n", me->name); + return nr_bytes; +} + +device pke0_device = + { + "pke0", + &pke0_io_read_buffer, + &pke0_io_write_buffer + }; + +void +pke0_attach(SIM_DESC sd) +{ + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + PKE0_REGISTER_WINDOW_START, + PKE0_REGISTER_WINDOW_SIZE /*nr_bytes*/, + 0 /*modulo*/, + &pke0_device, + NULL /*buffer*/); +} diff --git a/sim/txvu/pke0.h b/sim/txvu/pke0.h new file mode 100644 index 00000000000..633ac477e44 --- /dev/null +++ b/sim/txvu/pke0.h @@ -0,0 +1,17 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef PKE0_H_ +#define PKE0_H_ + +#include "sim-main.h" + +void pke0_attach(SIM_DESC sd); + +#define PKE0_REGISTER_WINDOW_START 0x10000800 +#define PKE0_REGISTER_WINDOW_END 0x10000980 + +#define PKE0_REGISTER_WINDOW_SIZE (PKE0_REGISTER_WINDOW_END - PKE0_REGISTER_WINDOW_START) + +#endif diff --git a/sim/txvu/pke1.c b/sim/txvu/pke1.c new file mode 100644 index 00000000000..62492f916ab --- /dev/null +++ b/sim/txvu/pke1.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#include "sim-main.h" + +#include "device.h" +#include "pke1.h" + +int +pke1_io_read_buffer(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Read!\n", me->name); + return nr_bytes; +} + +int +pke1_io_write_buffer(device *me, + const void *source, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Write!\n", me->name); + return nr_bytes; +} + +device pke1_device = + { + "pke1", + &pke1_io_read_buffer, + &pke1_io_write_buffer + }; + +void +pke1_attach(SIM_DESC sd) +{ + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + PKE1_REGISTER_WINDOW_START, + PKE1_REGISTER_WINDOW_SIZE /*nr_bytes*/, + 0 /*modulo*/, + &pke1_device, + NULL /*buffer*/); +} diff --git a/sim/txvu/pke1.h b/sim/txvu/pke1.h new file mode 100644 index 00000000000..04bd8832fb1 --- /dev/null +++ b/sim/txvu/pke1.h @@ -0,0 +1,17 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef PKE1_H_ +#define PKE1_H_ + +#include "sim-main.h" + +void pke1_attach(SIM_DESC sd); + +#define PKE1_REGISTER_WINDOW_START 0x10000a00 +#define PKE1_REGISTER_WINDOW_END 0x10000b80 + +#define PKE1_REGISTER_WINDOW_SIZE (PKE1_REGISTER_WINDOW_END - PKE1_REGISTER_WINDOW_START) + +#endif diff --git a/sim/txvu/r5900.igen b/sim/txvu/r5900.igen new file mode 100644 index 00000000000..a10d5d0e580 --- /dev/null +++ b/sim/txvu/r5900.igen @@ -0,0 +1,2463 @@ +// start-sanitize-r5900 + +// FIXME: The instructions below which are typically r5900 specific +// need to be merged back into the above. + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,0000000000011010:MMINORM:32::DIV1 +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + CHECKHILO("Division"); + { + int d1 = op1; + int d2 = op2; + if (d2 == 0) + { + LO1 = SIGNEXTEND(0x80000000,32); + HI1 = SIGNEXTEND(0,32); + } + else if (d2 == -1 && d1 == 0x80000000) + { + LO1 = SIGNEXTEND(0x80000000,32); + HI1 = SIGNEXTEND(0,32); + } + else + { + LO1 = SIGNEXTEND((d1 / d2),32); + HI1 = SIGNEXTEND((d1 % d2),32); + } + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,0000000000011011:MMINORM:32::DIVU1 +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + CHECKHILO("Division"); + { + unsigned int d1 = op1; + unsigned int d2 = op2; + if (d2 == 0) + { + LO1 = SIGNEXTEND(0x80000000,32); + HI1 = SIGNEXTEND(0,32); + } + else if (d2 == -1 && d1 == 0x80000000) + { + LO1 = SIGNEXTEND(0x80000000,32); + HI1 = SIGNEXTEND(0,32); + } + else + { + LO1 = SIGNEXTEND((d1 / d2),32); + HI1 = SIGNEXTEND((d1 % d2),32); + } + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011110,5.RS,5.RT,16.OFFSET:NORMAL:128::LQ +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + int destreg = ((instruction >> 16) & 0x0000001F); + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 15) != 0) + SignalExceptionAddressLoad(); + else + { + if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + unsigned64 mask = 0x7; + unsigned int shift = 8; + unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0); + unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0); + unsigned int byte; + LoadMemory(&memval,&memval1,uncached,AccessLength_QUADWORD,paddr,vaddr,isDATA,isREAL); + GPR[destreg] = memval; + GPR1[destreg] = memval1; + } + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000000000:MMINORM:32::MADD +*r5900: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + word64 prod = (word64)WORD64(VL4_8(HI),VL4_8(LO)) + ((word64)SIGNEXTEND(op1,32) * (word64)SIGNEXTEND(op2,32)); + LO = SIGNEXTEND(prod,32); + HI = SIGNEXTEND( VH4_8(prod), 32); + if( destreg != 0 ) GPR[destreg] = LO; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000000001:MMINORM:32::MADDU +*r5900: +*r3900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + unsigned64 prod = (unsigned64)WORD64(VL4_8(HI),VL4_8(LO)) + ((unsigned64)VL4_8(op1) * (unsigned64)VL4_8(op2)); + LO = SIGNEXTEND(prod,32); + HI = SIGNEXTEND( VH4_8(prod), 32); + if( destreg != 0 ) GPR[destreg] = LO; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000100000:MMINORM:32::MADD1 +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + word64 prod = (word64)WORD64(VL4_8(HI1),VL4_8(LO1)) + ((word64)SIGNEXTEND(op1,32) * (word64)SIGNEXTEND(op2,32)); + LO1 = SIGNEXTEND(prod,32); + HI1 = SIGNEXTEND( VH4_8(prod), 32); + if( destreg != 0 ) GPR[destreg] = LO1; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000100001:MMINORM:32::MADDU1 +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + unsigned64 prod = (unsigned64)WORD64(VL4_8(HI1),VL4_8(LO1)) + ((unsigned64)VL4_8(op1) * (unsigned64)VL4_8(op2)); + LO1 = SIGNEXTEND(prod,32); + HI1 = SIGNEXTEND( VH4_8(prod), 32); + if( destreg != 0 ) GPR[destreg] = LO1; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +0111000000000000,5.RD,00000010000:MMINORM:32::MFHI1 +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + { + GPR[destreg] = HI1; + HI1ACCESS = 3; /* 3rd instruction will be safe */ + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +0111000000000000,5.RD,00000010010:MMINORM:32::MFLO1 +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + { + GPR[destreg] = LO1; + LO1ACCESS = 3; /* 3rd instruction will be safe */ + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +0000000000000000,5.RD,00000101000:SPECIAL:32::MFSA +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + { + GPR[destreg] = SA; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,000000000000000010001:MMINORM:32::MTHI1 +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + if (HI1ACCESS != 0) + sim_io_error(sd,"MT (move-to) over-writing HI register value\n"); + HI1 = op1; + HI1ACCESS = 3; /* 3rd instruction will be safe */ + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,000000000000000010011:MMINORM:32::MTLO1 +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + if (LO1ACCESS != 0) + sim_io_error(sd,"MT (move-to) over-writing LO register value"); + LO1 = op1; + LO1ACCESS = 3; /* 3rd instruction will be safe */ + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +000000,5.RS,000000000000000101001:SPECIAL:32::MTSA +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + SA = op1; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +000001,5.RS,11000,16.IMMEDIATE:REGIMM:32::MTSAB +*r5900: +{ + SA = ((GPR[RA] & 0xF) ^ (IMMEDIATE & 0xF)) * 8; +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +000001,5.RS,11001,16.IMMEDIATE:REGIMM:32::MTSAH +*r5900: +{ + SA = ((GPR[RS] & 0x7) ^ (IMMEDIATE & 0x7)) * 16; +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000011000:MMINORM:32::MULT1 +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + CHECKHILO("Multiplication"); + { + unsigned64 temp = ((word64) op1 * (word64) op2); + LO1 = SIGNEXTEND((unsigned64)VL4_8(temp),32); + HI1 = SIGNEXTEND((unsigned64)VH4_8(temp),32); + if ( destreg != 0 ) + GPR[destreg] = LO1; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000011001:MMINORM:32::MULTU1 +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word op2 = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + { + CHECKHILO("Multiplication"); + { + unsigned64 temp = ((unsigned64)(op1 & 0xffffffff) * (unsigned64)(op2 & 0xffffffff)); + LO1 = SIGNEXTEND((unsigned64)VL4_8(temp),32); + HI1 = SIGNEXTEND((unsigned64)VH4_8(temp),32); + if ( destreg != 0 ) + GPR[destreg] = LO1; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,00101101000:MMI1:32::PABSH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i= 0) + GPR_SH(destreg,i) = RT_SH(i); + else if (RT_SH(i) == -32768) + GPR_SH(destreg,i) = 32767; + else + GPR_SH(destreg,i) = -RT_SH(i); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,00001101000:MMI1:32::PABSW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i= 0) + GPR_SW(destreg,i) = RT_SW(i); + else if (RT_SW(i) == (int)0x80000000) + GPR_SW(destreg,i) = (int)0x7FFFFFFF; + else + GPR_SW(destreg,i) = -RT_SW(i); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01000001000:MMI0:32::PADDB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < BYTES_IN_MMI_REGS; i++) + { + int s = RS_SB(i); + int t = RT_SB(i); + int r = s + t; + GPR_SB(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00100001000:MMI0:32::PADDH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < HALFWORDS_IN_MMI_REGS; i++) + { + int s = RS_SH(i); + int t = RT_SH(i); + int r = s + t; + GPR_SH(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000001000:MMI0:32::PADDW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < WORDS_IN_MMI_REGS; i++) + { + signed64 s = RS_SW(i); + signed64 t = RT_SW(i); + signed64 r = s + t; + GPR_SW(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,11000001000:MMI0:32::PADDSB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < BYTES_IN_MMI_REGS; i++) + { + int s = RS_SB(i); + int t = RT_SB(i); + int r = s + t; + if (r > 127) + GPR_SB(destreg,i) = 127; + else if (r < -128) + GPR_SB(destreg,i) = -128; + else + GPR_SB(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10100001000:MMI0:32::PADDSH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < HALFWORDS_IN_MMI_REGS; i++) + { + int s = RS_SH(i); + int t = RT_SH(i); + int r = s + t; + if (r > 32767) + GPR_SH(destreg,i) = 32767; + else if (r < -32768) + GPR_SH(destreg,i) = -32768; + else + GPR_SH(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10000001000:MMI0:32::PADDSW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < WORDS_IN_MMI_REGS; i++) + { + signed64 s = RS_SW(i); + signed64 t = RT_SW(i); + signed64 r = s + t; + if (r > (int)0x7FFFFFFF) + GPR_SW(destreg,i) = (int)0x7FFFFFFF; + else if (r < (int)0x80000000) + GPR_SW(destreg,i) = (int)0x80000000; + else + GPR_SW(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,11000101000:MMI1:32::PADDUB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < BYTES_IN_MMI_REGS; i++) + { + unsigned int s = RS_UB(i); + unsigned int t = RT_UB(i); + unsigned int r = s + t; + if (r > 0xFF) + GPR_UB(destreg,i) = 0xFF; + else + GPR_UB(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10100101000:MMI1:32::PADDUH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < HALFWORDS_IN_MMI_REGS; i++) + { + unsigned int s = RS_UH(i); + unsigned int t = RT_UH(i); + unsigned int r = s + t; + if (r > 0xFFFF) + GPR_UH(destreg,i) = 0xFFFF; + else + GPR_UH(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10000101000:MMI1:32::PADDUW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < WORDS_IN_MMI_REGS; i++) + { + unsigned64 s = RS_UW(i); + unsigned64 t = RT_UW(i); + unsigned64 r = s + t; + if (r > 0xFFFFFFFF) + GPR_UW(destreg,i) = 0xFFFFFFFF; + else + GPR_UW(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00100101000:MMI1:32::PADSBH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i RT_SB(i)) GPR_SB(destreg,i) = 0xFF; + else GPR_SB(destreg,i) = 0; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00110001000:MMI0:32::PCGTH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i RT_SH(i)) GPR_SH(destreg,i) = 0xFFFF; + else GPR_SH(destreg,i) = 0; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00010001000:MMI0:32::PCGTW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i RT_SW(i)) GPR_SW(destreg,i) = 0xFFFFFFFF; + else GPR_SW(destreg,i) = 0; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11011101001:MMI3:32::PCPYH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4); + GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01110001001:MMI2:32::PCPYLD +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UD(destreg,0) = RT_UD(0); + GPR_UD(destreg,1) = RS_UD(0); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01110101001:MMI3:32::PCPYUD +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UD(destreg,0) = RS_UD(1); + GPR_UD(destreg,1) = RT_UD(1); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,0000011101001001:MMI2:32::PDIVBW +*r5900: +{ + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + signed32 devisor = RT_SH(0); + if (devisor == -1) + { + LO_SW(0) = -RS_SW(0); + HI_SW(0) = 0; + LO_SW(1) = -RS_SW(1); + HI_SW(1) = 0; + LO_SW(2) = -RS_SW(2); + HI_SW(2) = 0; + LO_SW(3) = -RS_SW(3); + HI_SW(3) = 0; + } + else if (devisor != 0) + { + LO_SW(0) = RS_SW(0) / devisor; + HI_SW(0) = SIGNEXTEND( (RS_SW(0) % devisor), 16 ); + LO_SW(1) = RS_SW(1) / devisor; + HI_SW(1) = SIGNEXTEND( (RS_SW(1) % devisor), 16 ); + LO_SW(2) = RS_SW(2) / devisor; + HI_SW(2) = SIGNEXTEND( (RS_SW(2) % devisor), 16 ); + LO_SW(3) = RS_SW(3) / devisor; + HI_SW(3) = SIGNEXTEND( (RS_SW(3) % devisor), 16 ); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,0000001101101001:MMI3:32::PDIVUW +*r5900: +{ + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + if (RT_UW(0) != 0) + { + LO = (signed32)(RS_UW(0) / RT_UW(0)); + HI = (signed32)(RS_UW(0) % RT_UW(0)); + } + if (RT_UW(2) != 0) + { + LO1 = (signed32)(RS_UW(2) / RT_UW(2)); + HI1 = (signed32)(RS_UW(2) % RT_UW(2)); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,0000001101001001:MMI2:32::PDIVW +*r5900: +{ + signed_word rs_reg = GPR[RS]; + signed_word rs_reg1 = GPR1[RS]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + if (RT_SW(0) == -1) + { + LO = -RS_SW(0); + HI = 0; + } + else if (RT_UW(0) != 0) + { + LO = (signed32)(RS_SW(0) / RT_SW(0)); + HI = (signed32)(RS_SW(0) % RT_SW(0)); + } + if (RT_SW(2) == -1) + { + LO1 = -RS_SW(2); + HI1 = 0; + } + else if (RT_UW(2) != 0) + { + LO1 = (signed32)(RS_SW(2) / RT_SW(2)); + HI1 = (signed32)(RS_SW(2) % RT_SW(2)); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11010101001:MMI3:32::PEXCH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(0); + GPR_UH(destreg,1) = RT_UH(2); + GPR_UH(destreg,2) = RT_UH(1); + GPR_UH(destreg,3) = RT_UH(3); + GPR_UH(destreg,4) = RT_UH(4); + GPR_UH(destreg,5) = RT_UH(6); + GPR_UH(destreg,6) = RT_UH(5); + GPR_UH(destreg,7) = RT_UH(7); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11110101001:MMI3:32::PEXCW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UW(destreg,0) = RT_UW(0); + GPR_UW(destreg,1) = RT_UW(2); + GPR_UW(destreg,2) = RT_UW(1); + GPR_UW(destreg,3) = RT_UW(3); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11010001001:MMI2:32::PEXOH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(2); + GPR_UH(destreg,1) = RT_UH(1); + GPR_UH(destreg,2) = RT_UH(0); + GPR_UH(destreg,3) = RT_UH(3); + GPR_UH(destreg,4) = RT_UH(6); + GPR_UH(destreg,5) = RT_UH(5); + GPR_UH(destreg,6) = RT_UH(4); + GPR_UH(destreg,7) = RT_UH(7); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11110001001:MMI2:32::PEXOW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UW(destreg,0) = RT_UW(2); + GPR_UW(destreg,1) = RT_UW(1); + GPR_UW(destreg,2) = RT_UW(0); + GPR_UW(destreg,3) = RT_UW(3); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11110001000:MMI0:32::PEXT5 +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UB(destreg,0) = RT_UB(0); + GPR_UB(destreg,1) = RS_UB(0); + GPR_UB(destreg,2) = RT_UB(1); + GPR_UB(destreg,3) = RS_UB(1); + GPR_UB(destreg,4) = RT_UB(2); + GPR_UB(destreg,5) = RS_UB(2); + GPR_UB(destreg,6) = RT_UB(3); + GPR_UB(destreg,7) = RS_UB(3); + GPR_UB(destreg,8) = RT_UB(4); + GPR_UB(destreg,9) = RS_UB(4); + GPR_UB(destreg,10) = RT_UB(5); + GPR_UB(destreg,11) = RS_UB(5); + GPR_UB(destreg,12) = RT_UB(6); + GPR_UB(destreg,13) = RS_UB(6); + GPR_UB(destreg,14) = RT_UB(7); + GPR_UB(destreg,15) = RS_UB(7); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10110001000:MMI0:32::PEXTLH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(0); + GPR_UH(destreg,1) = RS_UH(0); + GPR_UH(destreg,2) = RT_UH(1); + GPR_UH(destreg,3) = RS_UH(1); + GPR_UH(destreg,4) = RT_UH(2); + GPR_UH(destreg,5) = RS_UH(2); + GPR_UH(destreg,6) = RT_UH(3); + GPR_UH(destreg,7) = RS_UH(3); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10010001000:MMI0:32::PEXTLW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UW(destreg,0) = RT_UW(0); + GPR_UW(destreg,1) = RS_UW(0); + GPR_UW(destreg,2) = RT_UW(1); + GPR_UW(destreg,3) = RS_UW(1); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,11010101000:MMI1:32::PEXTUB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UB(destreg,0) = RT_UB(8); + GPR_UB(destreg,1) = RS_UB(8); + GPR_UB(destreg,2) = RT_UB(9); + GPR_UB(destreg,3) = RS_UB(9); + GPR_UB(destreg,4) = RT_UB(10); + GPR_UB(destreg,5) = RS_UB(10); + GPR_UB(destreg,6) = RT_UB(11); + GPR_UB(destreg,7) = RS_UB(11); + GPR_UB(destreg,8) = RT_UB(12); + GPR_UB(destreg,9) = RS_UB(12); + GPR_UB(destreg,10) = RT_UB(13); + GPR_UB(destreg,11) = RS_UB(13); + GPR_UB(destreg,12) = RT_UB(14); + GPR_UB(destreg,13) = RS_UB(14); + GPR_UB(destreg,14) = RT_UB(15); + GPR_UB(destreg,15) = RS_UB(15); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10110101000:MMI1:32::PEXTUH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(4); + GPR_UH(destreg,1) = RS_UH(4); + GPR_UH(destreg,2) = RT_UH(5); + GPR_UH(destreg,3) = RS_UH(5); + GPR_UH(destreg,4) = RT_UH(6); + GPR_UH(destreg,5) = RS_UH(6); + GPR_UH(destreg,6) = RT_UH(7); + GPR_UH(destreg,7) = RS_UH(7); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10010101000:MMI1:32::PEXTUW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UW(destreg,0) = RT_UW(2); + GPR_UW(destreg,1) = RS_UW(2); + GPR_UW(destreg,2) = RT_UW(3); + GPR_UW(destreg,3) = RS_UW(3); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10001001001:MMI2:32::PHMADDH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) + (RS_SH(0) * RT_SH(0)); + GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) + (RS_SH(2) * RT_SH(2)); + GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) + (RS_SH(4) * RT_SH(4)); + GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) + (RS_SH(6) * RT_SH(6)); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10101001001:MMI2:32::PHMSUBH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) - (RS_SH(0) * RT_SH(0)); + GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) - (RS_SH(2) * RT_SH(2)); + GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) - (RS_SH(4) * RT_SH(4)); + GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) - (RS_SH(6) * RT_SH(6)); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01010001001:MMI2:32::PINTH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(0); + GPR_UH(destreg,1) = RS_UH(4); + GPR_UH(destreg,2) = RT_UH(1); + GPR_UH(destreg,3) = RS_UH(5); + GPR_UH(destreg,4) = RT_UH(2); + GPR_UH(destreg,5) = RS_UH(6); + GPR_UH(destreg,6) = RT_UH(3); + GPR_UH(destreg,7) = RS_UH(7); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01010101001:MMI3:32::PINTOH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(0); + GPR_UH(destreg,1) = RS_UH(0); + GPR_UH(destreg,2) = RT_UH(2); + GPR_UH(destreg,3) = RS_UH(2); + GPR_UH(destreg,4) = RT_UH(4); + GPR_UH(destreg,5) = RS_UH(4); + GPR_UH(destreg,6) = RT_UH(6); + GPR_UH(destreg,7) = RS_UH(6); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,00000,5.RD,00000000100:MMINORM:32::PLZCW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + { + unsigned long value; + int test; + int count; + int i; + value = RS_UW(0); + count = 0; + test = !!(value & (1 << 31)); + for(i=30; i>=0 && (test == !!(value & (1 << i))); i--) + count++; + GPR_UW(destreg,0) = count; + value = RS_UW(1); + count = 0; + test = !!(value & (1 << 31)); + for(i=30; i>=0 && (test == !!(value & (1 << i))); i--) + count++; + GPR_UW(destreg,1) = count; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10000001001:MMI2:32::PMADDH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_SW(destreg,0) = LO_SW(0) += (RS_SH(0) * RT_SH(0)); + LO_SW(1) += (RS_SH(1) * RT_SH(1)); + GPR_SW(destreg,1) = HI_SW(0) += (RS_SH(2) * RT_SH(2)); + HI_SW(1) += (RS_SH(3) * RT_SH(3)); + GPR_SW(destreg,2) = LO_SW(2) += (RS_SH(4) * RT_SH(4)); + LO_SW(3) += (RS_SH(5) * RT_SH(5)); + GPR_SW(destreg,3) = HI_SW(2) += (RS_SH(6) * RT_SH(6)); + HI_SW(3) += (RS_SH(7) * RT_SH(7)); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000101001:MMI3:32::PMADDUW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + unsigned64 sum0 = U8_4 (HI_SW(0), LO_SW(0)); + unsigned64 sum1 = U8_4 (HI_SW(2), LO_SW(2)); + unsigned64 prod0 = (unsigned64)RS_UW(0) * (unsigned64)RT_UW(0); + unsigned64 prod1 = (unsigned64)RS_UW(2) * (unsigned64)RT_UW(2); + sum0 += prod0; + sum1 += prod1; + GPR_UD(destreg,0) = sum0; + GPR_UD(destreg,1) = sum1; + LO = SIGNEXTEND( sum0, 32 ); + HI = SIGNEXTEND( VH4_8(sum0), 32 ); + LO1 = SIGNEXTEND( sum1, 32 ); + HI1 = SIGNEXTEND( VH4_8(sum1), 32 ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00000001001:MMI2:32::PMADDW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + signed64 sum0 = WORD64( HI_SW(0), LO_SW(0) ); + signed64 sum1 = WORD64( HI_SW(2), LO_SW(2) ); + signed64 prod0 = (signed64)RS_SW(0) * (signed64)RT_SW(0); + signed64 prod1 = (signed64)RS_SW(2) * (signed64)RT_SW(2); + sum0 += prod0; + sum1 += prod1; + GPR_SD(destreg,0) = sum0; + GPR_SD(destreg,1) = sum1; + LO = SIGNEXTEND( sum0, 32 ); + HI = SIGNEXTEND( VH4_8(sum0), 32 ); + LO1 = SIGNEXTEND( sum1, 32 ); + HI1 = SIGNEXTEND( VH4_8(sum1), 32 ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00111001000:MMI0:32::PMAXH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i RT_SH(i)) GPR_SH(destreg,i) = RS_SH(i); + else GPR_SH(destreg,i) = RT_SH(i); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00011001000:MMI0:32::PMAXW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i RT_SW(i)) GPR_SW(destreg,i) = RS_SW(i); + else GPR_SW(destreg,i) = RT_SW(i); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +0111000000000000,5.RD,01000001001:MMI2:32::PMFHI +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + { + GPR_SD(destreg,0) = HI; + GPR_SD(destreg,1) = HI1; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +0111000000000000,5.RD,01001001001:MMI2:32::PMFLO +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + { + GPR_SD(destreg,0) = LO; + GPR_SD(destreg,1) = LO1; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +0111000000000000,5.RD,5.SHIFT,110000:MMINORM:32::PMFHL +*r5900: +{ + unsigned32 instruction = instruction_0; + int op1 = ((instruction >> 6) & 0x0000001F); + int destreg = ((instruction >> 11) & 0x0000001F); + { + if (op1 == 0) + { + GPR_UW(destreg,0) = LO_UW(0); + GPR_UW(destreg,1) = HI_UW(0); + GPR_UW(destreg,2) = LO_UW(2); + GPR_UW(destreg,3) = HI_UW(2); + } + else if (op1 == 1) + { + GPR_UW(destreg,0) = LO_UW(1); + GPR_UW(destreg,1) = HI_UW(1); + GPR_UW(destreg,2) = LO_UW(3); + GPR_UW(destreg,3) = HI_UW(3); + } + else if (op1 == 2) + { + /* NOTE: This code implements a saturate according to the + figure on page B-115 and not according to the + definition on page B-113 */ + signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0); + signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2); + if ( t > SIGNED64 (0x000000007FFFFFFF) ) + GPR_SD(destreg,0) = SIGNED64 (0x000000007FFFFFFF); + else if ( t < - SIGNED64 (0x0000000080000000) ) + GPR_SD(destreg,0) = - SIGNED64 (0x0000000080000000); + else + GPR_SD(destreg,0) = t; + if ( u > SIGNED64 (0x000000007FFFFFFF) ) + GPR_SD(destreg,1) = SIGNED64 (0x000000007FFFFFFF); + else if ( u < - SIGNED64 (0x0000000080000000) ) + GPR_SD(destreg,1) = - SIGNED64 (0x0000000080000000); + else + GPR_SD(destreg,1) = u; + } + else if (op1 == 3) + { + GPR_UH(destreg,0) = LO_UH(0); + GPR_UH(destreg,1) = LO_UH(2); + GPR_UH(destreg,2) = HI_UH(0); + GPR_UH(destreg,3) = HI_UH(2); + GPR_UH(destreg,4) = LO_UH(4); + GPR_UH(destreg,5) = LO_UH(6); + GPR_UH(destreg,6) = HI_UH(4); + GPR_UH(destreg,7) = HI_UH(6); + } + else if (op1 == 4) + { + if (LO_SW(0) > 0x7FFF) + GPR_UH(destreg,0) = 0x7FFF; + else if (LO_SW(0) < -0x8000) + GPR_UH(destreg,0) = 0x8000; + else + GPR_UH(destreg,0) = LO_UH(0); + if (LO_SW(1) > 0x7FFF) + GPR_UH(destreg,1) = 0x7FFF; + else if (LO_SW(1) < -0x8000) + GPR_UH(destreg,1) = 0x8000; + else + GPR_UH(destreg,1) = LO_UH(2); + if (HI_SW(0) > 0x7FFF) + GPR_UH(destreg,2) = 0x7FFF; + else if (HI_SW(0) < -0x8000) + GPR_UH(destreg,2) = 0x8000; + else + GPR_UH(destreg,2) = HI_UH(0); + if (HI_SW(1) > 0x7FFF) + GPR_UH(destreg,3) = 0x7FFF; + else if (HI_SW(1) < -0x8000) + GPR_UH(destreg,3) = 0x8000; + else + GPR_UH(destreg,3) = HI_UH(2); + if (LO_SW(2) > 0x7FFF) + GPR_UH(destreg,4) = 0x7FFF; + else if (LO_SW(2) < -0x8000) + GPR_UH(destreg,4) = 0x8000; + else + GPR_UH(destreg,4) = LO_UH(4); + if (LO_SW(3) > 0x7FFF) + GPR_UH(destreg,5) = 0x7FFF; + else if (LO_SW(3) < -0x8000) + GPR_UH(destreg,5) = 0x8000; + else + GPR_UH(destreg,5) = LO_UH(6); + if (HI_SW(2) > 0x7FFF) + GPR_UH(destreg,6) = 0x7FFF; + else if (HI_SW(2) < -0x8000) + GPR_UH(destreg,6) = 0x8000; + else + GPR_UH(destreg,6) = HI_UH(4); + if (HI_SW(3) > 0x7FFF) + GPR_UH(destreg,7) = 0x7FFF; + else if (HI_SW(3) < -0x8000) + GPR_UH(destreg,7) = 0x8000; + else + GPR_UH(destreg,7) = HI_UH(6); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00111101000:MMI1:32::PMINH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_SW(destreg,0) = LO_SW(0) -= (RS_SH(0) * RT_SH(0)); + LO_SW(1) -= (RS_SH(1) * RT_SH(1)); + GPR_SW(destreg,1) = HI_SW(0) -= (RS_SH(2) * RT_SH(2)); + HI_SW(1) -= (RS_SH(3) * RT_SH(3)); + GPR_SW(destreg,2) = LO_SW(2) -= (RS_SH(4) * RT_SH(4)); + LO_SW(3) -= (RS_SH(5) * RT_SH(5)); + GPR_SW(destreg,3) = HI_SW(2) -= (RS_SH(6) * RT_SH(6)); + HI_SW(3) -= (RS_SH(7) * RT_SH(7)); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00100001001:MMI2:32::PMSUBW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + signed64 sum0 = WORD64( HI_SW(0), LO_SW(0) ); + signed64 sum1 = WORD64( HI_SW(2), LO_SW(2) ); + signed64 prod0 = (signed64)RS_SW(0) * (signed64)RT_SW(0); + signed64 prod1 = (signed64)RS_SW(2) * (signed64)RT_SW(2); + sum0 -= prod0; + sum1 -= prod1; + GPR_SD(destreg,0) = sum0; + GPR_SD(destreg,1) = sum1; + LO = SIGNEXTEND( sum0, 32 ); + HI = SIGNEXTEND( VH4_8(sum0), 32 ); + LO1 = SIGNEXTEND( sum1, 32 ); + HI1 = SIGNEXTEND( VH4_8(sum1), 32 ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,000000000001000101001:MMI3:32::PMTHI +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + { + HI = RS_SD(0); + HI1 = RS_SD(1); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,000000000001001101001:MMI3:32::PMTLO +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + { + LO = RS_SD(0); + LO1 = RS_SD(1); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,000000000000000110001:MMINORM:32::PMTHL.LW +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + { + LO_UW(0) = RS_UW(0); + HI_UW(0) = RS_UW(1); + LO_UW(2) = RS_UW(2); + HI_UW(2) = RS_UW(3); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,11100001001:MMI2:32::PMULTH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(0) * RT_SH(0)); + LO_SW(1) = (RS_SH(1) * RT_SH(1)); + GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(2) * RT_SH(2)); + HI_SW(1) = (RS_SH(3) * RT_SH(3)); + GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(4) * RT_SH(4)); + LO_SW(3) = (RS_SH(5) * RT_SH(5)); + GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(6) * RT_SH(6)); + HI_SW(3) = (RS_SH(7) * RT_SH(7)); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01100101001:MMI3:32::PMULTUW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + unsigned64 sum0 = 0; + unsigned64 sum1 = 0; + unsigned64 prod0 = (unsigned64)RS_UW(0) * (unsigned64)RT_UW(0); + unsigned64 prod1 = (unsigned64)RS_UW(2) * (unsigned64)RT_UW(2); + sum0 = prod0; + sum1 = prod1; + GPR_UD(destreg,0) = sum0; + GPR_UD(destreg,1) = sum1; + LO = SIGNEXTEND( sum0, 32 ); + HI = SIGNEXTEND( VH4_8(sum0), 32 ); + LO1 = SIGNEXTEND( sum1, 32 ); + HI1 = SIGNEXTEND( VH4_8(sum1), 32 ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01100001001:MMI2:32::PMULTW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + signed64 sum0 = 0; + signed64 sum1 = 0; + signed64 prod0 = (signed64)RS_SW(0) * (signed64)RT_SW(0); + signed64 prod1 = (signed64)RS_SW(2) * (signed64)RT_SW(2); + sum0 = prod0; + sum1 = prod1; + GPR_SD(destreg,0) = sum0; + GPR_SD(destreg,1) = sum1; + LO = SIGNEXTEND( sum0, 32 ); + HI = SIGNEXTEND( VH4_8(sum0), 32 ); + LO1 = SIGNEXTEND( sum1, 32 ); + HI1 = SIGNEXTEND( VH4_8(sum1), 32 ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10011101001:MMI3:32::PNOR +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> (31 - 15)) + | ((x & (31 << 19)) >> (19 - 10)) + | ((x & (31 << 11)) >> (11 - 5)) + | ((x & (31 << 3)) >> (3 - 0)); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,11011001000:MMI0:32::PPACB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UB(destreg,0) = RT_UB(0); + GPR_UB(destreg,1) = RT_UB(2); + GPR_UB(destreg,2) = RT_UB(4); + GPR_UB(destreg,3) = RT_UB(6); + GPR_UB(destreg,4) = RT_UB(8); + GPR_UB(destreg,5) = RT_UB(10); + GPR_UB(destreg,6) = RT_UB(12); + GPR_UB(destreg,7) = RT_UB(14); + GPR_UB(destreg,8) = RS_UB(0); + GPR_UB(destreg,9) = RS_UB(2); + GPR_UB(destreg,10) = RS_UB(4); + GPR_UB(destreg,11) = RS_UB(6); + GPR_UB(destreg,12) = RS_UB(8); + GPR_UB(destreg,13) = RS_UB(10); + GPR_UB(destreg,14) = RS_UB(12); + GPR_UB(destreg,15) = RS_UB(14); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10111001000:MMI0:32::PPACH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(0); + GPR_UH(destreg,1) = RT_UH(2); + GPR_UH(destreg,2) = RT_UH(4); + GPR_UH(destreg,3) = RT_UH(6); + GPR_UH(destreg,4) = RS_UH(0); + GPR_UH(destreg,5) = RS_UH(2); + GPR_UH(destreg,6) = RS_UH(4); + GPR_UH(destreg,7) = RS_UH(6); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10011001000:MMI0:32::PPACW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UW(destreg,0) = RT_UW(0); + GPR_UW(destreg,1) = RT_UW(2); + GPR_UW(destreg,2) = RS_UW(0); + GPR_UW(destreg,3) = RS_UW(2); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11011001001:MMI2:32::PREVH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UH(destreg,0) = RT_UH(3); + GPR_UH(destreg,1) = RT_UH(2); + GPR_UH(destreg,2) = RT_UH(1); + GPR_UH(destreg,3) = RT_UH(0); + GPR_UH(destreg,4) = RT_UH(7); + GPR_UH(destreg,5) = RT_UH(6); + GPR_UH(destreg,6) = RT_UH(5); + GPR_UH(destreg,7) = RT_UH(4); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,11111001001:MMI2:32::PROT3W +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UW(destreg,0) = RT_UW(0); + GPR_UW(destreg,1) = RT_UW(3); + GPR_UW(destreg,2) = RT_UW(1); + GPR_UW(destreg,3) = RT_UW(2); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,5.SHIFT,110100:MMINORM:32::PSLLH +*r5900: +{ + unsigned32 instruction = instruction_0; + int op1 = ((instruction >> 6) & 0x0000001F); + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int shift_by = op1 & (16-1); + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int s0 = (RS_UB(0) & 0x1F); + int s1 = (RS_UB(8) & 0x1F); + signed32 temp0 = RT_UW(0) << s0; + signed32 temp1 = RT_UW(2) << s1; + GPR_SD(destreg,0) = (signed64)temp0; + GPR_SD(destreg,1) = (signed64)temp1; + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,5.SHIFT,111100:MMINORM:32::PSLLW +*r5900: +{ + unsigned32 instruction = instruction_0; + int op1 = ((instruction >> 6) & 0x0000001F); + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int shift_by = op1 & (32-1); + int i; + for(i=0;i> 6) & 0x0000001F); + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int shift_by = op1 & (16-1); + int i; + for(i=0;i> shift_by), (16-shift_by) ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00011101001:MMI3:32::PSRAVW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) ); + GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,5.SHIFT,111111:MMINORM:32::PSRAW +*r5900: +{ + unsigned32 instruction = instruction_0; + int op1 = ((instruction >> 6) & 0x0000001F); + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int shift_by = op1 & (32-1); + int i; + for(i=0;i> shift_by), (32-shift_by) ); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,5.SHIFT,110110:MMINORM:32::PSRLH +*r5900: +{ + unsigned32 instruction = instruction_0; + int op1 = ((instruction >> 6) & 0x0000001F); + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int shift_by = op1 & (16-1); + int i; + for(i=0;i> shift_by); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00011001001:MMI2:32::PSRLVW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + GPR_UD(destreg,0) = SIGNEXTEND ( RT_UW(0) >> (RS_UB(0) & 0x1F), 31); + GPR_UD(destreg,1) = SIGNEXTEND ( RT_UW(2) >> (RS_UB(8) & 0x1F), 31); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +01110000000,5.RT,5.RD,5.SHIFT,111110:MMINORM:32::PSRLW +*r5900: +{ + unsigned32 instruction = instruction_0; + int op1 = ((instruction >> 6) & 0x0000001F); + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int shift_by = op1 & (32-1); + int i; + for(i=0;i> shift_by); + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,01001001000:MMI0:32::PSUBB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < BYTES_IN_MMI_REGS; i++) + { + int s = RS_SB(i); + int t = RT_SB(i); + int r = s - t; + GPR_SB(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00101001000:MMI0:32::PSUBH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < HALFWORDS_IN_MMI_REGS; i++) + { + int s = RS_SH(i); + int t = RT_SH(i); + int r = s - t; + GPR_SH(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,11001001000:MMI0:32::PSUBSB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < BYTES_IN_MMI_REGS; i++) + { + int s = RS_SB(i); + int t = RT_SB(i); + int r = s - t; + if (r > 127) + GPR_SB(destreg,i) = 127; + else if (r < -128) + GPR_SB(destreg,i) = -128; + else + GPR_SB(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10101001000:MMI0:32::PSUBSH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < HALFWORDS_IN_MMI_REGS; i++) + { + int s = RS_SH(i); + int t = RT_SH(i); + int r = s - t; + if (r > 32767) + GPR_SH(destreg,i) = 32767; + else if (r < -32768) + GPR_SH(destreg,i) = -32768; + else + GPR_SH(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10001001000:MMI0:32::PSUBSW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < WORDS_IN_MMI_REGS; i++) + { + signed64 s = RS_SW(i); + signed64 t = RT_SW(i); + signed64 r = s - t; + if (r > (int)0x7FFFFFFF) + GPR_SW(destreg,i) = (int)0x7FFFFFFF; + else if (r < (int)0x80000000) + GPR_SW(destreg,i) = (int)0x80000000; + else + GPR_SW(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,11001101000:MMI1:32::PSUBUB +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < BYTES_IN_MMI_REGS; i++) + { + unsigned int s = RS_UB(i); + unsigned int t = RT_UB(i); + unsigned int r = s - t; + if (r > 0xFF) + GPR_UB(destreg,i) = 0; + else + GPR_UB(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10101101000:MMI1:32::PSUBUH +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < HALFWORDS_IN_MMI_REGS; i++) + { + unsigned int s = RS_UH(i); + unsigned int t = RT_UH(i); + unsigned int r = s - t; + if (r > 0xFFFF) + GPR_UH(destreg,i) = 0; + else + GPR_UH(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10001101000:MMI1:32::PSUBUW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < WORDS_IN_MMI_REGS; i++) + { + unsigned64 s = RS_UW(i); + unsigned64 t = RT_UW(i); + unsigned64 r = s - t; + if (r > 0xFFFFFFFF) + GPR_UW(destreg,i) = 0; + else + GPR_UW(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,00001001000:MMI0:32::PSUBW +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for (i=0; i < WORDS_IN_MMI_REGS; i++) + { + signed64 s = RS_SW(i); + signed64 t = RT_SW(i); + signed64 r = s - t; + GPR_SW(destreg,i) = r; + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011100,5.RS,5.RT,5.RD,10011001001:MMI2:32::PXOR +*r5900: +{ + unsigned32 instruction = instruction_0; + int destreg = ((instruction >> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int i; + for(i=0;i> 11) & 0x0000001F); + signed_word rs_reg = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rs_reg1 = GPR1[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + int bytes = (SA / 8) % 16; + if (SA % 8) + SignalException(ReservedInstruction,instruction); + else + { + int i; + for(i=0;i<(16-bytes);i++) + GPR_SB(destreg,i) = RT_SB(bytes+i); + for(;i<16;i++) + GPR_SB(destreg,i) = RS_SB(i-(16-bytes)); + } + } +} + +// end-sanitize-r5900 +// start-sanitize-r5900 + +011111,5.RS,5.RT,16.OFFSET:NORMAL:128::SQ +*r5900: +{ + unsigned32 instruction = instruction_0; + signed_word offset = SIGNEXTEND((signed_word)((instruction >> 0) & 0x0000FFFF),16); + signed_word rsigned_word = GPR[((instruction >> 16) & 0x0000001F)]; + signed_word rsigned_word1 = GPR1[((instruction >> 16) & 0x0000001F)]; + signed_word op1 = GPR[((instruction >> 21) & 0x0000001F)]; + signed_word rt_reg = GPR[RT]; + signed_word rt_reg1 = GPR1[RT]; + { + address_word vaddr = ((unsigned64)op1 + offset); + address_word paddr; + int uncached; + if ((vaddr & 15) != 0) + SignalExceptionAddressStore(); + else + { + if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&uncached,isTARGET,isREAL)) + { + unsigned64 memval = 0; + unsigned64 memval1 = 0; + memval = rsigned_word; + memval1 = rsigned_word1; + { + StoreMemory(uncached,AccessLength_QUADWORD,memval,memval1,paddr,vaddr,isREAL); + } + } + } + } +} + +// end-sanitize-r5900 diff --git a/sim/txvu/sim-main.h b/sim/txvu/sim-main.h new file mode 100644 index 00000000000..aa0928a58f4 --- /dev/null +++ b/sim/txvu/sim-main.h @@ -0,0 +1,734 @@ +/* MIPS Simulator definition. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +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. */ + +#ifndef SIM_MAIN_H +#define SIM_MAIN_H + +/* This simulator doesn't cache the Current Instruction Address */ +/* #define SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA) */ +/* #define SIM_ENGINE_RESUME_HOOK(SD, LAST_CPU, CIA) */ + +#define SIM_HAVE_BIENDIAN + + +/* hobble some common features for moment */ +#define WITH_WATCHPOINTS 1 +#define WITH_MODULO_MEMORY 1 + +/* For device support. FIXME: revisit. */ +#define WITH_DEVICES 1 + +#include "sim-basics.h" + +typedef address_word sim_cia; + +#if (WITH_IGEN) +/* Get the number of instructions. FIXME: must be a more elegant way + of doing this. */ +#include "itable.h" +#define MAX_INSNS (nr_itable_entries) +#define INSN_NAME(i) itable[(i)].name +#endif + +#include "sim-base.h" + + +/* Depreciated macros and types for manipulating 64bit values. Use + ../common/sim-bits.h and ../common/sim-endian.h macros instead. */ + +typedef signed64 word64; +typedef unsigned64 uword64; + +#define WORD64LO(t) (unsigned int)((t)&0xFFFFFFFF) +#define WORD64HI(t) (unsigned int)(((uword64)(t))>>32) +#define SET64LO(t) (((uword64)(t))&0xFFFFFFFF) +#define SET64HI(t) (((uword64)(t))<<32) +#define WORD64(h,l) ((word64)((SET64HI(h)|SET64LO(l)))) +#define UWORD64(h,l) (SET64HI(h)|SET64LO(l)) + +/* Sign-extend the given value (e) as a value (b) bits long. We cannot + assume the HI32bits of the operand are zero, so we must perform a + mask to ensure we can use the simple subtraction to sign-extend. */ +#define SIGNEXTEND(e,b) \ + ((unsigned_word) \ + (((e) & ((uword64) 1 << ((b) - 1))) \ + ? (((e) & (((uword64) 1 << (b)) - 1)) - ((uword64)1 << (b))) \ + : ((e) & (((((uword64) 1 << ((b) - 1)) - 1) << 1) | 1)))) + +/* Check if a value will fit within a halfword: */ +#define NOTHALFWORDVALUE(v) ((((((uword64)(v)>>16) == 0) && !((v) & ((unsigned)1 << 15))) || (((((uword64)(v)>>32) == 0xFFFFFFFF) && ((((uword64)(v)>>16) & 0xFFFF) == 0xFFFF)) && ((v) & ((unsigned)1 << 15)))) ? (1 == 0) : (1 == 1)) + + + +/* Floating-point operations: */ + +#include "sim-fpu.h" + +/* FPU registers must be one of the following types. All other values + are reserved (and undefined). */ +typedef enum { + fmt_single = 0, + fmt_double = 1, + fmt_word = 4, + fmt_long = 5, + /* The following are well outside the normal acceptable format + range, and are used in the register status vector. */ + fmt_unknown = 0x10000000, + fmt_uninterpreted = 0x20000000, + fmt_uninterpreted_32 = 0x40000000, + fmt_uninterpreted_64 = 0x80000000, +} FP_formats; + +unsigned64 value_fpr PARAMS ((SIM_DESC sd, address_word cia, int fpr, FP_formats)); +#define ValueFPR(FPR,FMT) value_fpr (sd, cia, (FPR), (FMT)) + +void store_fpr PARAMS ((SIM_DESC sd, address_word cia, int fpr, FP_formats fmt, unsigned64 value)); +#define StoreFPR(FPR,FMT,VALUE) store_fpr (sd, cia, (FPR), (FMT), (VALUE)) + +int NaN PARAMS ((unsigned64 op, FP_formats fmt)); +int Infinity PARAMS ((unsigned64 op, FP_formats fmt)); +int Less PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +int Equal PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 AbsoluteValue PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 Negate PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 Add PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Sub PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Multiply PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Divide PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Recip PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 SquareRoot PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 convert PARAMS ((SIM_DESC sd, address_word cia, int rm, unsigned64 op, FP_formats from, FP_formats to)); +#define Convert(rm,op,from,to) convert(sd,cia,rm,op,from,to) + +/* Macro to update FPSR condition-code field. This is complicated by + the fact that there is a hole in the index range of the bits within + the FCSR register. Also, the number of bits visible depends on the + MIPS ISA version being supported. */ + +#define SETFCC(cc,v) {\ + int bit = ((cc == 0) ? 23 : (24 + (cc)));\ + FCSR = ((FCSR & ~(1 << bit)) | ((v) << bit));\ +} +#define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1 : 0) + +/* This should be the COC1 value at the start of the preceding + instruction: */ +#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0) + +#if 1 +#define SizeFGR() (WITH_TARGET_WORD_BITSIZE) +#else +/* They depend on the CPU being simulated */ +#define SizeFGR() ((WITH_TARGET_WORD_BITSIZE == 64 && ((SR & status_FR) == 1)) ? 64 : 32) +#endif + +/* Standard FCRS bits: */ +#define IR (0) /* Inexact Result */ +#define UF (1) /* UnderFlow */ +#define OF (2) /* OverFlow */ +#define DZ (3) /* Division by Zero */ +#define IO (4) /* Invalid Operation */ +#define UO (5) /* Unimplemented Operation */ + +/* Get masks for individual flags: */ +#if 1 /* SAFE version */ +#define FP_FLAGS(b) (((unsigned)(b) < 5) ? (1 << ((b) + 2)) : 0) +#define FP_ENABLE(b) (((unsigned)(b) < 5) ? (1 << ((b) + 7)) : 0) +#define FP_CAUSE(b) (((unsigned)(b) < 6) ? (1 << ((b) + 12)) : 0) +#else +#define FP_FLAGS(b) (1 << ((b) + 2)) +#define FP_ENABLE(b) (1 << ((b) + 7)) +#define FP_CAUSE(b) (1 << ((b) + 12)) +#endif + +#define FP_FS (1 << 24) /* MIPS III onwards : Flush to Zero */ + +#define FP_MASK_RM (0x3) +#define FP_SH_RM (0) +#define FP_RM_NEAREST (0) /* Round to nearest (Round) */ +#define FP_RM_TOZERO (1) /* Round to zero (Trunc) */ +#define FP_RM_TOPINF (2) /* Round to Plus infinity (Ceil) */ +#define FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */ +#define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM) + + + +/* Integer ALU operations: */ + +#include "sim-alu.h" + +#define ALU32_END(ANS) \ + if (ALU32_HAD_OVERFLOW) \ + SignalExceptionIntegerOverflow (); \ + (ANS) = ALU32_OVERFLOW_RESULT + + +#define ALU64_END(ANS) \ + if (ALU64_HAD_OVERFLOW) \ + SignalExceptionIntegerOverflow (); \ + (ANS) = ALU64_OVERFLOW_RESULT; + +/* start-sanitize-r5900 */ + +#define BYTES_IN_MMI_REGS (sizeof(signed_word) + sizeof(signed_word)) +#define HALFWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/2) +#define WORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/4) +#define DOUBLEWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/8) + +#define BYTES_IN_MIPS_REGS (sizeof(signed_word)) +#define HALFWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/2) +#define WORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/4) +#define DOUBLEWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/8) + +/* SUB_REG_FETCH - return as lvalue some sub-part of a "register" + T - type of the sub part + TC - # of T's in the mips part of the "register" + I - index (from 0) of desired sub part + A - low part of "register" + A1 - high part of register +*/ +#define SUB_REG_FETCH(T,TC,A,A1,I) \ +(*(((I) < (TC) ? (T*)(A) : (T*)(A1)) \ + + (CURRENT_HOST_BYTE_ORDER == BIG_ENDIAN \ + ? ((TC) - 1 - (I) % (TC)) \ + : ((I) % (TC)) \ + ) \ + ) \ + ) + +/* +GPR_(R,I) - return, as lvalue, the I'th of general register R + where has two letters: + 1 is S=signed or U=unsigned + 2 is B=byte H=halfword W=word D=doubleword +*/ + +#define SUB_REG_SB(A,A1,I) SUB_REG_FETCH(signed8, BYTES_IN_MIPS_REGS, A, A1, I) +#define SUB_REG_SH(A,A1,I) SUB_REG_FETCH(signed16, HALFWORDS_IN_MIPS_REGS, A, A1, I) +#define SUB_REG_SW(A,A1,I) SUB_REG_FETCH(signed32, WORDS_IN_MIPS_REGS, A, A1, I) +#define SUB_REG_SD(A,A1,I) SUB_REG_FETCH(signed64, DOUBLEWORDS_IN_MIPS_REGS, A, A1, I) + +#define SUB_REG_UB(A,A1,I) SUB_REG_FETCH(unsigned8, BYTES_IN_MIPS_REGS, A, A1, I) +#define SUB_REG_UH(A,A1,I) SUB_REG_FETCH(unsigned16, HALFWORDS_IN_MIPS_REGS, A, A1, I) +#define SUB_REG_UW(A,A1,I) SUB_REG_FETCH(unsigned32, WORDS_IN_MIPS_REGS, A, A1, I) +#define SUB_REG_UD(A,A1,I) SUB_REG_FETCH(unsigned64, DOUBLEWORDS_IN_MIPS_REGS, A, A1, I) + +#define GPR_SB(R,I) SUB_REG_SB(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_SH(R,I) SUB_REG_SH(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_SW(R,I) SUB_REG_SW(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_SD(R,I) SUB_REG_SD(®ISTERS[R], ®ISTERS1[R], I) + +#define GPR_UB(R,I) SUB_REG_UB(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_UH(R,I) SUB_REG_UH(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_UW(R,I) SUB_REG_UW(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_UD(R,I) SUB_REG_UD(®ISTERS[R], ®ISTERS1[R], I) + + +#define RS_SB(I) SUB_REG_SB(&rs_reg, &rs_reg1, I) +#define RS_SH(I) SUB_REG_SH(&rs_reg, &rs_reg1, I) +#define RS_SW(I) SUB_REG_SW(&rs_reg, &rs_reg1, I) +#define RS_SD(I) SUB_REG_SD(&rs_reg, &rs_reg1, I) + +#define RS_UB(I) SUB_REG_UB(&rs_reg, &rs_reg1, I) +#define RS_UH(I) SUB_REG_UH(&rs_reg, &rs_reg1, I) +#define RS_UW(I) SUB_REG_UW(&rs_reg, &rs_reg1, I) +#define RS_UD(I) SUB_REG_UD(&rs_reg, &rs_reg1, I) + +#define RT_SB(I) SUB_REG_SB(&rt_reg, &rt_reg1, I) +#define RT_SH(I) SUB_REG_SH(&rt_reg, &rt_reg1, I) +#define RT_SW(I) SUB_REG_SW(&rt_reg, &rt_reg1, I) +#define RT_SD(I) SUB_REG_SD(&rt_reg, &rt_reg1, I) + +#define RT_UB(I) SUB_REG_UB(&rt_reg, &rt_reg1, I) +#define RT_UH(I) SUB_REG_UH(&rt_reg, &rt_reg1, I) +#define RT_UW(I) SUB_REG_UW(&rt_reg, &rt_reg1, I) +#define RT_UD(I) SUB_REG_UD(&rt_reg, &rt_reg1, I) + + + +#define LO_SB(I) SUB_REG_SB(&LO, &LO1, I) +#define LO_SH(I) SUB_REG_SH(&LO, &LO1, I) +#define LO_SW(I) SUB_REG_SW(&LO, &LO1, I) +#define LO_SD(I) SUB_REG_SD(&LO, &LO1, I) + +#define LO_UB(I) SUB_REG_UB(&LO, &LO1, I) +#define LO_UH(I) SUB_REG_UH(&LO, &LO1, I) +#define LO_UW(I) SUB_REG_UW(&LO, &LO1, I) +#define LO_UD(I) SUB_REG_UD(&LO, &LO1, I) + +#define HI_SB(I) SUB_REG_SB(&HI, &HI1, I) +#define HI_SH(I) SUB_REG_SH(&HI, &HI1, I) +#define HI_SW(I) SUB_REG_SW(&HI, &HI1, I) +#define HI_SD(I) SUB_REG_SD(&HI, &HI1, I) + +#define HI_UB(I) SUB_REG_UB(&HI, &HI1, I) +#define HI_UH(I) SUB_REG_UH(&HI, &HI1, I) +#define HI_UW(I) SUB_REG_UW(&HI, &HI1, I) +#define HI_UD(I) SUB_REG_UD(&HI, &HI1, I) + +/* end-sanitize-r5900 */ + + + + +struct _sim_cpu { + + + /* The following are internal simulator state variables: */ +#define CPU_CIA(CPU) (PC) + address_word dspc; /* delay-slot PC */ +#define DSPC ((STATE_CPU (sd,0))->dspc) + + /* Issue a delay slot instruction immediatly by re-calling + idecode_issue */ +#define DELAY_SLOT(TARGET) \ + do { \ + address_word target = (TARGET); \ + instruction_word delay_insn; \ + sim_events_slip (sd, 1); \ + CIA = CIA + 4; \ + STATE |= simDELAYSLOT; \ + delay_insn = IMEM (CIA); \ + idecode_issue (sd, delay_insn, (CIA)); \ + STATE &= ~simDELAYSLOT; \ + NIA = target; \ + } while (0) +#define NULLIFY_NEXT_INSTRUCTION() \ + do { \ + sim_events_slip (sd, 1); \ + dotrace (sd, tracefh, 2, NIA, 4, "load instruction"); \ + NIA = CIA + 8; \ + } while (0) + + + + /* State of the simulator */ + unsigned int state; + unsigned int dsstate; +#define STATE ((STATE_CPU (sd,0))->state) +#define DSSTATE ((STATE_CPU (sd,0))->dsstate) + +/* Flags in the "state" variable: */ +#define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */ +#define simHALTIN (1 << 3) /* 0 = run; 1 = halt on interrupt */ +#define simTRACE (1 << 8) /* 0 = do nothing; 1 = trace address activity */ +#define simPCOC0 (1 << 17) /* COC[1] from current */ +#define simPCOC1 (1 << 18) /* COC[1] from previous */ +#define simDELAYSLOT (1 << 24) /* 0 = do nothing; 1 = delay slot entry exists */ +#define simSKIPNEXT (1 << 25) /* 0 = do nothing; 1 = skip instruction */ +#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */ +#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */ + +#define ENGINE_ISSUE_PREFIX_HOOK() \ + { \ + /* Set previous flag, depending on current: */ \ + if (STATE & simPCOC0) \ + STATE |= simPCOC1; \ + else \ + STATE &= ~simPCOC1; \ + /* and update the current value: */ \ + if (GETFCC(0)) \ + STATE |= simPCOC0; \ + else \ + STATE &= ~simPCOC0; \ + } + + +/* This is nasty, since we have to rely on matching the register + numbers used by GDB. Unfortunately, depending on the MIPS target + GDB uses different register numbers. We cannot just include the + relevant "gdb/tm.h" link, since GDB may not be configured before + the sim world, and also the GDB header file requires too much other + state. */ + +#ifndef TM_MIPS_H +#define LAST_EMBED_REGNUM (89) +#define NUM_REGS (LAST_EMBED_REGNUM + 1) +/* start-sanitize-r5900 */ +#undef NUM_REGS +#define NUM_REGS (128) +/* end-sanitize-r5900 */ +#endif + +/* To keep this default simulator simple, and fast, we use a direct + vector of registers. The internal simulator engine then uses + manifests to access the correct slot. */ + + unsigned_word registers[LAST_EMBED_REGNUM + 1]; + int register_widths[NUM_REGS]; +#define REGISTERS ((STATE_CPU (sd,0))->registers) + +#define GPR (®ISTERS[0]) +#define FGRIDX (38) +#define FGR (®ISTERS[FGRIDX]) +#define LO (REGISTERS[33]) +#define HI (REGISTERS[34]) +#define PC (REGISTERS[37]) +#define CAUSE (REGISTERS[36]) +#define SRIDX (32) +#define SR (REGISTERS[SRIDX]) /* CPU status register */ +#define FCR0IDX (71) +#define FCR0 (REGISTERS[FCR0IDX]) /* really a 32bit register */ +#define FCR31IDX (70) +#define FCR31 (REGISTERS[FCR31IDX]) /* really a 32bit register */ +#define FCSR (FCR31) +#define Debug (REGISTERS[86]) +#define DEPC (REGISTERS[87]) +#define EPC (REGISTERS[88]) +#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */ + + unsigned_word c0_config_reg; +#define C0_CONFIG ((STATE_CPU (sd,0))->c0_config_reg) + +/* The following are pseudonyms for standard registers */ +#define ZERO (REGISTERS[0]) +#define V0 (REGISTERS[2]) +#define A0 (REGISTERS[4]) +#define A1 (REGISTERS[5]) +#define A2 (REGISTERS[6]) +#define A3 (REGISTERS[7]) +#define SP (REGISTERS[29]) +#define RA (REGISTERS[31]) + + /* Keep the current format state for each register: */ + FP_formats fpr_state[32]; +#define FPR_STATE ((STATE_CPU (sd, 0))->fpr_state) + + + /* Slots for delayed register updates. For the moment we just have a + fixed number of slots (rather than a more generic, dynamic + system). This keeps the simulator fast. However, we only allow + for the register update to be delayed for a single instruction + cycle. */ +#define PSLOTS (5) /* Maximum number of instruction cycles */ + int pending_in; + int pending_out; + int pending_total; + int pending_slot_count[PSLOTS]; + int pending_slot_reg[PSLOTS]; + unsigned_word pending_slot_value[PSLOTS]; +#define PENDING_IN ((STATE_CPU (sd, 0))->pending_in) +#define PENDING_OUT ((STATE_CPU (sd, 0))->pending_out) +#define PENDING_TOTAL ((STATE_CPU (sd, 0))->pending_total) +#define PENDING_SLOT_COUNT ((STATE_CPU (sd, 0))->pending_slot_count) +#define PENDING_SLOT_REG ((STATE_CPU (sd, 0))->pending_slot_reg) +#define PENDING_SLOT_VALUE ((STATE_CPU (sd, 0))->pending_slot_value) + +#if 0 + + /* The following are not used for MIPS IV onwards: */ +#define PENDING_FILL(r,v) {\ +/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL); */\ + if (PENDING_SLOT_REG[PENDING_IN] != (LAST_EMBED_REGNUM + 1))\ + sim_io_eprintf(sd,"Attempt to over-write pending value\n");\ + PENDING_SLOT_COUNT[PENDING_IN] = 2;\ + PENDING_SLOT_REG[PENDING_IN] = (r);\ + PENDING_SLOT_VALUE[PENDING_IN] = (uword64)(v);\ +/*printf("DBG: FILL reg %d value = 0x%s\n",(r),pr_addr(v));*/\ + PENDING_TOTAL++;\ + PENDING_IN++;\ + if (PENDING_IN == PSLOTS)\ + PENDING_IN = 0;\ +/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);*/\ + } +#endif + + + /* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic + read-write instructions. It is set when a linked load occurs. It + is tested and cleared by the conditional store. It is cleared + (during other CPU operations) when a store to the location would + no longer be atomic. In particular, it is cleared by exception + return instructions. */ + int llbit; +#define LLBIT ((STATE_CPU (sd, 0))->llbit) + + +/* The HIACCESS and LOACCESS counts are used to ensure that + corruptions caused by using the HI or LO register to close to a + following operation are spotted. */ + + int hiaccess; + int loaccess; +#define HIACCESS ((STATE_CPU (sd, 0))->hiaccess) +#define LOACCESS ((STATE_CPU (sd, 0))->loaccess) + /* start-sanitize-r5900 */ + int hi1access; + int lo1access; +#define HI1ACCESS ((STATE_CPU (sd, 0))->hi1access) +#define LO1ACCESS ((STATE_CPU (sd, 0))->lo1access) + /* end-sanitize-r5900 */ +#if 1 + /* The 4300 and a few other processors have interlocks on hi/lo + register reads, and hence do not have this problem. To avoid + spurious warnings, we just disable this always. */ +#define CHECKHILO(s) +#else + unsigned_word HLPC; + /* If either of the preceding two instructions have accessed the HI + or LO registers, then the values they see should be + undefined. However, to keep the simulator world simple, we just + let them use the value read and raise a warning to notify the + user: */ +#define CHECKHILO(s) {\ + if ((HIACCESS != 0) || (LOACCESS != 0)) \ + sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\ +} + /* start-sanitize-r5900 */ +#undef CHECKHILO +#define CHECKHILO(s) {\ + if ((HIACCESS != 0) || (LOACCESS != 0) || (HI1ACCESS != 0) || (LO1ACCESS != 0))\ + sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\ +} + /* end-sanitize-r5900 */ +#endif + + + /* start-sanitize-r5900 */ + /* The R5900 has 128 bit registers, but the hi 64 bits are only + touched by multimedia (MMI) instructions. The normal mips + instructions just use the lower 64 bits. To avoid changing the + older parts of the simulator to handle this weirdness, the high + 64 bits of each register are kept in a separate array + (registers1). The high 64 bits of any register are by convention + refered by adding a '1' to the end of the normal register's name. + So LO still refers to the low 64 bits of the LO register, LO1 + refers to the high 64 bits of that same register. */ + + signed_word registers1[LAST_EMBED_REGNUM + 1]; +#define REGISTERS1 ((STATE_CPU (sd, 0))->registers1) +#define GPR1 (®ISTERS1[0]) +#define LO1 (REGISTERS1[32]) +#define HI1 (REGISTERS1[33]) +#define REGISTER_SA (124) + + unsigned_word sa; /* the shift amount register */ +#define SA ((STATE_CPU (sd, 0))->sa) + + /* end-sanitize-r5900 */ + /* start-sanitize-vr5400 */ + + /* The MDMX ISA has a very very large accumulator */ + unsigned8 acc[3 * 8]; + /* end-sanitize-vr5400 */ + + sim_cpu_base base; +}; + + +/* MIPS specific simulator watch config */ + +void watch_options_install PARAMS ((SIM_DESC sd)); + +struct swatch { + sim_event *pc; + sim_event *clock; + sim_event *cycles; +}; + + +/* FIXME: At present much of the simulator is still static */ +struct sim_state { + + struct swatch watch; + + sim_cpu cpu[1]; +#if (WITH_SMP) +#define STATE_CPU(sd,n) (&(sd)->cpu[n]) +#else +#define STATE_CPU(sd,n) (&(sd)->cpu[0]) +#endif + + sim_state_base base; +}; + + + +/* Status information: */ + +/* TODO : these should be the bitmasks for these bits within the + status register. At the moment the following are VR4300 + bit-positions: */ +#define status_KSU_mask (0x3) /* mask for KSU bits */ +#define status_KSU_shift (3) /* shift for field */ +#define ksu_kernel (0x0) +#define ksu_supervisor (0x1) +#define ksu_user (0x2) +#define ksu_unknown (0x3) + +#define status_IE (1 << 0) /* Interrupt enable */ +#define status_EXL (1 << 1) /* Exception level */ +#define status_RE (1 << 25) /* Reverse Endian in user mode */ +#define status_FR (1 << 26) /* enables MIPS III additional FP registers */ +#define status_SR (1 << 20) /* soft reset or NMI */ +#define status_BEV (1 << 22) /* Location of general exception vectors */ +#define status_TS (1 << 21) /* TLB shutdown has occurred */ +#define status_ERL (1 << 2) /* Error level */ +#define status_RP (1 << 27) /* Reduced Power mode */ + +#define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */ + +/* NOTE: We keep the following status flags as bit values (1 for true, + 0 for false). This allows them to be used in binary boolean + operations without worrying about what exactly the non-zero true + value is. */ + +/* UserMode */ +#define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0) + +/* BigEndianMem */ +/* Hardware configuration. Affects endianness of LoadMemory and + StoreMemory and the endianness of Kernel and Supervisor mode + execution. The value is 0 for little-endian; 1 for big-endian. */ +#define BigEndianMem (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) +/*(state & simBE) ? 1 : 0)*/ + +/* ReverseEndian */ +/* This mode is selected if in User mode with the RE bit being set in + SR (Status Register). It reverses the endianness of load and store + instructions. */ +#define ReverseEndian (((SR & status_RE) && UserMode) ? 1 : 0) + +/* BigEndianCPU */ +/* The endianness for load and store instructions (0=little;1=big). In + User mode this endianness may be switched by setting the state_RE + bit in the SR register. Thus, BigEndianCPU may be computed as + (BigEndianMem EOR ReverseEndian). */ +#define BigEndianCPU (BigEndianMem ^ ReverseEndian) /* Already bits */ + + + +/* Exceptions: */ + +/* NOTE: These numbers depend on the processor architecture being + simulated: */ +#define Interrupt (0) +#define TLBModification (1) +#define TLBLoad (2) +#define TLBStore (3) +#define AddressLoad (4) +#define AddressStore (5) +#define InstructionFetch (6) +#define DataReference (7) +#define SystemCall (8) +#define BreakPoint (9) +#define ReservedInstruction (10) +#define CoProcessorUnusable (11) +#define IntegerOverflow (12) /* Arithmetic overflow (IDT monitor raises SIGFPE) */ +#define Trap (13) +#define FPE (15) +#define DebugBreakPoint (16) +#define Watch (23) + +/* The following exception code is actually private to the simulator + world. It is *NOT* a processor feature, and is used to signal + run-time errors in the simulator. */ +#define SimulatorFault (0xFFFFFFFF) + +void signal_exception (SIM_DESC sd, address_word cia, int exception, ...); +#define SignalException(exc,instruction) signal_exception (sd, cia, (exc), (instruction)) +#define SignalExceptionInterrupt() signal_exception (sd, NULL_CIA, Interrupt) +#define SignalExceptionInstructionFetch() signal_exception (sd, cia, InstructionFetch) +#define SignalExceptionAddressStore() signal_exception (sd, cia, AddressStore) +#define SignalExceptionAddressLoad() signal_exception (sd, cia, AddressLoad) +#define SignalExceptionSimulatorFault(buf) signal_exception (sd, cia, SimulatorFault, buf) +#define SignalExceptionFPE() signal_exception (sd, cia, FPE) +#define SignalExceptionIntegerOverflow() signal_exception (sd, cia, IntegerOverflow) +#define SignalExceptionCoProcessorUnusable() signal_exception (sd, cia, CoProcessorUnusable) + + +/* Co-processor accesses */ + +void cop_lw PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg, unsigned int memword)); +void cop_ld PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg, uword64 memword)); +unsigned int cop_sw PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg)); +uword64 cop_sd PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg)); + +#define COP_LW(coproc_num,coproc_reg,memword) cop_lw(sd,cia,coproc_num,coproc_reg,memword) +#define COP_LD(coproc_num,coproc_reg,memword) cop_ld(sd,cia,coproc_num,coproc_reg,memword) +#define COP_SW(coproc_num,coproc_reg) cop_sw(sd,cia,coproc_num,coproc_reg) +#define COP_SD(coproc_num,coproc_reg) cop_sd(sd,cia,coproc_num,coproc_reg) + +void decode_coproc PARAMS ((SIM_DESC sd, address_word cia, unsigned int instruction)); +#define DecodeCoproc(instruction) decode_coproc(sd, cia, (instruction)) + + + +/* Memory accesses */ + +/* The following are generic to all versions of the MIPS architecture + to date: */ + +/* Memory Access Types (for CCA): */ +#define Uncached (0) +#define CachedNoncoherent (1) +#define CachedCoherent (2) +#define Cached (3) + +#define isINSTRUCTION (1 == 0) /* FALSE */ +#define isDATA (1 == 1) /* TRUE */ +#define isLOAD (1 == 0) /* FALSE */ +#define isSTORE (1 == 1) /* TRUE */ +#define isREAL (1 == 0) /* FALSE */ +#define isRAW (1 == 1) /* TRUE */ +/* The parameter HOST (isTARGET / isHOST) is ignored */ +#define isTARGET (1 == 0) /* FALSE */ +/* #define isHOST (1 == 1) TRUE */ + +/* The "AccessLength" specifications for Loads and Stores. NOTE: This + is the number of bytes minus 1. */ +#define AccessLength_BYTE (0) +#define AccessLength_HALFWORD (1) +#define AccessLength_TRIPLEBYTE (2) +#define AccessLength_WORD (3) +#define AccessLength_QUINTIBYTE (4) +#define AccessLength_SEXTIBYTE (5) +#define AccessLength_SEPTIBYTE (6) +#define AccessLength_DOUBLEWORD (7) +#define AccessLength_QUADWORD (15) + +int address_translation PARAMS ((SIM_DESC sd, address_word cia, address_word vAddr, int IorD, int LorS, address_word *pAddr, int *CCA, int raw)); +#define AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) \ +address_translation(sd,cia,vAddr,IorD,LorS,pAddr,CCA,raw) + +void load_memory PARAMS ((SIM_DESC sd, address_word cia, uword64* memvalp, uword64* memval1p, int CCA, int AccessLength, address_word pAddr, address_word vAddr, int IorD)); +#define LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) \ +load_memory(sd,cia,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD) + +void store_memory PARAMS ((SIM_DESC sd, address_word cia, int CCA, int AccessLength, uword64 MemElem, uword64 MemElem1, address_word pAddr, address_word vAddr)); +#define StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) \ +store_memory(sd,cia,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr) + +void cache_op PARAMS ((SIM_DESC sd, address_word cia, int op, address_word pAddr, address_word vAddr, unsigned int instruction)); +#define CacheOp(op,pAddr,vAddr,instruction) cache_op(sd,cia,op,pAddr,vAddr,instruction) + +void sync_operation PARAMS ((SIM_DESC sd, address_word cia, int stype)); +#define SyncOperation(stype) sync_operation (sd, cia, (stype)) + +void prefetch PARAMS ((SIM_DESC sd, address_word cia, int CCA, address_word pAddr, address_word vAddr, int DATA, int hint)); +#define Prefetch(CCA,pAddr,vAddr,DATA,hint) prefetch(sd,cia,CCA,pAddr,vAddr,DATA,hint) + +unsigned32 ifetch32 PARAMS ((SIM_DESC sd, address_word cia, address_word vaddr)); +#define IMEM(CIA) ifetch32 (SD, (CIA), (CIA)) + +void dotrace PARAMS ((SIM_DESC sd, FILE *tracefh, int type, SIM_ADDR address, int width, char *comment, ...)); +FILE *tracefh; + +#endif diff --git a/sim/txvu/tconfig.in b/sim/txvu/tconfig.in new file mode 100644 index 00000000000..66f2b6f33bc --- /dev/null +++ b/sim/txvu/tconfig.in @@ -0,0 +1,17 @@ +/* mips target configuration file. */ + +/* Define this if the simulator supports profiling. + See the mips simulator for an example. + This enables the `-p foo' and `-s bar' options. + The target is required to provide sim_set_profile{,_size}. */ +#define SIM_HAVE_PROFILE + +/* Define this if the simulator uses an instruction cache. + See the h8/300 simulator for an example. + This enables the `-c size' option to set the size of the cache. + The target is required to provide sim_set_simcache_size. */ +/* #define SIM_HAVE_SIMCACHE */ + +/* Define this if the target cpu is bi-endian + and the simulator supports it. */ +#define SIM_HAVE_BIENDIAN diff --git a/sim/txvu/vr5400.igen b/sim/txvu/vr5400.igen new file mode 100644 index 00000000000..2e77ea2c31e --- /dev/null +++ b/sim/txvu/vr5400.igen @@ -0,0 +1,241 @@ + + +// Integer Instructions +// -------------------- +// +// MulAcc is the Multiply Accumulator. +// This register is mapped on the the HI and LO registers. +// Upper 32 bits of MulAcc is mapped on to lower 32 bits of HI register. +// Lower 32 bits of MulAcc is mapped on to lower 32 bits of LO register. + + +:function:::unsigned64:MulAcc: +{ + unsigned64 result = U8_4 (HI, LO); + return result; +} + +:function:::void:SET_MulAcc:unsigned64 value +{ + *AL4_8 (&HI) = VH4_8 (value); + *AL4_8 (&LO) = VL4_8 (value); +} + +:function:::signed64:SignedMultiply:signed32 l, signed32 r +{ + signed64 result = (signed64) l * (signed64) r; + return result; +} + +:function:::unsigned64:UnsignedMultiply:unsigned32 l, unsigned32 r +{ + unsigned64 result = (unsigned64) l * (unsigned64) r; + return result; +} + +:function:::unsigned64:Low32Bits:unsigned64 value +{ + unsigned64 result = (signed64) (signed32) VL4_8 (value); + return result; +} + +:function:::unsigned64:High32Bits:unsigned64 value +{ + unsigned64 result = (signed64) (signed32) VH4_8 (value); + return result; +} + + + +// Multiply and Move LO. +000000,5.RS,5.RT,5.RD,00001,011000::::MUL +"mul r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 + SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply and Move LO. +000000,5.RS,5.RT,5.RD,00001,011001::::MULU +"mulu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 + UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Multiply and Move HI. +000000,5.RS,5.RT,5.RD,01001,011000::::MULHI +"mulhi r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 + SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply and Move HI. +000000,5.RS,5.RT,5.RD,01001,011001::::MULHIU +"mulhiu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 + UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); +} + + +// Multiply, Negate and Move LO. +000000,5.RS,5.RT,5.RD,00011,011000::::MULS +"muls r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 - SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply, Negate and Move LO. +000000,5.RS,5.RT,5.RD,00011,011001::::MULSU +"mulsu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 - UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Multiply, Negate and Move HI. +000000,5.RS,5.RT,5.RD,01011,011000::::MULSHI +"mulshi r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 - SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply, Negate and Move HI. +000000,5.RS,5.RT,5.RD,01011,011001::::MULSHIU +"mulshiu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, 0 - UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); +} + + +// Multiply, Accumulate and Move LO. +000000,5.RS,5.RT,5.RD,00101,011000::::MACC +"macc r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) + SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply, Accumulate and Move LO. +000000,5.RS,5.RT,5.RD,00101,011001::::MACCU +"maccu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) + UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Multiply, Accumulate and Move HI. +000000,5.RS,5.RT,5.RD,01101,011000::::MACCHI +"macchi r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) + SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply, Accumulate and Move HI. +000000,5.RS,5.RT,5.RD,01101,011001::::MACCHIU +"macchiu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) + UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); + +} + +// Multiply, Negate, Accumulate and Move LO. +000000,5.RS,5.RT,5.RD,00111,011000::::MSAC +"msac r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) - SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply, Negate, Accumulate and Move LO. +000000,5.RS,5.RT,5.RD,00111,011001::::MSACU +"msacu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) - UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = Low32Bits (SD_, MulAcc (SD_)); +} + +// Multiply, Negate, Accumulate and Move HI. +000000,5.RS,5.RT,5.RD,01111,011000::::MSACHI +"msachi r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) - SignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); +} + +// Unsigned Multiply, Negate, Accumulate and Move HI. +000000,5.RS,5.RT,5.RD,01111,011001::::MSACHIU +"msachiu r, r, r" +*vr5400: +{ + SET_MulAcc (SD_, MulAcc (SD_) - UnsignedMultiply (SD_, GPR[RS], GPR[RT])); + GPR[RD] = High32Bits (SD_, MulAcc (SD_)); +} + + +// Rotate Right. +000000,00001,5.RT,5.RD,5.SHIFT,000010::::ROR +"ror r, r, " +*vr5400: +{ + int s = SHIFT; + GPR[RD] = ROTR32 (GPR[RT], s); +} + +// Rotate Right Variable. +000000,5.RS,5.RT,5.RD,00001,000110::::RORV +"rorv r, r, " +*vr5400: +{ + int s = MASKED (GPR[RS], 4, 0); + GPR[RD] = ROTR32 (GPR[RT], s); +} + +// Double Rotate Right. +000000,00001,5.RT,5.RD,5.SHIFT,111010::::DROR +"dror r, r, " +*vr5400: +{ + int s = SHIFT; + GPR[RD] = ROTR64 (GPR[RT], s); +} + +// Double Rotate Right Plus 32. +000000,00001,5.RT,5.RD,5.SHIFT,111110::::DROR32 +"dror32 r, r, " +*vr5400: +{ + int s = SHIFT + 32; + GPR[RD] = ROTR64 (GPR[RT], s); +} + +// Double Rotate Right Variable. +000000,5.RS,5.RT,5.RD,00001,010110::::DRORV +"drorv r, r, " +*vr5400: +{ + int s = MASKED (GPR[RS], 5, 0); + GPR[RD] = ROTR64 (GPR[RT], s); +} diff --git a/sim/txvu/vu0.c b/sim/txvu/vu0.c new file mode 100644 index 00000000000..9c82b9f68c7 --- /dev/null +++ b/sim/txvu/vu0.c @@ -0,0 +1,81 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#include "sim-main.h" + +#include "device.h" +#include "vu0.h" + +static char vu0_mem0_buffer[VU0_MEM0_SIZE]; +static char vu0_mem1_buffer[VU0_MEM1_SIZE]; + +int +vu0_io_read_buffer(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Read!\n", me->name); + return nr_bytes; +} + +int +vu0_io_write_buffer(device *me, + const void *source, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Write!\n", me->name); + return nr_bytes; +} + +device vu0_device = + { + "vu0", + &vu0_io_read_buffer, + &vu0_io_write_buffer + }; + +void +vu0_attach(SIM_DESC sd) +{ + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + VU0_REGISTER_WINDOW_START, + VU0_REGISTER_WINDOW_SIZE /*nr_bytes*/, + 0 /*modulo*/, + &vu0_device, + NULL /*buffer*/); + + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + VU0_MEM0_WINDOW_START, + VU0_MEM0_SIZE /*nr_bytes*/, + 0 /*modulo*/, + 0 /*device*/, + &vu0_mem0_buffer /*buffer*/); + + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + VU0_MEM1_WINDOW_START, + VU0_MEM1_SIZE /*nr_bytes*/, + 0 /*modulo*/, + 0 /*device*/, + &vu0_mem1_buffer /*buffer*/); +} diff --git a/sim/txvu/vu0.h b/sim/txvu/vu0.h new file mode 100644 index 00000000000..021a6f69eae --- /dev/null +++ b/sim/txvu/vu0.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef VU0_H_ +#define VU0_H_ + +#include "sim-main.h" + +void vu0_attach(SIM_DESC sd); + +#define VU0_MEM0_WINDOW_START 0x11000000 +#define VU0_MEM0_SIZE 0x1000 /* 4K = 4096 */ + +#define VU0_MEM1_WINDOW_START 0x11004000 +#define VU0_MEM1_SIZE 0x1000 /* 4K = 4096 */ + +#define VU0_REGISTER_WINDOW_START 0x10000c00 + +#define VU0_VF00 0x10000c00 +/* ... */ +#define VU0_VF31 0x10000df0 + +#define VU0_VI00 0x10000e00 +/* ... */ +#define VU0_VI15 0x10000ef0 + +/* ... */ + +#define VPE0_STAT 0x10000fd0 + +#define VU0_REGISTER_WINDOW_END 0x10000fe0 + +#define VU0_REGISTER_WINDOW_SIZE (VU0_REGISTER_WINDOW_END - VU0_REGISTER_WINDOW_START) + +#endif diff --git a/sim/txvu/vu1.c b/sim/txvu/vu1.c new file mode 100644 index 00000000000..049edd39d2a --- /dev/null +++ b/sim/txvu/vu1.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#include "sim-main.h" + +#include "device.h" +#include "vu1.h" + +static char vu1_mem0_buffer[VU1_MEM0_SIZE]; +static char vu1_mem1_buffer[VU1_MEM1_SIZE]; + +int +vu1_io_read_buffer(device *me, + void *dest, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Read!\n", me->name); + +printf(" vu1_mem0[0] = %d\n", *(int*)&vu1_mem0_buffer[0]); +printf(" vu1_mem1[0] = %d\n", *(int*)&vu1_mem1_buffer[0]); + + return nr_bytes; +} + +int +vu1_io_write_buffer(device *me, + const void *source, + int space, + address_word addr, + unsigned nr_bytes, + sim_cpu *processor, + sim_cia cia) +{ + printf("%s: Write!\n", me->name); + return nr_bytes; +} + +device vu1_device = + { + "vu1", + &vu1_io_read_buffer, + &vu1_io_write_buffer + }; + +void +vu1_attach(SIM_DESC sd) +{ + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + VU1_REGISTER_WINDOW_START, + VU1_REGISTER_WINDOW_SIZE /*nr_bytes*/, + 0 /*modulo*/, + &vu1_device, + NULL /*buffer*/); + + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + VU1_MEM0_WINDOW_START, + VU1_MEM0_SIZE /*nr_bytes*/, + 0 /*modulo*/, + 0 /*device*/, + &vu1_mem0_buffer /*buffer*/); + + sim_core_attach (sd, + NULL, + 0 /*level*/, + access_read_write, + 0 /*space ???*/, + VU1_MEM1_WINDOW_START, + VU1_MEM1_SIZE /*nr_bytes*/, + 0 /*modulo*/, + 0 /*device*/, + &vu1_mem1_buffer /*buffer*/); +} diff --git a/sim/txvu/vu1.h b/sim/txvu/vu1.h new file mode 100644 index 00000000000..f336361ce83 --- /dev/null +++ b/sim/txvu/vu1.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1998, Cygnus Solutions + + */ + +#ifndef VU1_H_ +#define VU1_H_ + +#include "sim-main.h" + +void vu1_attach(SIM_DESC sd); + +#define VU1_MEM0_WINDOW_START 0x11008000 +#define VU1_MEM0_SIZE 0x4000 /* 16K = 16384 */ + +#define VU1_MEM1_WINDOW_START 0x1100c000 +#define VU1_MEM1_SIZE 0x4000 /* 16K = 16384 */ + +#define VU1_REGISTER_WINDOW_START 0x11007000 + +#define VU1_VF00 0x11007000 +/* ... */ +#define VU1_VF31 0x110071f0 + +#define VU1_VI00 0x11007200 +/* ... */ +#define VU1_VI15 0x110072f0 + +/* ... */ + +#define VPE1_STAT 0x11007370 + +#define VU1_REGISTER_WINDOW_END 0x11007380 + +#define VU1_REGISTER_WINDOW_SIZE (VU1_REGISTER_WINDOW_END - VU1_REGISTER_WINDOW_START) + +#endif