tendra-4.1.2.orig/ 40775 1750 1750 0 6626056515 13247 5ustar brooniebroonietendra-4.1.2.orig/COPYRIGHT100644 1750 1750 2253 6506672661 14642 0ustar brooniebroonie WELCOME TO THE TENDRA 4.1.2 RELEASE =================================== Crown Copyright (c) 1997, 1998 This TenDRA(r) Computer Program is subject to Copyright owned by the United Kingdom Secretary of State for Defence acting through the Defence Evaluation and Research Agency (DERA). It is made available to Recipients with a royalty-free licence for its use, reproduction, transfer to other parties and amendment for any purpose not excluding product development provided that any such use et cetera shall be deemed to be acceptance of the following conditions: (1) Its Recipients shall ensure that this Notice is reproduced upon any copies or amended versions of it; (2) Any amended version of it shall be clearly marked to show both the nature of and the organisation responsible for the relevant amendment or amendments; (3) Its onward transfer from a recipient to another party shall be deemed to be that party's acceptance of these conditions; (4) DERA gives no warranty or assurance as to its quality or suitability for any purpose and DERA accepts no liability whatsoever in relation to any use to which it may be put. tendra-4.1.2.orig/INSTALL100755 1750 1750 50623 6506672661 14427 0ustar brooniebroonie#!/bin/sh # # Crown Copyright (c) 1997, 1998 # # This TenDRA(r) Computer Program is subject to Copyright # owned by the United Kingdom Secretary of State for Defence # acting through the Defence Evaluation and Research Agency # (DERA). It is made available to Recipients with a # royalty-free licence for its use, reproduction, transfer # to other parties and amendment for any purpose not excluding # product development provided that any such use et cetera # shall be deemed to be acceptance of the following conditions:- # # (1) Its Recipients shall ensure that this Notice is # reproduced upon any copies or amended versions of it; # # (2) Any amended version of it shall be clearly marked to # show both the nature of and the organisation responsible # for the relevant amendment or amendments; # # (3) Its onward transfer from a recipient to another # party shall be deemed to be that party's acceptance of # these conditions; # # (4) DERA gives no warranty or assurance as to its # quality or suitability for any purpose and DERA accepts # no liability whatsoever in relation to any use to which # it may be put. # # # STANDARD DIRECTORIES # # These directories are used to configure where the release is to be # installed: # # BASE_DIR gives the directory in which the source has been # installed (i.e. the directory containing this script). # # PUBLIC_BIN gives the directory in which the public executables # (tcc, tchk and tspec) are to be installed. If # PUBLIC_BIN is left blank then the public executables # will be installed in the private executables # directory. # # INSTALL_DIR gives the directory in which the configuration files, # include files, private executables, libraries etc. # are to be installed. # # COMMON_DIR gives the sub-directory of INSTALL_DIR in which the # target independent components are to be installed. # # MACH_DIR gives the sub-directory of INSTALL_DIR in which the # target dependent components are to be installed. # # MAN_DIR gives the directory in which the manual pages are # to be installed. # # WORK_DIR gives the working directory in which binary object # files etc. created during the build process will # be stored. # # TMP_DIR gives a temporary directory, used both by this # script and by tcc (so make sure that there is # plenty of free space). # BASE_DIR=/usr/local/src/TenDRA-4.1.2 PUBLIC_BIN=/usr/local/bin INSTALL_DIR=/usr/local/lib/TenDRA COMMON_DIR=${INSTALL_DIR}/lib MACH_DIR=${INSTALL_DIR}/machines MAN_DIR=/usr/local/man WORK_DIR=${BASE_DIR}/work TEMP_DIR=/var/tmp # # BUILD OPTIONS # # These flags control which components of the release should be installed. # # If BUILD_UPDATE is true then the public executables and their configuration # files will be installed (this has to be done on every target platform). # # If BUILD_MACHINE is true then all the other target dependent components # will be installed (this also has to be done on every target platform). # # If BUILD_COMMON is true then the target independent components will be # installed (this only has to be done once, indeed if the release is being # built simultaneously on several platforms then the builds can conflict # with each other, so start the quickest machine off first to install # the complete release, and get the other machines to only install the # target dependent sections). # # BUILD_OK is set to false if an error occurs. # # COMMENT controls whether or not this script prints comments as it goes # along. # BUILD_UPDATE=true BUILD_MACHINE=true BUILD_COMMON=true BUILD_OK=true COMMENT=echo # # COMPILER INFORMATION # # These variables give information on the compiler to be used to install # the release. CC gives the compiler. CCOPTS and LIBOPTS give any target # specific options required by the build, and are set by this script. It # is recommended that any extra flags which the user requires are made # part of the definition of CC, so CC="gcc -O" would install using gcc # in optimising mode. TCCOPTS controls the extra configuration options # required when bootstrapping the system using tcc. It should be set to: # # TCCOPTS= for tcc, # TCCOPTS="TCCOPTS=" for other compilers. # # To install the bootstrapped compiler, install first using cc or gcc. # Then remove the work directory (WORK_DIR), change the compiler to tcc, # and install again. Bootstrapping is recommended (all our testing is # on the bootstrapped compiler). # # SYS_INCLUDES gives a list of include file directories to be searched # when building the TDF API libraries. # # STRIP may be set to "strip" in order to ensure that the installed # executables are stripped. # # RANLIB is used on those platforms on which system libraries need to be # ranlib-ed. # # EXEC_SUFFIX is used on those platforms where executable names need to # have a particular suffix, for example it may be set to ".exe". # CC=cc CCOPTS= LIBOPTS= TCCOPTS="TCCOPTS=" SYS_INCLUDES="-I/usr/include" STRIP=: RANLIB=ranlib EXEC_SUFFIX= # # COMMAND LINE ARGUMENTS # # The easiest way of configuring this installation script is by direct # editing, however these command line options may be used to make minor # alterations. # for ARG in $* do case ${ARG} in -cc) CC=cc ; TCCOPTS="TCCOPTS=" ;; -gcc) CC=gcc ; TCCOPTS="TCCOPTS=" ;; -tcc) CC=tcc ; TCCOPTS="" ;; -g) CC="${CC} -g" ;; -O) CC="${CC} -O" ;; -exe) EXEC_SUFFIX=".exe" ;; -quiet) COMMENT=":" ;; -strip) STRIP=strip ;; -target) BUILD_COMMON=false ;; -update) BUILD_COMMON=false ; BUILD_MACHINE=false ;; *) ${COMMENT} "Unknown option, ${ARG}" ;; esac done # # PRINT THE COPYRIGHT NOTICE # # The copyright notice is printed. This also checks for the most common # error, running INSTALL before configuring it to the system. # if [ ! -f ${BASE_DIR}/COPYRIGHT ] then ${COMMENT} "Please set BASE_DIR in the INSTALL script" exit 1 fi cat ${BASE_DIR}/COPYRIGHT # # FIND HOST TYPE # # The method for finding the operating system type, operating system version # and CPU type is decidedly dirty. A program tuname, similar to uname, but # more uniform across platforms, is installed. Feel free to hack tuname # around if it doesn't work properly. # ${COMMENT} building host type determiner, tuname ... TUNAME=${TEMP_DIR}/tuname_$$${EXEC_SUFFIX} MACH_HEADER=${TEMP_DIR}/mach_$$.h SRC=${BASE_DIR}/src/utilities/tuname cd ${TEMP_DIR} || exit 1 make -f ${SRC}/Makefile CC="${CC}" ${TCCOPTS}\ BASE=${BASE_DIR} NAME=${TUNAME} all if [ -f ${TUNAME} ] then MACH_OS=`${TUNAME} -s` MACH_VERS=`${TUNAME} -r` MACH_CPU=`${TUNAME} -m` MACH_EXEC=`${TUNAME} -e` ${TUNAME} -D > ${MACH_HEADER} rm -f ${TUNAME} if [ "X${MACH_OS}X" = "XunknownX" ] then ${COMMENT} Unknown machine type exit 1 fi else ${COMMENT} Unknown machine type exit 1 fi ${COMMENT} ${COMMENT} Operating system = ${MACH_OS} ${COMMENT} Operating system version = ${MACH_VERS} ${COMMENT} Processor type = ${MACH_CPU} ${COMMENT} Executable type = ${MACH_EXEC} # # FIND MACHINE DEPENDENT FLAGS # # The target specific options required to build the system on the various # platforms are stored in separate configuration files. Feel free to add # or modify these files as necessary. # MACH_OPTS=${BASE_DIR}/src/build/${MACH_OS}.opt if [ -f ${MACH_OPTS} ] then . ${MACH_OPTS} fi # # CREATE DIRECTORIES # # All the directories required for the installation are created. The PATH # is also set to pick up the private and public executables during # installation. # MACH_BASE=${MACH_DIR}/${MACH_OS}/${MACH_VERS}/${MACH_CPU} MACH_WORK=${WORK_DIR}/${MACH_OS}/${MACH_VERS}/${MACH_CPU} if [ "X${PUBLIC_BIN}X" = "XX" ] then PUBLIC_BIN=${MACH_BASE}/bin fi PATH=${MACH_BASE}/bin:${PUBLIC_BIN}:/usr/ccs/bin:${PATH} export PATH if ${BUILD_UPDATE} then CREATE_DIRS="${MACH_DIR}\ ${MACH_DIR}/${MACH_OS}\ ${MACH_DIR}/${MACH_OS}/${MACH_VERS}\ ${MACH_BASE}\ ${MACH_BASE}/bin\ ${MACH_BASE}/env\ ${MACH_BASE}/lib\ ${MACH_BASE}/lib/diag\ ${MACH_BASE}/lib/sys\ ${PUBLIC_BIN}" else CREATE_DIRS= fi if ${BUILD_MACHINE} then MACH_DIRS="${WORK_DIR} ${WORK_DIR}/${MACH_OS}\ ${WORK_DIR}/${MACH_OS}/${MACH_VERS}\ ${MACH_WORK}" else MACH_DIRS= fi if ${BUILD_COMMON} then COMMON_DIRS="${INSTALL_DIR}\ ${COMMON_DIR}\ ${MAN_DIR}\ ${MAN_DIR}/man1\ ${MAN_DIR}/man5" else COMMON_DIRS= fi for DIR in ${COMMON_DIRS} ${CREATE_DIRS} ${MACH_DIRS} do if [ ! -d ${DIR} ] then ${COMMENT} creating ${DIR} ... mkdir ${DIR} || exit 1 fi done ${COMMENT} # # BUILD PROGRAMS # # The various program executables are now built. The list of executables # is stored in the PROGRAMS file. Note that each executable has its own # Makefile which can be used to install the executable in isolation, or # during development work. # MACH_SED=${TEMP_DIR}/mach$$.sed cat > ${MACH_SED} << EOF 1,\$s/MACH_OS/${MACH_OS}/g 1,\$s/MACH_CPU/${MACH_CPU}/g EOF for PROG in `sed -f ${MACH_SED} ${BASE_DIR}/src/build/PROGRAMS` do NAME=`echo ${PROG} | sed -e 's/:.*//'` SRC=${BASE_DIR}/src/`echo ${PROG} | sed -e 's/.*://'` # # Build program # if ${BUILD_MACHINE} then ${COMMENT} building ${NAME} ... if [ ! -d ${MACH_WORK}/${NAME} ] then ${COMMENT} creating ${MACH_WORK}/${NAME} ... mkdir ${MACH_WORK}/${NAME} || exit 1 fi cd ${MACH_WORK}/${NAME} || exit 1 EXEC=${MACH_BASE}/bin/${NAME}${EXEC_SUFFIX} make -f ${SRC}/Makefile CC="${CC} ${CCOPTS}" ${TCCOPTS}\ BASE=${BASE_DIR} NAME=${EXEC} all || BUILD_OK=false if [ -f ${EXEC} ] then ${STRIP} ${EXEC} else ${COMMENT} compilation failed ... BUILD_OK=false fi ${COMMENT} fi # # Copy manual pages # if ${BUILD_COMMON} then for SUFFIX in 1 5 do for MANPAGE in ${SRC}/*.${SUFFIX} do if [ -f ${MANPAGE} ] then NEWPAGE=${MAN_DIR}/man${SUFFIX}/`basename ${MANPAGE}` rm -f ${NEWPAGE} cp ${MANPAGE} ${NEWPAGE} fi done done fi done rm -f ${MACH_SED} # # BUILD DYNAMIC LINKER # # On some platforms a dynamic linker is required to handle the TDF # initial_value construct (used by C++'s non-constant initialisation etc.). # This is built at this stage. # if ${BUILD_MACHINE} then ${COMMENT} building machine dependent components ... SRC=${BASE_DIR}/src/lib/machines/${MACH_OS}/${MACH_CPU}/src if [ -f ${SRC}/Makefile ] then cd ${MACH_BASE}/lib/sys || exit 1 make -f ${SRC}/Makefile CC="${CC} ${CCOPTS}" ${TCCOPTS}\ BASE=${BASE_DIR} pre || BUILD_OK=false ${COMMENT} fi fi # # INSTALL ENVIRONMENTS # # The user interfaces to the TenDRA compiler, tcc and tchk, use configuration # files called environments to configure them to the particular details of # the platform on which they are installed (including where the private # executables, libraries etc. are to be found). If the release is moved # then only the environments need to be re-installed, by setting BUILD_UPDATE # to true, but BUILD_COMMON and BUILD_MACHINE to false. # if ${BUILD_UPDATE} then ${COMMENT} installing tcc environments ... ENV_SED=${TEMP_DIR}/env$$.sed cat > ${ENV_SED} << EOF 1,\$s%-MACH-%${MACH_OS}/${MACH_CPU}%g 1,\$s%-MACHDIR-%${MACH_BASE}%g 1,\$s%-BINDIR-%${MACH_BASE}/bin%g 1,\$s%-ENVDIR-%${MACH_BASE}/env%g 1,\$s%-LIBDIR-%${MACH_BASE}/lib%g 1,\$s%-INCLDIR-%${COMMON_DIR}/include%g 1,\$s%-STARTUPDIR-%${COMMON_DIR}/startup%g 1,\$s%-TMPDIR-%${TEMP_DIR}%g EOF cd ${MACH_BASE}/env || exit 1 SRC=${BASE_DIR}/src/lib/env ENVIRON_DIRS="${SRC}/common\ ${SRC}/${MACH_OS}/common/common\ ${SRC}/${MACH_OS}/common/${MACH_CPU}\ ${SRC}/${MACH_OS}/${MACH_EXEC}/common\ ${SRC}/${MACH_OS}/${MACH_EXEC}/${MACH_CPU}\ ${SRC}/${MACH_OS}/${MACH_VERS}/common\ ${SRC}/${MACH_OS}/${MACH_VERS}/${MACH_CPU}" for DIR in ${ENVIRON_DIRS} do if [ -d ${DIR} ] then for ENVFILE in ${DIR}/* do if [ -f ${ENVFILE} ] then NEWFILE=`basename ${ENVFILE}` ${COMMENT} ${ENVFILE} '->' ${NEWFILE} rm -f ${NEWFILE} sed -f ${ENV_SED} ${ENVFILE} > ${NEWFILE} fi done fi done ${COMMENT} default.extra '>>' default rm -f default.new cat default default.extra > default.new rm -f default mv default.new default rm -f ${ENV_SED} ${COMMENT} fi # # INSTALL WRAPPER FUNCTIONS # # The public executables are actually wrapper scripts which call the # actual programs from the private executables directory with the appropriate # configuration options. # if ${BUILD_UPDATE} then ${COMMENT} installing tcc ... rm -f ${PUBLIC_BIN}/tcc cat > ${PUBLIC_BIN}/tcc << EOF #!/bin/sh exec ${MACH_BASE}/bin/tcc1${EXEC_SUFFIX} -Y${MACH_BASE}/env/default \${@+"\$@"} EOF chmod +x ${PUBLIC_BIN}/tcc ${COMMENT} ${COMMENT} installing tchk ... rm -f ${PUBLIC_BIN}/tchk cat > ${PUBLIC_BIN}/tchk << EOF #!/bin/sh exec ${MACH_BASE}/bin/tcc1${EXEC_SUFFIX} -Y${MACH_BASE}/env/default -ch \${@+"\$@"} EOF chmod +x ${PUBLIC_BIN}/tchk ${COMMENT} ${COMMENT} installing tspec ... rm -f ${PUBLIC_BIN}/tspec cat > ${PUBLIC_BIN}/tspec << EOF #!/bin/sh TSPEC_INPUT=${BASE_DIR}/src/lib/apis TSPEC_INCL_OUTPUT=${COMMON_DIR}/include TSPEC_SRC_OUTPUT=${COMMON_DIR}/building export TSPEC_INPUT TSPEC_INCL_OUTPUT TSPEC_SRC_OUTPUT exec ${MACH_BASE}/bin/tspec1${EXEC_SUFFIX} \${@+"\$@"} EOF chmod +x ${PUBLIC_BIN}/tspec ${COMMENT} fi # # INSTALL START-UP FILES # # The machine independent compiler configuration files are installed # (cp -r would do as well as tar, but not all machines support it). # if ${BUILD_COMMON} then ${COMMENT} installing start-up files ... cd ${BASE_DIR}/src/lib || exit 1 rm -f ${MACH_WORK}/startup.tar tar cvf ${MACH_WORK}/startup.tar startup cd ${COMMON_DIR} || exit 1 rm -rf startup tar xvf ${MACH_WORK}/startup.tar rm -f ${MACH_WORK}/startup.tar ${COMMENT} fi # # INSTALL API DESCRIPTIONS # # The TenDRA API descriptions for the various supported APIs are installed # using the tspec executable built above. The list of APIs is given in a # separate file, APIS. # if ${BUILD_COMMON} then for API in `cat ${BASE_DIR}/src/build/APIS` do ${COMMENT} installing API ${API} ... ${PUBLIC_BIN}/tspec -w -v ${API} ${COMMENT} all done ${COMMENT} done fi # # INSTALL MACHINE DEPENDENT HEADERS # # The machine dependent include files and configuration files are now # installed. These are used in particular during TDF API library building # and when the compiler is configured to use the system headers. # if ${BUILD_MACHINE} then ${COMMENT} installing machine dependent headers ... SRC=${BASE_DIR}/src/lib/machines/${MACH_OS}/${MACH_CPU} if [ -d ${SRC} ] then cd ${SRC} || exit 1 rm -f ${MACH_WORK}/machine.tar tar cvf ${MACH_WORK}/machine.tar include startup cd ${MACH_BASE} || exit 1 rm -rf include rm -rf startup tar xvf ${MACH_WORK}/machine.tar rm -f ${MACH_WORK}/machine.tar cp ${MACH_HEADER} startup/machine.h fi ${COMMENT} fi rm -f ${MACH_HEADER} # # BUILD MACHINE DEPENDENT COMPONENTS # # Any machine dependent libraries etc. are now built. This includes the # basic TDF token definitions which describe the machine to the compiler. # if ${BUILD_MACHINE} then ${COMMENT} building machine dependent components ... SRC=${BASE_DIR}/src/lib/machines/${MACH_OS}/${MACH_CPU}/src if [ -f ${SRC}/Makefile ] then cd ${MACH_BASE}/lib/sys || exit 1 make -f ${SRC}/Makefile CC="${CC} ${CCOPTS}" ${TCCOPTS}\ BASE=${BASE_DIR} all || BUILD_OK=false fi ${COMMENT} fi # # BUILD API LIBRARIES # # And now the tricky bit. The TDF API libraries are built from the TenDRA # API descriptions and the implementation of the API as described in the # system headers. # # Although this has been tested to the operating system versions listed # in the supported platforms section of the release notes, it is possible # that it may fail for other operating system versions. Provided the # ansi library builds, you have enough to play with, but to get other # libraries through, you may need to modify the machine dependent include # and start-up files in src/lib/machines//, using the existing # files as a template. If you get really stuck; you've read all the # documentation, and looked at all what I've done in similar circumstances, # you can email me (Rob) at the address on the web page, but make this a # last resort - I do have other things to do. # # Note that each library is built twice, firstly without diagnostic # information and secondly with. Really only the ones with diagnostics # are required (the diagnostic information is ignored if not needed), # but building both is traditional. # DIAG_MSG= DIAG_CC=tcc for LIBDIR in lib lib/diag do # # Build basic token definitions # if ${BUILD_MACHINE} then ${COMMENT} building basic C token definitions${DIAG_MSG} ... if [ ! -d ${MACH_WORK}/${LIBDIR} ] then ${COMMENT} creating ${MACH_WORK}/${LIBDIR} ... mkdir ${MACH_WORK}/${LIBDIR} || exit 1 fi for API in `cat ${BASE_DIR}/src/build/APIS` ansi cpp do API_NAME=`echo ${API} | sed -e 's%/%_%g'` if [ ! -d ${MACH_WORK}/${LIBDIR}/${API_NAME} ] then ${COMMENT} creating ${MACH_WORK}/${LIBDIR}/${API_NAME} ... mkdir ${MACH_WORK}/${LIBDIR}/${API_NAME} || exit 1 fi done SRC=${BASE_DIR}/src/lib/machines/${MACH_OS}/${MACH_CPU}/tokens if [ -d ${SRC} ] then cd ${MACH_WORK}/${LIBDIR}/ansi || exit 1 make -f ${SRC}/Makefile TCC="${DIAG_CC}" BASE=${BASE_DIR}\ basic || BUILD_OK=false fi ${COMMENT} SRC=${BASE_DIR}/src/lib/cpp/tokens if [ -d ${SRC} ] then ${COMMENT} building basic C++ token definitions${DIAG_MSG} ... cd ${MACH_WORK}/${LIBDIR}/cpp || exit 1 make -f ${SRC}/Makefile TCC="${DIAG_CC}" BASE=${BASE_DIR}\ all || BUILD_OK=false ${COMMENT} fi fi # # Build API token libraries # if ${BUILD_MACHINE} then cd ${MACH_WORK}/${LIBDIR} || exit 1 for API in `cat ${BASE_DIR}/src/build/APIS` do API_NAME=`echo ${API} | sed -e 's%/%_%g'` SRC=${COMMON_DIR}/building/${API}.api if [ -d ${SRC} ] then ${COMMENT} building ${API} API token library${DIAG_MSG} ... rm -f ${API_NAME}/Makefile cat > ${API_NAME}/Makefile << EOF BASE=${MACH_BASE} LIB=\${BASE}/${LIBDIR}/${API_NAME}.tl SRC=${COMMON_DIR}/building STARTUP=\${BASE}/startup WORK=. TLIB=tld -mc TDI=${DIAG_CC} -Fj -Ybuilding -Y32bit -I\${BASE}/include ${SYS_INCLUDES} TDP=echo EOF cat ${SRC}/Makefile >> ${API_NAME}/Makefile if [ -f ${MACH_BASE}/startup/${API_NAME}.h ] then make -f ${API_NAME}/Makefile all || BUILD_OK=false else ${COMMENT} skipped fi ${COMMENT} fi done fi # # Build TDF standard token library # if ${BUILD_MACHINE} then SRC=${BASE_DIR}/src/lib/machines/${MACH_OS}/${MACH_CPU}/tokens if [ -d ${SRC} ] then ${COMMENT} building TDF standard token library${DIAG_MSG} ... LIB=${MACH_BASE}/${LIBDIR}/target_tok.tl cd ${MACH_WORK}/${LIBDIR}/ansi || exit 1 make -f ${SRC}/Makefile LIB=${LIB} TCC="${DIAG_CC}"\ BASE=${BASE_DIR} all || BUILD_OK=false ${COMMENT} fi fi # # Now build with diagnostics # DIAG_MSG=" (with diagnostics)" DIAG_CC="tcc -g" done # # BUILD SUPPORT LIBRARIES # # The support libraries are now built. The list of libraries to be built # is stored in a separate file, LIBRARIES. It bears repeating that the # C++ support library only contains the minimum language support features. # if ${BUILD_MACHINE} then SRC=${BASE_DIR}/src/lib/machines/common/src if [ -f ${SRC}/Makefile ] then ${COMMENT} building crtp_n.o ... cd ${MACH_BASE}/lib/sys || exit 1 make -f ${SRC}/Makefile BASE=${BASE_DIR} all || BUILD_OK=false ${COMMENT} fi for PROG in `cat ${BASE_DIR}/src/build/LIBRARIES` do NAME=`echo ${PROG} | sed -e 's/:.*//'` SRC=${BASE_DIR}/src/`echo ${PROG} | sed -e 's/.*://'` if [ -f ${SRC}/Makefile ] then ${COMMENT} building ${NAME} ... if [ ! -d ${MACH_WORK}/${NAME} ] then ${COMMENT} creating ${MACH_WORK}/${NAME} ... mkdir ${MACH_WORK}/${NAME} || exit 1 fi cd ${MACH_WORK}/${NAME} || exit 1 LIB=${MACH_BASE}/lib/sys/lib${NAME}.a make -f ${SRC}/Makefile BASE=${BASE_DIR} NAME=${LIB}\ MACHOPTS="${LIBOPTS}" RANLIB="${RANLIB}" all || BUILD_OK=false if [ ! -f ${LIB} ] then ${COMMENT} compilation failed ... BUILD_OK=false fi ${COMMENT} fi done fi # # END OF INSTALLATION SCRIPT # # Phew! # if ${BUILD_OK} then ${COMMENT} installation completed successfully else ${COMMENT} installation completed with errors fi exit 0 tendra-4.1.2.orig/README100644 1750 1750 31607 6507733177 14255 0ustar brooniebroonieTENDRA 4.1.2 RELEASE INFORMATION ================================ COPYRIGHT INFORMATION --------------------- Please read the file COPYRIGHT for the DERA copyright notice. In addition, the power installer (src/installers/power and its subdirectories) are subject to the following copyright notice: Copyright (c) 1996 Open Software Foundation, Inc. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation. OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. and the Motif 1.2 API description (src/lib/apis/motif1.2 and its subdirectories) are subject to the following copyright: COPYRIGHT NOTICE This program is the proprietary property of IXI Ltd, a subsidiary of the Santa Cruz Operation (SCO). Use, reproduction, production of amended versions and/or transfer of this program is permitted PROVIDED THAT: (a) This legend be preserved on any such reproduction and amended version. (b) Any recipient of such reproduction or amended version accept the conditions set out in this legend. IXI accepts no liability whatsoever in relation to any use to which this program may be put and gives no warranty as to the program's suitability for any purpose. All rights reserved. Copyright (c) 1995, 1996 DOWNLOADING INFORMATION ----------------------- The TenDRA 4.1.2 release is available via the Web site: http://alph.dera.gov.uk/TenDRA/ or by FTP from alph.dera.gov.uk, in the directory /pub/TenDRA. It consists of the gzipped tar archive: TenDRA-4.1.2.tar.gz (about 3.9MB - see the actual site for the precise figure), plus the optional documentation, comprising a copy of the documents available from the TenDRA web site: TenDRA-4.1.2-doc.tar.gz (about 760kB). INSTALLATION INFORMATION ------------------------ The main source archive, TenDRA-4.1.2.tar.gz, can be extracted using: gzip -d TenDRA-4.1.2.tar.gz tar xvf TenDRA-4.1.2.tar to give a directory, TenDRA-4.1.2, containing the release source. If you also want to install the release documentation you will also need to download TenDRA-4.1.2-doc.tar.gz and extract this as above. The documentation is extracted into the subdirectory TenDRA-4.1.2/doc. The release is installed by running the shell script INSTALL found in the main source directory. The default configuration installs the public executables into /usr/local/bin, the private executables, libraries, configuration files etc. into /usr/local/lib/TenDRA, and the manual pages into /usr/local/man. It also assumes that the source has been installed in /usr/local/src/TenDRA-4.1.2. These locations may be changed by editing the INSTALL script (which is fully commented). Note that the installation script makes no distinction between build and installation due to the large degree of interdependence between the various tools. If a separate build phase is required then the system should be installed into a local directory and then re-installed into its permanent location. Other installation details, such as which compiler to use, can be specified using command-line options to INSTALL, or by editing the script. For example: INSTALL -gcc will install the release using gcc as the compiler. After this the work directory can be removed, and: INSTALL -tcc run to bootstrap the system. It is suggested that the output of INSTALL is piped into a log file for later examination if things go wrong (the script will report whether or not there were errors in the installation, but it isn't always reliable). The comments in the INSTALL script should be consulted for more details. KNOWN INSTALLATION PROBLEMS --------------------------- Several of the components have been updated to use the posix1 or xpg4 APIs rather than the older posix and xpg3. Due to an error in the TenDRA-4.1.1 posix1 API specification, this means that they may not compile under the TenDRA-4.1.1 (although they will with TenDRA-4.1.2 of course). If this is an issue then modify the Makefiles to use the older APIs. The location of certain system linker files has changed in later versions of Linux. The solution is to change the tcc environment files to reflect the new locations. This can be done by: cd src/lib/env/linux/elf mv 80x86 80x86.old mv 80x86.new 80x86 before running INSTALL. ORGANISATION OF RELEASE ----------------------- The src subdirectory, which contains the source code, is organised into the following top-level directories: build which contains various information used during installation; installers which contains the compiler back-ends, which translate the compiler intermediate form, TDF, to the appropriate machine instructions; lib which contains everything not included in the other directories; producers which contains the compiler front-ends, which translate C and C++ to the compiler intermediate form, TDF; tools which contains various tools for manipulating, viewing and generating TDF; utilities which contains various compiler generator utilities used in the development of the TenDRA software. The installers directory is split into a common section, containing code which is used by all the back ends, plus a directory for each of the target CPUs: 680x0 Motorola 68020, 68030 and 68040, 80x86 Intel i386, i486 and Pentium, alpha DEC Alpha, hppa HP Precision Architecture, mips SGI/DEC MIPS, power POWER, ppc601 POWER PC, sparc SPARC. Each CPU directory is also divided into a common section, plus a directory for each of the target operating systems: 680x0/sunos 680x0 on SunOS 4, 80x86/cygwin32 Intel on Cygwin32, 80x86/freebsd Intel on FreeBSD, 80x86/linux Intel on Linux, 80x86/sco Intel on SCO, 80x86/solaris Intel on Solaris 2, 80x86/svr4.2 Intel on Unixware, alpha/osf1 Alpha on OSF/1, hppa/hpux HP-PA on HP-UX, mips/irix MIPS on Irix, mips/ultrix MIPS on Ultrix, power/aix POWER on AIX, ppc601/aix POWER PC on AIX, sparc/solaris SPARC on Solaris 2, sparc/sunos SPARC on SunOS 4. The common installer directory is also subdivided, for convenience, into a number of different subdirectories: construct which contains the main routines for transforming and optimising the internal representation; diag which contains routines for reading and processing diagnostic information contained within the TDF; dwarf which contains routines for writing out diagnostic information as DWARF directives; dwarf2 which contains routines for writing out diagnostic information as DWARF 2 directives; linkinfo which contains routines for reading linkage information contained within the TDF; reader which contains the main routine for reading the input TDF and building up the internal representation; templ which contains template files used to generate the TDF reading routines. The producers subdirectory is divided into a common directory, containing code shared by both the C and C++ producers, plus directories c and cpp, containing the language specific components. The differences between the languages are driven from the parser, which is found in the syntax subdirectory of c and cpp. C merely uses a subset of the routines available for the C++ producer, with a number of run-time or compile-time flags to control the differences between the languages. The common producer directory is divided, for convenience into a number of subdirectories: construct which contains the main routines for building up and checking the internal representation; obj_c which contains macros describing the internal representation; obj_templ which contains various template files used in automatic code generation; obj_tok which contains TenDRA tokens describing the internal representation; output which contains the routines of writing the internal representation to disk as TDF; parse which contains routines for lexical analysis and preprocessing; utility which contains routines for error reporting, memory allocation etc. The tools directory contains the source for a number of different tools: disp translates TDF into a human readable form; pl is a structured TDF assembler; tcc is the front-end to the TenDRA compiler; tld links a number of TDF capsules into one; tnc is an unstructured TDF assember and disassembler; tspec is a specification tool used in the TenDRA API descriptions. The utilities directory contains the source for a number of different compiler generator tools: calculus is used to manage the complex type system used in the producers; lexi is a simple lexical analyser generator (lex is not used); make_err is used to manage the producer error catalogue; make_mf is a simple makefile generator; make_tdf is used to generate TDF encoding and decoding routines from the TDF specification; shared contains code common to a number of tools; sid is a parser generator (yacc is not used); tuname is a uname-like utility used in the installation process. The lib directory is divided into a number of subdirectories: apis containing the TenDRA API descriptions used in its API checking facilities; cpp containing the C++ support library (note that this is only a minimal language support subset of the complete C++ standard library); env containing the compiler front-end configuration files; libtdf containing a support library certain aspects of TDF (such as 64 bits integers); machines containing machine specific tools, libraries and configuration files; startup containing the C and C++ producer configuration files; tdf containing a description of the TDF specification used by make_tdf to generate TDF encoders and decoders. ORGANISATION OF INSTALLED RELEASE --------------------------------- The installation script creates three shell scripts in the public binaries directory (/usr/local/bin in the default set-up). These are the compiler, tcc, the stand-alone static checker, tchk, and the API specification tool, tspec. The manual pages for these tools and those which they invoke are installed in the manual page directory (/usr/local/man in the default set-up). The remaining files are installed into the TenDRA configuration directory (/usr/local/lib/TenDRA in the default set-up). The remainder of this section describes the files installed into this directory. For each target machine, a directory: machines/// is created to hold the machine dependent files, where denotes the operating system name, denotes the operating system version and denotes the CPU type (as above). This machine directory has five subdirectories: bin containing the compiled executables for this machine; advanced users may wish to put this directory on their PATH, but the executables in the public binaries directory should suffice for most users; env containing the tcc configuration files for this machine (see above); include containing the modified system headers for this machine; these are copied directly from the src/lib/machines directory in the release; lib containing the API token libraries describing the implementation of the various standard APIs on this machine; the generation of these libraries from the API descriptions and the system headers is the most complex part of the installation; startup containing the compiler configuration files describing how to navigate through the system headers on this machine; these are copied directly from the src/lib/machines directory in the release. The remainder of the directories created by the installation are common to all machines. These are: building containing files automatically generated by tspec from the API descriptions which are used to build the API token libraries; these files are only used during installation and may be deleted if space is short; include containing the include files automatically generated by tspec from the API descriptions; startup containing the C and C++ producer configuration files copied directly from the src/lib/startup directory in the release. tendra-4.1.2.orig/src/ 40755 1750 1750 0 6507735201 14026 5ustar brooniebroonietendra-4.1.2.orig/src/build/ 40755 1750 1750 0 6507734507 15135 5ustar brooniebroonietendra-4.1.2.orig/src/build/APIS100644 1750 1750 176 6466043112 15662 0ustar brooniebroonieansi iso cpp posix posix1 posix2 xpg3 xpg4 svid3 unix95 x5/lib x5/t x5/aw x5/mu x5/proto x5/ext x5/mit motif/1_2 gcc bsd_extn tendra-4.1.2.orig/src/build/HEADERS100644 1750 1750 16 6460152374 16157 0ustar brooniebrooniefnmatch wchar tendra-4.1.2.orig/src/build/LIBRARIES100644 1750 1750 37 6466043112 16416 0ustar brooniebroonietdf:lib/libtdf cpp:lib/cpp/src tendra-4.1.2.orig/src/build/PROGRAMS100644 1750 1750 520 6466043113 16352 0ustar brooniebrooniecalculus:utilities/calculus lexi:utilities/lexi make_err:utilities/make_err make_mf:utilities/make_mf make_tdf:utilities/make_tdf sid:utilities/sid tuname:utilities/tuname disp:tools/disp pl:tools/pl tcc1:tools/tcc tld:tools/tld tnc:tools/tnc tspec1:tools/tspec tdfc2:producers/c tcpplus:producers/cpp trans:installers/MACH_CPU/MACH_OS tendra-4.1.2.orig/src/build/TOUCH_AUTO100755 1750 1750 7505 6506672701 16675 0ustar brooniebroonie#!/bin/sh -x # # TOUCH ALL AUTOMATICALLY GENERATED FILES # # The source contains a great number of automatically generated files. # During the installation process the tools used to generate these files # are generally built before they are used, but this is not possible # for tools like calculus, lexi and sid which are defined in terms of # themselves. The datestamps on the files provided in the release # should prevent the makefiles from building the automatically generated # files in the initial installation. If the datestamps become corrupted # then this script can be used to touch all the automatically generated # files. # BASE="../.." TOUCH="touch -c" ${TOUCH} ${BASE}/src/installers/common/reader/decoder.c ${TOUCH} ${BASE}/src/installers/common/reader/ecodes.h ${TOUCH} ${BASE}/src/installers/common/reader/externs.h ${TOUCH} ${BASE}/src/installers/common/reader/inits.h ${TOUCH} ${BASE}/src/installers/common/reader/main_reads.h ${TOUCH} ${BASE}/src/installers/common/reader/temp_fns.new ${TOUCH} ${BASE}/src/producers/c/syntax/syntax*.c ${TOUCH} ${BASE}/src/producers/c/syntax/syntax.h ${TOUCH} ${BASE}/src/producers/common/obj_c/*.h ${TOUCH} ${BASE}/src/producers/common/obj_tok/*.h ${TOUCH} ${BASE}/src/producers/common/output/tdf1.h ${TOUCH} ${BASE}/src/producers/common/parse/psyntax*.c ${TOUCH} ${BASE}/src/producers/common/parse/psyntax.h ${TOUCH} ${BASE}/src/producers/common/utility/errors*.h ${TOUCH} ${BASE}/src/producers/common/utility/opts.h ${TOUCH} ${BASE}/src/producers/cpp/syntax/syntax*.c ${TOUCH} ${BASE}/src/producers/cpp/syntax/syntax.h ${TOUCH} ${BASE}/src/tools/disp/tdf.c ${TOUCH} ${BASE}/src/tools/disp/tdf.h ${TOUCH} ${BASE}/src/tools/pl/consfile.c ${TOUCH} ${BASE}/src/tools/pl/consfile.h ${TOUCH} ${BASE}/src/tools/pl/decodings.c ${TOUCH} ${BASE}/src/tools/pl/decodings.h ${TOUCH} ${BASE}/src/tools/pl/enc_nos.h ${TOUCH} ${BASE}/src/tools/pl/encodings.h ${TOUCH} ${BASE}/src/tools/pl/fnsfile.c ${TOUCH} ${BASE}/src/tools/pl/syntax.c ${TOUCH} ${BASE}/src/tools/pl/syntax.h ${TOUCH} ${BASE}/src/tools/tld/gen-errors.c ${TOUCH} ${BASE}/src/tools/tld/gen-errors.h ${TOUCH} ${BASE}/src/tools/tnc/check_exp.h ${TOUCH} ${BASE}/src/tools/tnc/tdf.c ${TOUCH} ${BASE}/src/tools/tnc/tdf.h ${TOUCH} ${BASE}/src/tools/tspec/keyword.h ${TOUCH} ${BASE}/src/tools/tspec/lexer.h ${TOUCH} ${BASE}/src/tools/tspec/syntax.c ${TOUCH} ${BASE}/src/tools/tspec/syntax.h ${TOUCH} ${BASE}/src/utilities/calculus/keyword.h ${TOUCH} ${BASE}/src/utilities/calculus/lexer.h ${TOUCH} ${BASE}/src/utilities/calculus/obj_c/*.h ${TOUCH} ${BASE}/src/utilities/calculus/obj_tok/*.h ${TOUCH} ${BASE}/src/utilities/calculus/print_def.h ${TOUCH} ${BASE}/src/utilities/calculus/read_def.h ${TOUCH} ${BASE}/src/utilities/calculus/syntax.c ${TOUCH} ${BASE}/src/utilities/calculus/syntax.h ${TOUCH} ${BASE}/src/utilities/calculus/write_def.h ${TOUCH} ${BASE}/src/utilities/lexi/keyword.h ${TOUCH} ${BASE}/src/utilities/lexi/lexer.h ${TOUCH} ${BASE}/src/utilities/lexi/syntax.c ${TOUCH} ${BASE}/src/utilities/lexi/syntax.h ${TOUCH} ${BASE}/src/utilities/make_err/keyword.h ${TOUCH} ${BASE}/src/utilities/make_err/lexer.h ${TOUCH} ${BASE}/src/utilities/make_err/obj_c/*.h ${TOUCH} ${BASE}/src/utilities/make_err/obj_tok/*.h ${TOUCH} ${BASE}/src/utilities/make_err/syntax.c ${TOUCH} ${BASE}/src/utilities/make_err/syntax.h ${TOUCH} ${BASE}/src/utilities/make_tdf/keyword.h ${TOUCH} ${BASE}/src/utilities/make_tdf/lexer.h ${TOUCH} ${BASE}/src/utilities/make_tdf/obj_c/*.h ${TOUCH} ${BASE}/src/utilities/make_tdf/obj_tok/*.h ${TOUCH} ${BASE}/src/utilities/make_tdf/syntax.c ${TOUCH} ${BASE}/src/utilities/make_tdf/syntax.h ${TOUCH} ${BASE}/src/utilities/sid/c-junk.h ${TOUCH} ${BASE}/src/utilities/sid/c-parser.c ${TOUCH} ${BASE}/src/utilities/sid/gen-errors.c ${TOUCH} ${BASE}/src/utilities/sid/gen-errors.h ${TOUCH} ${BASE}/src/utilities/sid/junk.h ${TOUCH} ${BASE}/src/utilities/sid/parser.c tendra-4.1.2.orig/src/build/VERSION100644 1750 1750 15 6466641222 16231 0ustar brooniebroonieTenDRA-4.1.1 tendra-4.1.2.orig/src/build/cygwin32.opt100755 1750 1750 34 6503206036 17346 0ustar brooniebroonie#!/bin/sh CCOPTS="-DFS_DOS" tendra-4.1.2.orig/src/build/hpux.opt100755 1750 1750 46 6466043113 16673 0ustar brooniebroonie#!/bin/sh LIBOPTS="-DBIGENDIAN_INT64" tendra-4.1.2.orig/src/build/irix.opt100755 1750 1750 27 6466043113 16661 0ustar brooniebroonie#!/bin/sh RANLIB=touch tendra-4.1.2.orig/src/build/osf1.opt100755 1750 1750 43 6506672702 16563 0ustar brooniebroonie#!/bin/sh LIBOPTS="-DNATIVE_INT64" tendra-4.1.2.orig/src/build/solaris.opt100755 1750 1750 27 6466043114 17363 0ustar brooniebroonie#!/bin/sh RANLIB=touch tendra-4.1.2.orig/src/build/sunos.opt100755 1750 1750 152 6466043114 17075 0ustar brooniebroonie#!/bin/sh if [ "X${TCCOPTS}X" != "XX" ] then CCOPTS="-DFS_NO_ANSI_ENVIRON" fi LIBOPTS="-DFS_ATEXIT=1" tendra-4.1.2.orig/src/build/svr4.2.opt100755 1750 1750 27 6466043114 16745 0ustar brooniebroonie#!/bin/sh RANLIB=touch tendra-4.1.2.orig/src/installers/ 40755 1750 1750 0 6507734613 16214 5ustar brooniebroonietendra-4.1.2.orig/src/installers/680x0/ 40755 1750 1750 0 6507734514 17001 5ustar brooniebroonietendra-4.1.2.orig/src/installers/680x0/common/ 40755 1750 1750 0 6507734514 20271 5ustar brooniebroonietendra-4.1.2.orig/src/installers/680x0/common/68k_globals.c100644 1750 1750 4411 6460152204 22631 0ustar brooniebroonie/* Crown Copyright (c) 1997 This TenDRA(r) Computer Program is subject to Copyright owned by the United Kingdom Secretary of State for Defence acting through the Defence Evaluation and Research Agency (DERA). It is made available to Recipients with a royalty-free licence for its use, reproduction, transfer to other parties and amendment for any purpose not excluding product development provided that any such use et cetera shall be deemed to be acceptance of the following conditions:- (1) Its Recipients shall ensure that this Notice is reproduced upon any copies or amended versions of it; (2) Any amended version of it shall be clearly marked to show both the nature of and the organisation responsible for the relevant amendment or amendments; (3) Its onward transfer from a recipient to another party shall be deemed to be that party's acceptance of these conditions; (4) DERA gives no warranty or assurance as to its quality or suitability for any purpose and DERA accepts no liability whatsoever in relation to any use to which it may be put. */ /* VERSION INFORMATION =================== -------------------------------------------------------------------------- $Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/68k_globals.c,v 1.1.1.1 1998/01/17 15:55:48 release Exp $ -------------------------------------------------------------------------- $Log: 68k_globals.c,v $ * Revision 1.1.1.1 1998/01/17 15:55:48 release * First version to be checked into rolling release. * Revision 1.2 1997/10/29 10:22:03 ma Replaced use_alloca with has_alloca. Revision 1.1.1.1 1997/10/13 12:42:46 ma First version. Revision 1.1 1997/10/13 09:54:22 ma First version. -------------------------------------------------------------------------- */ #include "config.h" #include "common_types.h" #include "68k_globals.h" int not_in_params = 1; int not_in_postlude = 1; int need_preserve_stack = 0; dec* cur_proc_dec = 0; int cur_proc_has_tail_call = 0; int cur_proc_use_same_callees = 0; int cur_proc_has_vcallees = 0; long cur_proc_callees_size = 0; long cur_proc_callers_size = 0; long cur_proc_env_size = 0; int apply_tag_flag = 0; tendra-4.1.2.orig/src/installers/680x0/common/68k_globals.h100644 1750 1750 4642 6460152204 22644 0ustar brooniebroonie/* Crown Copyright (c) 1997 This TenDRA(r) Computer Program is subject to Copyright owned by the United Kingdom Secretary of State for Defence acting through the Defence Evaluation and Research Agency (DERA). It is made available to Recipients with a royalty-free licence for its use, reproduction, transfer to other parties and amendment for any purpose not excluding product development provided that any such use et cetera shall be deemed to be acceptance of the following conditions:- (1) Its Recipients shall ensure that this Notice is reproduced upon any copies or amended versions of it; (2) Any amended version of it shall be clearly marked to show both the nature of and the organisation responsible for the relevant amendment or amendments; (3) Its onward transfer from a recipient to another party shall be deemed to be that party's acceptance of these conditions; (4) DERA gives no warranty or assurance as to its quality or suitability for any purpose and DERA accepts no liability whatsoever in relation to any use to which it may be put. */ /* VERSION INFORMATION =================== -------------------------------------------------------------------------- $Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/68k_globals.h,v 1.1.1.1 1998/01/17 15:55:48 release Exp $ -------------------------------------------------------------------------- $Log: 68k_globals.h,v $ * Revision 1.1.1.1 1998/01/17 15:55:48 release * First version to be checked into rolling release. * Revision 1.2 1997/10/29 10:22:05 ma Replaced use_alloca with has_alloca. Revision 1.1.1.1 1997/10/13 12:42:46 ma First version. Revision 1.1 1997/10/13 09:54:24 ma First version. -------------------------------------------------------------------------- */ #ifndef __68k_globals__ #define __68k_globals__ #include "config.h" #include "expmacs.h" #include "exp.h" /* global variables describing the current procedure */ extern int not_in_params; extern int not_in_postlude; extern int need_preserve_stack; extern dec* cur_proc_dec; extern int cur_proc_has_tail_call; extern int cur_proc_use_same_callees; extern int cur_proc_has_vcallees; extern long cur_proc_callees_size; extern long cur_proc_callers_size; extern long cur_proc_env_size; extern int apply_tag_flag; #endif tendra-4.1.2.orig/src/installers/680x0/common/codec.c100644 1750 1750 100344 6460152205 21636 0ustar brooniebroonie/* Crown Copyright (c) 1996 This TenDRA(r) Computer Program is subject to Copyright owned by the United Kingdom Secretary of State for Defence acting through the Defence Evaluation and Research Agency (DERA). It is made available to Recipients with a royalty-free licence for its use, reproduction, transfer to other parties and amendment for any purpose not excluding product development provided that any such use et cetera shall be deemed to be acceptance of the following conditions:- (1) Its Recipients shall ensure that this Notice is reproduced upon any copies or amended versions of it; (2) Any amended version of it shall be clearly marked to show both the nature of and the organisation responsible for the relevant amendment or amendments; (3) Its onward transfer from a recipient to another party shall be deemed to be that party's acceptance of these conditions; (4) DERA gives no warranty or assurance as to its quality or suitability for any purpose and DERA accepts no liability whatsoever in relation to any use to which it may be put. */ /* VERSION INFORMATION =================== -------------------------------------------------------------------------- $Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/codec.c,v 1.1.1.1 1998/01/17 15:55:49 release Exp $ -------------------------------------------------------------------------- $Log: codec.c,v $ * Revision 1.1.1.1 1998/01/17 15:55:49 release * First version to be checked into rolling release. * Revision 1.3 1997/11/13 08:27:09 ma All avs test passed (except add_to_ptr). Revision 1.2 1997/11/09 14:06:53 ma Rounding mode represented with names. Revision 1.1.1.1 1997/10/13 12:42:47 ma First version. Revision 1.5 1997/10/13 08:48:58 ma Made all pl_tests for general proc & exception handling pass. Revision 1.4 1997/09/25 06:44:49 ma All general_proc tests passed Revision 1.3 1997/06/18 10:09:22 ma Checking in before merging with Input Baseline changes. Revision 1.2 1997/04/20 11:30:17 ma Introduced gcproc.c & general_proc.[ch]. Added cases for apply_general_proc next to apply_proc in all files. Revision 1.1.1.1 1997/03/14 07:50:10 ma Imported from DRA * Revision 1.1.1.1 1996/09/20 10:56:52 john * * Revision 1.3 1996/07/30 16:29:34 john * Fixed bug, discarding side-effecting operations * * Revision 1.2 1996/07/05 14:16:20 john * Changes for spec 3.1 * * Revision 1.1.1.1 1996/03/26 15:45:08 john * * Revision 1.5 94/11/16 10:36:02 10:36:02 ra (Robert Andrews) * Added integer absolute construct. * - * * Revision 1.4 94/06/29 14:18:00 14:18:00 ra (Robert Andrews) * Added div0, rem0, max and min for TDF 3.0. * * Revision 1.3 93/11/19 16:14:42 16:14:42 ra (Robert Andrews) * Corrected order of arguments in offset_subtract. * * Revision 1.2 93/03/03 14:46:05 14:46:05 ra (Robert Andrews) * Added error handling routines. * * Revision 1.1 93/02/22 17:15:17 17:15:17 ra (Robert Andrews) * Initial revision * -------------------------------------------------------------------------- */ #include "config.h" #include "common_types.h" #include "exp.h" #include "expmacs.h" #include "flags.h" #include "shapemacs.h" #include "install_fns.h" #include "tags.h" #include "mach.h" #include "where.h" #include "codec.h" #include "coder.h" #include "operations.h" #include "utility.h" #include "mach.h" #include "instr.h" #include "codex.h" #include "instrs.h" #include "f64.h" #include "me_fns.h" #include "evaluate.h" #include "ops_shared.h" #include "mach_ins.h" extern bool have_cond ; /* CONSTRUCT A SIMILAR EXP This routine, given a where, copies the corresponding exp, and sets its sh equal to the given shape. */ exp sim_exp PROTO_N ( ( sha, w ) ) PROTO_T ( shape sha X where w ) { exp e = copyexp ( w.wh_exp ) ; sh ( e ) = sha ; return ( e ) ; } /* PROCESS A UNARY OPERATION This routine processes the unary operation described by the routine op. The operand is given by a and the result, which is of shape sha, is put into dest. The stack argument describes the current state of the stack. */ static void uop PROTO_N ( ( op, sha, a, dest, stack ) ) PROTO_T ( void ( *op ) PROTO_S ( ( shape, where, where ) ) X shape sha X exp a X where dest X ash stack ) { int old_rmode ; if ( !is_o ( name ( a ) ) ) { /* If a is not an operand, we need to calculate its value first */ if ( whereis ( dest ) == Dreg ) { /* If dest is in a D register, code a into dest */ old_rmode = crt_rmode ; coder ( dest, stack, a ) ; crt_rmode = old_rmode ; /* Now apply op to dest */ ( *op ) ( sha, dest, dest ) ; return ; } else { /* Code a into D1 */ where w ; exp e = sim_exp ( sha, D1 ) ; w = zw ( e ) ; regsinproc |= regmsk ( REG_D1 ) ; old_rmode = crt_rmode ; coder ( w, stack, a ) ; crt_rmode = old_rmode ; /* Apply op to D1 */ ( *op ) ( sha, w, dest ) ; retcell ( e ) ; if ( have_cond == 3 ) have_cond = 1 ; return ; } } /* If a is an operand, apply op directly to a */ ( *op ) ( sha, zw ( a ), dest ) ; return ; } /* PROCESS A BINARY OPERATION This routine processes the binary operation described by the routine op. The operands are given by a and b and the result, which is of shape sha, is put into dest. The stack argument describes the current state of the stack. */ static void bop PROTO_N ( ( op, sha, a, b, dest, stack ) ) PROTO_T ( void ( *op ) PROTO_S ( ( shape, where, where, where ) ) X shape sha X exp a X exp b X where dest X ash stack ) { where w, t ; bool noa = !is_o ( name ( a ) ) ; bool nob = !is_o ( name ( b ) ) ; if ( noa ) { /* If a is not an operand, we need to calculate its value first */ if ( nob ) { /* a and b cannot both not be operands */ error ( "Illegal binary operation" ) ; } t = zw ( b ) ; if ( whereis ( dest ) == Dreg && !interfere ( dest, t ) ) { /* If dest is in a D register which is not used in b, code a into dest */ coder ( dest, stack, a ) ; /* Apply op to dest and b */ ( *op ) ( sha, dest, t, dest ) ; return ; } else { /* Code a into D1 */ exp e = sim_exp ( sha, D1 ) ; w = zw ( e ) ; regsinproc |= regmsk ( REG_D1 ) ; coder ( w, stack, a ) ; /* Apply op to D1 and b */ ( *op ) ( sha, w, t, dest ) ; retcell ( e ) ; if ( have_cond == 3 ) have_cond = 1 ; return ; } } if ( nob ) { /* If b is not an operand, we need to calculate its value first */ t = zw ( a ) ; if ( whereis ( dest ) == Dreg && !interfere ( dest, t ) ) { /* If dest is in a D register which is not used in a, code b into dest */ coder ( dest, stack, b ) ; /* Apply op to a and dest */ ( *op ) ( sha, t, dest, dest ) ; return ; } else { /* Code b into D1 */ exp e = sim_exp ( sha, D1 ) ; w = zw ( e ) ; regsinproc |= regmsk ( REG_D1 ) ; coder ( w, stack, b ) ; /* Apply op to a and D1 */ ( *op ) ( sha, t, w, dest ) ; retcell ( e ) ; if ( have_cond == 3 ) have_cond = 1 ; return ; } } /* If a and b are both operands, apply op directly */ ( *op ) ( sha, zw ( a ), zw ( b ), dest ) ; return ; } /* PROCESS A LOGICAL OPERATION This routine processes the logical operation described by the routine op. This operation will be binary, commutative and associative. The operands are given by the bro-list starting at the son of e. The result is put into dest. The stack argument describes the current state of the stack. */ static void logop PROTO_N ( ( op, e, dest, stack ) ) PROTO_T ( void ( *op ) PROTO_S ( ( shape, where, where, where ) ) X exp e X where dest X ash stack ) { exp arg1 = son ( e ) ; /* First argument */ exp arg2 = bro ( arg1 ) ; /* Second argument */ exp t, u, v ; where w ; if ( last ( arg1 ) ) { /* If there is of one argument, code it into dest */ coder ( dest, stack, arg1 ) ; return ; } if ( last ( arg2 ) ) { /* If there are two arguments, use bop */ bop ( op, sh ( e ), arg1, arg2, dest, stack ) ; return ; } /* Three or more arguments : need to take care about overlap between dest and args, so use D1. */ regsinproc |= regmsk ( REG_D1 ) ; v = sim_exp ( sh ( e ), D1 ) ; w = zw ( v ) ; t = arg1 ; /* Scan the arguments. t will hold either the first non-operand, or nilexp if all the arguments are operands. There should be at most one non-operand. */ while ( 1 ) { if ( !is_o ( name ( t ) ) ) break ; if ( last ( t ) ) { t = nilexp ; break ; } t = bro ( t ) ; } /* Deal with the case where all the arguments are operands. This does : D1 = op ( arg1, arg2 ) D1 = op ( arg3, D1 ) D1 = op ( arg4, D1 ) .................... dest = op ( argn, D1 ) */ if ( t == nilexp ) { /* Process the first two terms */ ( *op ) ( sh ( e ), zw ( arg1 ), zw ( arg2 ), w ) ; t = bro ( arg2 ) ; while ( !last ( t ) ) { /* Process the third, fourth, ... terms */ ( *op ) ( sh ( e ), zw ( t ), w, w ) ; t = bro ( t ) ; } /* Process the last term */ reuseables |= regmsk ( REG_D1 ) ; ( *op ) ( sh ( e ), zw ( t ), w, dest ) ; reuseables &= ~regmsk ( REG_D1 ) ; retcell ( v ) ; if ( have_cond == 3 ) have_cond = 1 ; return ; } /* Deal with the case where one argument, say arg2, is a non-operand. This does : D1 = arg2 D1 = op ( arg1, D1 ) D1 = op ( arg3, D1 ) .................... dest = op ( argn, D1 ) */ coder ( w, stack, t ) ; u = arg1 ; while ( 1 ) { if ( t != u ) { if ( last ( u ) || ( bro ( u ) == t && last ( bro ( u ) ) ) ) { ( *op ) ( sh ( e ), zw ( u ), w, dest ) ; } else { ( *op ) ( sh ( e ), zw ( u ), w, w ) ; } } if ( last ( u ) ) break ; u = bro ( u ) ; } retcell ( v ) ; if ( have_cond == 3 ) have_cond = 1 ; return ; } /* PROCESS ADD AND SUBTRACT This routine processes the binary operation add. It does dest = b + a. The second argument, a, may be of the form neg ( a1 ), in which case we use sub. */ static void addsub PROTO_N ( ( sha, a, b, dest, stack ) ) PROTO_T ( shape sha X where a X where b X where dest X ash stack ) { exp e = a.wh_exp ; if ( name ( e ) == neg_tag ) { bop ( sub, sha, son ( e ), b.wh_exp, dest, stack ) ; } else { bop ( add, sha, e, b.wh_exp, dest, stack ) ; } return ; } /* Some constructs only set the overflow bit for 32 bit results. This checks values of other varieties to determine whether or not an overflow has occured */ void check_unset_overflow PROTO_N ( (dest,shp) ) PROTO_T ( where dest X shape shp ) { exp max_val = getexp(shp,nilexp,0,nilexp,nilexp,0,range_max(shp), val_tag); exp min_val = getexp(shp,nilexp,0,nilexp,nilexp,0,range_min(shp), val_tag); bool sw; move(shp,dest,D0); if(is_signed(shp) && (shape_size(shp) < 32)) { ins1((shape_size(shp) == 16)?m_extl : m_extbl,32,D0,1); } sw = cmp(is_signed(shp)?slongsh:ulongsh,D0,zw(max_val),tst_gr); test_overflow2(branch_ins(tst_gr,sw,is_signed(shp),is_floating(name(shp)))); sw = cmp(is_signed(shp)?slongsh:ulongsh,D0,zw(min_val),tst_ls); test_overflow2(branch_ins(tst_ls,sw,is_signed(shp), is_floating(name(shp)))); kill_exp(max_val,max_val); kill_exp(min_val,min_val); return; } /* MAIN OPERATION CODING ROUTINE This routine creates code to evaluate e, putting the result into dest. The stack argument describes the current stack position. */ void codec PROTO_N ( ( dest, stack, e ) ) PROTO_T ( where dest X ash stack X exp e ) { if ( e == nilexp ) { error ( "Internal coding error" ) ; return ; } switch ( name ( e ) ) { case plus_tag : { /* Addition is treated similarly to logical operations - see the routine logop above. It takes a variable number of arguments in the form of a bro-list starting with the son of e. Each argument may be of the form neg ( x ). */ exp arg1 = son ( e ) ; /* First argument */ exp arg2 = bro ( arg1 ) ; /* Second argument */ exp s, t, u, v ; where w ; int prev_ov ; if ( last ( arg1 ) ) { /* One argument */ coder ( dest, stack, arg1 ) ; return ; } prev_ov = set_overflow ( e ) ; if ( last ( arg2 ) ) { /* Two arguments */ addsub ( sh ( e ), zw ( arg2 ), zw ( arg1 ), dest, stack ) ; clear_overflow ( prev_ov ) ; return ; } /* Three or more arguments - use D1 */ t = arg1 ; regsinproc |= regmsk ( REG_D1 ) ; s = sim_exp ( sh ( e ), D1 ) ; w = zw ( s ) ; /* Look for the non-operand if there is one */ while ( 1 ) { if ( !is_o ( name ( t ) ) && ( name ( t ) != neg_tag || !is_o ( name ( son ( t ) ) ) ) ) break ; if ( last( t ) ) { t = nilexp ; break ; } t = bro( t ) ; } if ( t == nilexp && name ( arg1 ) == neg_tag && name ( arg2 ) == neg_tag ) t = arg1 ; /* Deal with the case where all the arguments are operands */ if ( t == nilexp ) { t = bro ( arg2 ) ; /* Deal with the first two arguments */ if ( name ( arg1 ) == neg_tag ) { addsub ( sh ( e ), zw ( arg1 ), zw ( arg2 ), ( ( t == e ) ? dest : w ), stack ) ; } else { addsub ( sh ( e ), zw ( arg2 ), zw ( arg1 ), ( ( t == e ) ? dest : w ), stack ) ; } if ( t == e ) { clear_overflow ( prev_ov ) ; return ; } /* Deal with the third, fourth, ... arguments */ while ( !last ( t ) ) { u = bro ( t ) ; addsub ( sh ( e ), zw ( t ), w, w, stack ) ; t = u ; } /* Deal with the last argument */ addsub ( sh ( e ), zw ( t ), w, dest, stack ) ; retcell ( s ) ; if ( have_cond == 3 ) have_cond = 1 ; clear_overflow ( prev_ov ) ; return ; } /* Deal with the case where one argument is a non-operand */ coder ( w, stack, t ) ; u = arg1 ; while ( 1 ) { v = bro ( u ) ; if ( t != u ) { if ( last ( u ) || ( v == t && last ( v ) ) ) { addsub ( sh ( e ), zw ( u ), w, dest, stack ) ; } else { addsub ( sh ( e ), zw ( u ), w, w, stack ) ; } } if ( last ( u ) ) break ; u = v ; } retcell ( s ) ; if ( have_cond == 3 ) have_cond = 1 ; clear_overflow ( prev_ov ) ; return ; } #ifndef tdf3 case addptr_tag : { exp pointer = son ( e ) ; exp offset = son ( pointer ) ; make_comment("addptr_tag ...") ; mova ( zw ( e ), dest ) ; make_comment("addptr_tag done") ; return ; } #endif case chvar_tag : { /* Change variety, the son of e, a, gives the argument */ exp a = son ( e ) ; int prev_ov = set_overflow(e); if ( !is_o ( name ( a ) ) ) { /* If a is not an operand */ if ( whereis ( dest ) != Dreg ) { /* If dest is not a D register, code a into D1 */ where w ; exp s = sim_exp ( sh ( a ), D1 ) ; w = zw ( s ) ; regsinproc |= regmsk ( REG_D1 ) ; coder ( w, stack, a ) ; /* Preform the change variety on D1 */ change_var ( sh ( e ), w, dest ) ; retcell ( s ) ; if ( have_cond == 3 ) have_cond = 1 ; clear_overflow ( prev_ov ) ; return ; } /* If dest is a D register, code a into dest */ coder ( dest, stack, a ) ; /* Preform the change variety on dest */ change_var_sh ( sh ( e ), sh ( a ), dest, dest ) ; clear_overflow ( prev_ov ) ; return ; } /* If a is an operand, call change_var directly */ change_var ( sh ( e ), zw ( a ), dest ) ; clear_overflow ( prev_ov ) ; return ; } case minus_tag : { /* Minus, subtract pointer etc are binary operations */ int prev_ov = set_overflow ( e ) ; bop ( sub, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; clear_overflow ( prev_ov ) ; return ; } #ifndef tdf3 case make_stack_limit_tag : #endif case subptr_tag : case minptr_tag : { /* Minus, subtract pointer etc are binary operations */ bop ( sub, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; return ; } case mult_tag : { /* Multiply is treated as a logical operation */ int prev_ov = set_overflow ( e ) ; logop ( mult, e, dest, stack ) ; if (!optop(e)&&(name(sh(e))!=slonghd)&&(name(sh(e))!=ulonghd)) { check_unset_overflow(dest,sh(e)); } clear_overflow ( prev_ov ) ; return ; } case div0_tag : case div2_tag : { /* Division is a binary operation */ int prev_ov = set_overflow(e); bop ( div2, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; if (!optop(e)&&(name(sh(e))!=slonghd)&&(name(sh(e))!=ulonghd)) { check_unset_overflow(dest,sh(e)); } clear_overflow( prev_ov ); return ; } case div1_tag : { /* Division is a binary operation */ int prev_ov = set_overflow(e); bop ( div1, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; if (!optop(e)&&(name(sh(e))!=slonghd)&&(name(sh(e))!=ulonghd)) { check_unset_overflow(dest,sh(e)); } clear_overflow( prev_ov ); return ; } case neg_tag : { /* Negation is a unary operation */ int prev_ov = set_overflow ( e ) ; uop ( negate, sh ( e ), son ( e ), dest, stack ) ; clear_overflow ( prev_ov ) ; return ; } case abs_tag : { /* Abs is a unary operation */ int prev_ov = set_overflow(e); uop ( absop, sh ( e ), son ( e ), dest, stack ) ; clear_overflow( prev_ov ) ; return ; } case shl_tag : { /* Shifting left is a binary operation */ int prev_ov = set_overflow ( e ) ; bop ( shift, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; clear_overflow ( prev_ov ) ; return ; } case shr_tag : { /* Shifting right is a binary operation */ bop ( rshift, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; return ; } case mod_tag : { /* Remainder is a binary operation */ int prev_ov = set_overflow ( e ) ; bop ( rem1, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; clear_overflow ( prev_ov ) ; return ; } case rem0_tag : case rem2_tag : { /* Remainder is a binary operation */ int prev_ov = set_overflow ( e ) ; bop ( rem2, sh ( e ), bro ( son ( e ) ), son ( e ), dest, stack ) ; clear_overflow ( prev_ov ) ; return ; } case round_tag : { /* Rounding a floating point number is a unary operation */ int prev_ov = set_overflow ( e ) ; set_continue(e); crt_rmode = round_number ( e ) ; uop ( round_float, sh ( e ), son ( e ), dest, stack ) ; clear_overflow ( prev_ov ) ; clear_continue(e); return ; } case fmult_tag : { /* Floating multiplication is a floating binary operation */ exp f1 = son ( e ) ; exp f2 = bro ( f1 ) ; int prev_ov = set_overflow ( e ) ; if(last(f2)) { /* two arguments */ fl_binop ( fmult_tag, sh ( e ), zw ( f1 ), zw ( f2 ), dest ) ; } else { /* more than two arguments; use %fp1. Assumes that all parameters are operands */ where w; exp s = sim_exp(sh(e), FP1); regsinproc |= regmsk(REG_FP1); w = zw(s); fl_binop(fmult_tag,sh(e),zw(f1),zw(f2),w); while(!last(f2)) { f2 = bro(f2); fl_binop(fmult_tag,sh(e),w,zw(f2),(last(f2)?dest:w)); } } clear_overflow ( prev_ov ) ; return ; } case fminus_tag : { /* Floating subtraction is a floating binary operation */ exp f1 = son ( e ) ; exp f2 = bro ( f1 ) ; int prev_ov = set_overflow ( e ) ; fl_binop ( fminus_tag, sh ( e ), zw ( f2 ), zw ( f1 ), dest ) ; clear_overflow ( prev_ov ) ; return ; } case fdiv_tag : { /* Floating division is a floating binary operation */ exp f1 = son ( e ) ; exp f2 = bro ( f1 ) ; int prev_ov = set_overflow ( e ) ; fl_binop ( fdiv_tag, sh ( e ), zw ( f2 ), zw ( f1 ), dest ) ; clear_overflow ( prev_ov ) ; return ; } case fneg_tag : { /* Floating negation is simple */ int prev_ov = set_overflow ( e ) ; negate_float ( sh ( e ), zw ( son ( e ) ), dest ) ; clear_overflow ( prev_ov ) ; return ; } case fabs_tag : { /* Floating absolute value is simple */ int prev_ov = set_overflow ( e ) ; abs_float ( sh ( e ), zw ( son ( e ) ), dest ) ; clear_overflow ( prev_ov ) ; return ; } case float_tag : { /* Casting to a floating point number is simple */ int prev_ov = set_overflow ( e ) ; int_to_float ( sh ( e ), zw ( son ( e ) ), dest ) ; clear_overflow ( prev_ov ) ; return ; } case chfl_tag : { /* Changing a floating variety is simple */ int prev_ov = set_overflow ( e ) ; change_flvar ( sh ( e ), zw ( son ( e ) ), dest ) ; clear_overflow ( prev_ov ) ; return ; } case and_tag : { /* And is a logical operation */ logop ( and, e, dest, stack ) ; return ; } case or_tag : { /* Or is a logical operation */ logop ( or, e, dest, stack ) ; return ; } case xor_tag : { /* Xor is a logical operation */ logop ( xor, e, dest, stack ) ; return ; } case not_tag : { /* Not is a unary operation */ uop ( not, sh ( e ), son ( e ), dest, stack ) ; return ; } case absbool_tag : { /* The setcc instruction is not used */ error ( "Not implemented" ) ; return ; } case fplus_tag : { /* Floating addition is similar to integer addition */ exp f1 = son ( e ) ; /* First argument */ exp f2 = bro ( f1 ) ; /* Second argument */ exp t ; long count_dest = 2 ; exp de = dest.wh_exp ; int prev_ov = set_overflow ( e ) ; if ( last ( f1 ) ) { /* If there is only one argument things are simple */ move ( sh ( e ), zw ( f1 ), dest ) ; clear_overflow ( prev_ov ) ; return ; } if ( last ( f2 ) ) { /* If there are two arguments code directly */ if ( name ( f2 ) == fneg_tag ) { f2 = son ( f2 ) ; fl_binop ( fminus_tag, sh ( e ), zw ( f2 ), zw ( f1 ), dest ) ; } else { fl_binop ( fplus_tag, sh ( e ), zw ( f1 ), zw ( f2 ), dest ) ; } clear_overflow ( prev_ov ) ; return ; } if ( last ( bro ( f2 ) ) && name ( bro ( f2 ) ) == real_tag && name ( dest.wh_exp ) != apply_tag && name ( dest.wh_exp ) != tail_call_tag && name ( dest.wh_exp ) != apply_general_tag ) { /* If there are 3 arguments, the last of which is constant */ if ( name ( f2 ) == fneg_tag ) { f2 = son ( f2 ) ; fl_binop ( fminus_tag, sh ( e ), zw ( f2 ), zw ( f1 ), dest ) ; fl_binop ( fplus_tag, sh ( e ), zw ( bro ( f2 ) ), dest, dest ) ; } else { fl_binop ( fplus_tag, sh ( e ), zw ( f1 ), zw ( f2 ), dest ) ; fl_binop ( fplus_tag, sh ( e ), zw ( bro ( f2 ) ), dest, dest ) ; } clear_overflow ( prev_ov ) ; return ; } if ( name ( de ) == ass_tag && name ( son ( de ) ) == name_tag && ( ( props ( son ( son ( de ) ) ) & 0x9 ) == 0x9 ) ) { count_dest = 0 ; t = f1 ; if ( eq_where ( dest, zw ( t ) ) ) count_dest++ ; while ( !last ( t ) ) { t = bro ( t ) ; if ( name ( t ) == fneg_tag ) { if ( eq_where ( zw ( son ( t ) ), dest ) ) count_dest = 2 ; } else { if ( eq_where ( zw ( t ), dest ) ) count_dest++ ; } } } if ( count_dest < 2 && (name ( dest.wh_exp ) != apply_tag && name ( dest.wh_exp ) != tail_call_tag && name ( dest.wh_exp ) != apply_general_tag) ) { if ( count_dest == 1 ) { t = f1 ; } else { if ( name ( f2 ) == fneg_tag ) { exp m = son ( f2 ) ; fl_binop ( fminus_tag, sh ( e ), zw ( m ), zw ( f1 ), dest ) ; } else { fl_binop ( fplus_tag, sh ( e ), zw ( f1 ), zw ( f2 ), dest ) ; } t = bro ( f2 ) ; } for ( ; ; ) { where tw ; if ( name ( t ) == fneg_tag ) { tw = zw ( son ( t ) ) ; if ( !eq_where ( dest, tw ) ) { fl_binop ( fminus_tag, sh ( e ), tw, dest, dest ) ; } } else { tw = zw ( t ) ; if ( !eq_where ( dest, tw ) ) { fl_binop ( fplus_tag, sh ( e ), tw, dest, dest ) ; } } if ( last ( t ) ) break ; t = bro ( t ) ; } } else { if ( name ( f2 ) == fneg_tag ) { fl_binop ( fminus_tag, sh ( e ), zw ( son ( f2 ) ), zw ( f1 ), FP0 ) ; } else { fl_binop ( fplus_tag, sh ( e ), zw ( f1 ), zw ( f2 ), FP0 ) ; } t = bro ( f2 ) ; while ( !last ( t ) ) { if ( name ( t ) == fneg_tag ) { fl_binop ( fminus_tag, sh ( e ), zw ( son ( t ) ), FP0, FP0 ) ; } else { fl_binop ( fplus_tag, sh ( e ), zw ( t ), FP0, FP0 ) ; } t = bro ( t ) ; } if ( name ( t ) == fneg_tag ) { fl_binop ( fminus_tag, sh ( e ), zw ( son ( t ) ), FP0, dest ) ; } else { fl_binop ( fplus_tag, sh ( e ), zw ( t ), FP0, dest ) ; } } clear_overflow ( prev_ov ) ; return ; } /* Note : in the following offset operations I have put the shape as slongsh rather than sh ( e ). This is because the system stddef.h wrongly says that ptrdiff_t is unsigned and I don't trust people to put it right when making up TDF libraries. If this was right sh ( e ) would be slongsh. */ case offset_add_tag : { make_comment("offset_add_tag..."); /* Offset addition is a binary operation */ bop ( add, slongsh, son ( e ), bro ( son ( e ) ), dest, stack ) ; make_comment("offset_add_tag done"); return ; } case offset_subtract_tag : { /* Offset subtraction is a binary operation */ bop ( sub, slongsh, bro ( son ( e ) ), son ( e ), dest, stack ) ; return ; } case offset_mult_tag : { make_comment("offset_mult_tag..."); /* Offset multiplication is a binary operation */ bop ( mult, slongsh, son ( e ), bro ( son ( e ) ), dest, stack ) ; make_comment("offset_mult_tag done"); return ; } case offset_negate_tag : { /* Offset negation is a unary operation */ uop ( negate, slongsh, son ( e ), dest, stack ) ; return ; } case offset_div_tag : case offset_div_by_int_tag : { /* Offset division is a binary operation */ if(name(sh(bro(son(e)))) < slonghd){ exp changer = me_u3(slongsh,bro(son(e)),chvar_tag); bro(son(e)) = changer; } bop ( div2, slongsh, bro ( son ( e ) ), son ( e ), dest, stack ) ; return ; } case offset_pad_tag : { /* Pad an operand */ exp cur_offset = son ( e ) ; long cur_align = al2 ( sh ( cur_offset ) ) ; long next_align = al2 ( sh ( e ) ) ; make_comment("offset_pad ...") ; /* does current alignment include next alignment? */ if ( cur_align >= next_align ) { if( ( next_align !=1 ) || ( cur_align ==1 ) ) { coder ( dest, stack, cur_offset ) ; } else { /* left shift */ shift( sh(e), mnw(3), zw(cur_offset),dest); } } else { /* cur_align < next_align */ where r ; if ( whereis ( dest ) == Dreg ) { r = dest ; } else { r = D1 ; regsinproc |= regmsk ( REG_D1 ) ; } codec ( r, stack, cur_offset ) ; if( cur_align == 1){ add ( slongsh, mnw ( next_align - 1 ), r, r ) ; and ( slongsh, mnw ( -next_align ), r, dest ) ; rshift(sh(e),mnw(3),dest,dest); } else { long al = next_align / 8 ; add ( slongsh, mnw ( al - 1 ), r, r ) ; and ( slongsh, mnw ( -al ), r, dest ) ; } } make_comment("offset_pad done") ; return ; } case bitf_to_int_tag : { if ( whereis ( dest ) == Dreg ) { coder ( dest, stack, son ( e ) ) ; change_var_sh ( sh ( e ), sh ( son ( e ) ), dest, dest ) ; } else { regsinproc |= regmsk ( REG_D1 ) ; coder ( D1, stack, son ( e ) ) ; change_var_sh ( sh ( e ), sh ( son ( e ) ), D1, dest ) ; } return ; } case int_to_bitf_tag : { where r ; long nbits = shape_size ( sh ( e ) ) ; long mask = lo_bits [ nbits ] ; r = ( whereis ( dest ) == Dreg ? dest : D0 ) ; move ( slongsh, zw ( son ( e ) ), r ) ; and ( slongsh, mnw ( mask ), r, dest ) ; return ; } case offset_max_tag : case max_tag : { /* Maximum */ bop ( maxop, sh ( e ), son ( e ), bro ( son ( e ) ), dest, stack ) ; return ; } case min_tag : { /* Minimum */ bop ( minop, sh ( e ), son ( e ), bro ( son ( e ) ), dest, stack ) ; return ; } case cont_tag : { make_comment("cont_tag ...") ; if ( name ( sh ( e ) ) == bitfhd ) { bitf_to_int ( e, sh ( e ), dest, stack ) ; return ; } move ( sh ( e ), zw ( e ), dest ) ; make_comment("cont_tag done") ; return ; } default : { if ( !is_o ( name ( e ) ) ) { /* If e is not an operand, code e into a register */ exp s ; where w ; if ( name ( e ) == apply_tag || name ( e ) == apply_general_tag || name ( e ) == tail_call_tag ) { s = sim_exp ( sh ( e ), D0 ) ; } else { if ( whereis ( dest ) == Dreg ) { /* error ( "Untested optimization" ) ;*/ s = sim_exp ( sh ( e ), dest ) ; } else { regsinproc |= regmsk ( REG_D1 ) ; s = sim_exp ( sh ( e ), D1 ) ; } } w = zw ( s ) ; coder ( w, stack, e ) ; /* Move the value of this register into dest */ move ( sh ( e ), w, dest ) ; retcell ( s ) ; if ( have_cond == 3 ) have_cond = 1 ; return ; } if ( name ( e ) == reff_tag && shape_size ( sh ( e ) ) != 32 ) { /* Deal with pointers to bitfields */ exp s ; where d ; /* s = sim_exp ( sh ( e ), D0 ) ; */ d = mw ( dest.wh_exp, dest.wh_off + 32 ) ; if ( shape_size ( sh ( son ( e ) ) ) == 32 ) { make_comment("Pointer to bitfield (32) ...") ; coder ( dest, stack, son ( e ) ) ; move ( slongsh, mnw ( no ( e ) ), d ) ; make_comment("Pointer to bitfield (32) done") ; return ; } make_comment("Pointer to bitfield ...") ; coder ( dest, stack, son ( e ) ) ; add ( slongsh, mnw ( no ( e ) ), d, d ) ; make_comment("Pointer to bitfield done") ; return ; } if ( name ( e ) == reff_tag && ( name ( son ( e ) ) == name_tag || ( name ( son ( e ) ) == cont_tag && name ( son ( son ( e ) ) ) == name_tag ) ) ) { /* Deal with pointers with offsets */ long off = no ( e ) / 8 ; make_comment("reff_tag ..."); add ( slongsh, zw ( son ( e ) ), mnw ( off ), dest ) ; make_comment("reff_tag done"); return ; } if ( ( name ( e ) == name_tag && isvar ( son ( e ) ) ) || name ( e ) == reff_tag){ /* Deal with pointers */ mova ( zw ( e ), dest ) ; return ; } if ( name ( e ) == clear_tag ) { /* Deal with clear shapes */ char sn = name ( sh ( e ) ) ; if ( sn >= shrealhd && sn <= doublehd ) { move ( sh ( e ), fzero, dest ) ; } #ifndef tdf3 if(name (dest.wh_exp) == apply_tag || name (dest.wh_exp) == apply_general_tag || name (dest.wh_exp) == tail_call_tag ) { move ( sh ( e ), zero, dest ) ; } #endif return ; } if (name(e) == val_tag && ((name(sh(e)) == s64hd) || name(sh(e)) == u64hd)){ flt64 bval; where w; bval = exp_to_f64(e); if ( eq_where ( dest, D0_D1 ) ) { move_const(slongsh,32,bval.big, D1); move_const(slongsh,32,bval.small, D0); } else { w = dest; move_const(sh(e),32,bval.small,w); w.wh_off += 32; move_const(sh(e),32,bval.big,w); } return; } /* If all else fails, use move */ if ( name ( e ) == top_tag ) return ; move ( sh ( e ), zw ( e ), dest ) ; return ; } } } tendra-4.1.2.orig/src/installers/680x0/common/codec.h100644 1750 1750 4364 6460152205 21610 0ustar brooniebroonie/* Crown Copyright (c) 1996 This TenDRA(r) Computer Program is subject to Copyright owned by the United Kingdom Secretary of State for Defence acting through the Defence Evaluation and Research Agency (DERA). It is made available to Recipients with a royalty-free licence for its use, reproduction, transfer to other parties and amendment for any purpose not excluding product development provided that any such use et cetera shall be deemed to be acceptance of the following conditions:- (1) Its Recipients shall ensure that this Notice is reproduced upon any copies or amended versions of it; (2) Any amended version of it shall be clearly marked to show both the nature of and the organisation responsible for the relevant amendment or amendments; (3) Its onward transfer from a recipient to another party shall be deemed to be that party's acceptance of these conditions; (4) DERA gives no warranty or assurance as to its quality or suitability for any purpose and DERA accepts no liability whatsoever in relation to any use to which it may be put. */ /* VERSION INFORMATION =================== -------------------------------------------------------------------------- $Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/codec.h,v 1.1.1.1 1998/01/17 15:55:49 release Exp $ -------------------------------------------------------------------------- $Log: codec.h,v $ * Revision 1.1.1.1 1998/01/17 15:55:49 release * First version to be checked into rolling release. * Revision 1.1.1.1 1997/10/13 12:42:48 ma First version. Revision 1.1.1.1 1997/03/14 07:50:10 ma Imported from DRA * Revision 1.2 1996/09/20 13:51:24 john * *** empty log message *** * * Revision 1.1.1.1 1996/09/20 10:56:52 john * * Revision 1.1.1.1 1996/03/26 15:45:08 john * * Revision 1.1 93/02/22 17:15:18 17:15:18 ra (Robert Andrews) * Initial revision * -------------------------------------------------------------------------- */ #ifndef CODEC_INCLUDED #define CODEC_INCLUDED extern void codec PROTO_S ( ( where, ash, exp ) ) ; extern exp sim_exp PROTO_S ( ( shape, where ) ) ; #endif tendra-4.1.2.orig/src/installers/680x0/common/coder.c100644 1750 1750 144007 6460152205 21661 0ustar brooniebroonie/* Crown Copyright (c) 1997 This TenDRA(r) Computer Program is subject to Copyright owned by the United Kingdom Secretary of State for Defence acting through the Defence Evaluation and Research Agency (DERA). It is made available to Recipients with a royalty-free licence for its use, reproduction, transfer to other parties and amendment for any purpose not excluding product development provided that any such use et cetera shall be deemed to be acceptance of the following conditions:- (1) Its Recipients shall ensure that this Notice is reproduced upon any copies or amended versions of it; (2) Any amended version of it shall be clearly marked to show both the nature of and the organisation responsible for the relevant amendment or amendments; (3) Its onward transfer from a recipient to another party shall be deemed to be that party's acceptance of these conditions; (4) DERA gives no warranty or assurance as to its quality or suitability for any purpose and DERA accepts no liability whatsoever in relation to any use to which it may be put. */ /* VERSION INFORMATION =================== -------------------------------------------------------------------------- $Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/coder.c,v 1.1.1.1 1998/01/17 15:55:49 release Exp $ -------------------------------------------------------------------------- $Log: coder.c,v $ * Revision 1.1.1.1 1998/01/17 15:55:49 release * First version to be checked into rolling release. * Revision 1.4 1997/11/13 08:27:10 ma All avs test passed (except add_to_ptr). Revision 1.3 1997/11/09 14:06:09 ma Fixed AVS problems. Revision 1.2 1997/10/29 10:22:06 ma Replaced use_alloca with has_alloca. Revision 1.1.1.1 1997/10/13 12:42:48 ma First version. Revision 1.8 1997/10/13 08:49:01 ma Made all pl_tests for general proc & exception handling pass. Revision 1.7 1997/09/25 06:44:52 ma All general_proc tests passed Revision 1.6 1997/06/24 10:55:57 ma Added changes for "Plumhall Patch" Revision 1.5 1997/06/18 12:04:49 ma Merged with Input Baseline changes. Revision 1.4 1997/06/18 10:09:23 ma Checking in before merging with Input Baseline changes. Revision 1.3 1997/04/20 11:30:19 ma Introduced gcproc.c & general_proc.[ch]. Added cases for apply_general_proc next to apply_proc in all files. Revision 1.2 1997/03/20 12:46:22 ma Now tag ids are kept in unsigned chars (MAX tag id > 127). Revision 1.1.1.1 1997/03/14 07:50:10 ma Imported from DRA * Revision 1.1.1.1 1996/09/20 10:56:52 john * * Revision 1.4 1996/07/31 16:25:46 john * Changed alloca * * Revision 1.3 1996/07/30 16:30:43 john * Removed offset conversion * * Revision 1.2 1996/07/05 14:16:42 john * Changes for spec 3.1 * * Revision 1.1.1.1 1996/03/26 15:45:09 john * * Revision 1.5 94/06/29 14:18:27 14:18:27 ra (Robert Andrews) * always_round_fl has changed its name. Need to be slightly more careful * in a couple of places. * * Revision 1.4 94/02/21 15:56:25 15:56:25 ra (Robert Andrews) * A couple of flags which used to be bool are now int. * * Revision 1.3 93/11/19 16:15:49 16:15:49 ra (Robert Andrews) * Minor corrections to nof_tag and ncopies_tag cases. * * Revision 1.2 93/03/08 15:28:34 15:28:34 ra (Robert Andrews) * Procedures which take compound arguments and return a compound * result which is ignored were having their arguments put on the * stack in the wrong place. * * Revision 1.1 93/02/22 17:15:20 17:15:20 ra (Robert Andrews) * Initial revision * -------------------------------------------------------------------------- */ #include "config.h" #include #include "common_types.h" #include "check.h" #include "exp.h" #include "expmacs.h" #include "flags.h" #include "shapemacs.h" #include "externs.h" #include "install_fns.h" #include "spec.h" #include "mach.h" #include "where.h" #include "tags.h" #include "codec.h" #include "coder.h" #include "operations.h" #include "mach.h" #include "mach_ins.h" #include "mach_op.h" #include "instr.h" #include "installglob.h" #include "codex.h" #include "instrs.h" #include "peephole.h" #include "szs_als.h" #include "tests.h" #include "utility.h" #include "weights.h" #include "translate.h" #include "ops_shared.h" #include "general_proc.h" #include "68k_globals.h" #if have_diagnostics #include "xdb_basics.h" #endif extern int do_peephole ; extern int normal_version ; static int extra_weight = 0 ; /* ADD A SHAPE TO A THE STACK Given an ash p, representing the stack, and a shape s, this procedure returns the ast correponding to the new stack formed by adding s to the old stack. */ ast add_shape_to_stack PROTO_N ( ( p, s ) ) PROTO_T ( ash p X shape s ) { ast res ; char n = name ( s ) ; long sz = shape_size ( s ) ; long adj = 0 ; if ( n == scharhd || n == ucharhd || n == swordhd || n == uwordhd ) { adj = SLONG_SZ - sz ; sz = SLONG_SZ ; } if ( n == bitfhd ) sz = SLONG_SZ ; res.astoff = round ( p, param_align ) ; res.astadj = adj ; res.astash = round ( res.astoff + sz, param_align ) ; return ( res ) ; } /* REGISTER ALLOCATION ROUTINES This routine tries to choose registers for a value of shape sha. br gives the breakpoint - the minimum number of registers which need to be free for it to be worth putting this value in a register. The big flag is true to indicate that a register which is preserved across procedure calls is required. If a register can be allocated, then its bitpattern is returned. Otherwise 0 is returned. */ static bitpattern alloc_reg PROTO_N ( ( sha, br, big ) ) PROTO_T ( shape sha X int br X bool big ) { int go = 1 ; bitpattern mask ; bitpattern rs = regsinuse ; int i, start, end, rev = 0 ; int rg ; int r = shtype ( sha ) ; if ( r == Dreg ) { rg = bits_in ( ~rs & 0x00fc ) ; mask = regmsk ( REG_D2 ) ; start = REG_D2 ; end = REG_D7 ; } else if ( r == Areg ) { rg = bits_in ( ~rs & 0x3c00 ) ; mask = regmsk ( REG_A2 ) ; start = REG_A2 ; end = REG_A5 ; if ( br > extra_weight ) br -= extra_weight ; } else if ( r == Freg ) { if ( round_after_flop ) return ( 0 ) ; rg = bits_in ( ~rs & 0xfc0000 ) ; mask = regmsk ( REG_FP7 ) ; start = REG_FP7 ; end = REG_FP2 ; rev = 1 ; } else { error ( "Illegal register type" ) ; return ( 0 ) ; } if ( rg < br || rg == 0 ) return ( 0 ) ; i = start ; while ( go ) { if ( !( rs & mask ) ) { if ( big ) { bigregs |= mask ; if ( r == Freg ) normal_version = 0 ; } regsinproc |= mask ; return ( mask ) ; } if ( i == end ) { go = 0 ; } else { if ( rev ) { i-- ; mask >>= 1 ; } else { i++ ; mask <<= 1 ; } } } return ( 0 ) ; } /* IS A GIVEN EXPRESSION A USE OF A REUSABLE REGISTER? This routine returns 0 if the expression e is not a use of a reuseable register, and the bitmask of the register otherwise. */ static long reuse_check PROTO_N ( ( e ) ) PROTO_T ( exp e ) { exp id ; if ( name ( e ) != name_tag ) return ( 0 ) ; id = son ( e ) ; if ( isglob ( id ) || pt ( id ) != reg_pl ) return ( 0 ) ; return ( reuseables & no ( id ) ) ; } /* CAN WE REUSE A REGISTER? This routine checks whether or not we can use a reuseable register to store def. It returns the bitmask of a suitable register if so and 0 otherwise. */ static long reuse PROTO_N ( ( def ) ) PROTO_T ( exp def ) { switch ( name ( def ) ) { case name_tag : { return ( reuse_check ( def ) ) ; } case plus_tag : case and_tag : case or_tag : case xor_tag : case mult_tag : { /* Allow at most two arguments - check both */ exp arg1 = son ( def ) ; exp arg2 = bro ( arg1 ) ; if ( last ( arg1 ) ) { return ( reuse_check ( arg1 ) ) ; } if ( last ( arg2 ) ) { return ( reuse_check ( arg1 ) || reuse_check ( arg2 ) ) ; } return ( 0 ) ; } case chvar_tag : case neg_tag : case not_tag : { /* Check one argument */ return ( reuse_check ( son ( def ) ) ) ; } case minus_tag : case subptr_tag : case minptr_tag : case shl_tag : case shr_tag : { /* Check two arguments */ exp arg1 = son ( def ) ; exp arg2 = bro ( arg1 ) ; return ( reuse_check ( arg1 ) || reuse_check ( arg2 ) ) ; } } return ( 0 ) ; } /* IS AN EXPRESSION GUARANTEED NOT TO USE D0? Or if it is, are we really careful? */ static bool nouse PROTO_N ( ( e ) ) PROTO_T ( exp e ) { char n = name ( e ) ; if ( n == test_tag ) return ( 1 ) ; return ( 0 ) ; } /* WHERE IS A DECLARATION TO BE PUT? The routine alloc_variable chooses where to put a declaration. e is the declaration, def is the definition (for identity) or initialisation (for variable), stack is the ash for the current stack position. The place field of the result indicates where the declaration should be put (reg_pl, var_pl etc. - see coder.h). num gives the offset (for objects put on the stack) or register mask (for objects put into registers). new_stack gives the ash of the stack after this declaration. is_new is a flag indicating a new declaration or a reuse of an old declaration. */ static allocation alloc_variable PROTO_N ( ( e, def, stack ) ) PROTO_T ( exp e X exp def X ash stack ) { ast locast ; allocation dc ; bitpattern ru ; unsigned char n = name ( def ) ; exp s = son ( def ) ; exp body = bro ( def ) ; int br = ( int ) no ( e ) ; bool force_reg = isusereg ( e ) ; bool big = ( props ( e ) & 0x80 ? 1 : 0 ) ; bool in_reg1 = 0, in_reg2 = 0, in_reg3 = 1 ; dc.new_stack = stack ; dc.is_new = 1 ; if ( name ( sh ( def ) ) == tophd && !isvis(e)) { dc.place = nowhere_pl ; dc.num = 0 ; return ( dc ) ; } if ( n == name_tag ) { in_reg1 = ( !isvar ( s ) && ( no ( def ) == 0 || !isglob ( s ) ) ) ; } else if ( n == cont_tag && name ( s ) == name_tag ) { exp t = son ( s ) ; in_reg2 = ( isvar ( t ) && ( no ( s ) == 0 || !isglob ( t ) ) && no_side ( body ) ) ; } if ( !isvar ( e ) && ( in_reg1 || in_reg2 ) ) { /* Re-identification or contents of variable not altered in body */ if ( in_reg1 ) { dc.place = ptno ( s ) ; #ifndef tdf3 switch ( ptno (s) ) { case var_pl: dc.num = no ( s ) - no ( def ) ; break; case par3_pl: case par2_pl: dc.num = no ( s ) - no ( def ) ; break; default: dc.num = no ( s ) + no ( def ) ; } #else if ( ptno ( s ) == var_pl ) { dc.num = no ( s ) - no ( def ) ; } else { dc.num = no ( s ) + no ( def ) ; } #endif } else { s = son ( s ) ; dc.place = ptno ( s ) ; if ( ptno ( s ) == var_pl ) { dc.num = no ( s ) - no ( son ( def ) ) ; } else { dc.num = no ( s ) + no ( son ( def ) ) ; } } /* We have a declaration */ if ( dc.place == reg_pl ) { /* If the old one was in registers, reuse it */ dc.is_new = 0 ; return ( dc ) ; } if ( !force_reg ) { if ( regable ( e ) ) { ru = alloc_reg ( sh ( def ), br, big ) ; if ( ru ) { dc.place = reg_pl ; dc.num = ru ; return ( dc ) ; } } if ( isglob ( s ) ) { locast = add_shape_to_stack ( stack, sh ( def ) ) ; dc.new_stack = locast.astash ; dc.place = var_pl ; if ( locast.astadj ) { dc.num = locast.astoff + locast.astadj ; } else { dc.num = locast.astash ; } return ( dc ) ; } /* If there was not room, reuse the old dec */ dc.is_new = 0 ; return ( dc ) ; } if ( regable ( e ) ) { ru = alloc_reg ( sh ( def ), br, big ) ; if ( ru ) { dc.place = reg_pl ; dc.num = ru ; return ( dc ) ; } if ( isglob ( s ) ) { locast = add_shape_to_stack ( stack, sh ( def ) ) ; dc.new_stack = locast.astash ; dc.place = var_pl ; if ( locast.astadj ) { dc.num = locast.astoff + locast.astadj ; } else { dc.num = locast.astash ; } return ( dc ) ; } dc.is_new = 0 ; return ( dc ) ; } return ( dc ) ; } if ( n == apply_tag || n == apply_general_tag || n == tail_call_tag ) in_reg3 = result_in_reg ( sh ( def ) ) ; /* Try to allocate in registers */ if ( regable ( e ) && in_reg3 ) { if ( ( n == apply_tag || n == apply_general_tag || n == tail_call_tag ) && shtype ( sh ( def ) ) != Freg && nouse ( bro ( def ) ) ) { dc.place = reg_pl ; dc.num = regmsk ( REG_D0 ) ; return ( dc ) ; } if ( is_a ( n ) ) { long rg = reuse ( def ) & 0x3cfc ; if ( rg ) { reuseables &= ~rg ; dc.place = reg_pl ; dc.num = rg ; return ( dc ) ; } } ru = alloc_reg ( sh ( def ), br, big ) ; if ( ru ) { dc.place = reg_pl ; dc.num = ru ; return ( dc ) ; } } /* Otherwise allocate on the stack */ locast = add_shape_to_stack ( stack, sh ( def ) ) ; dc.new_stack = locast.astash ; dc.place = var_pl ; if ( locast.astadj ) { dc.num = locast.astoff + locast.astadj ; } else { dc.num = locast.astash ; } return ( dc ) ; } /* CURRENT SCOPES These variables are used for the scope and destination of inlined procedures. */ static exp crt_rscope ; static where rscope_dest ; /* PUSH A SET OF PROCEDURE ARGUMENTS The arguments are given by a bro-list starting with t. They are coded in reverse order. */ static void code_pars PROTO_N ( ( w, stack, t ) ) PROTO_T ( where w X ash stack X exp t ) { long sz = shape_size ( sh ( t ) ) ; if ( last ( t ) ) { /* Code last argument */ coder ( w, stack, t ) ; stack_dec -= round ( sz, param_align ) ; } else { /* Code the following arguments */ code_pars ( w, stack, bro ( t ) ) ; /* And then this one */ coder ( w, stack, t ) ; stack_dec -= round ( sz, param_align ) ; } return ; } /* PRODUCE CODE FOR A SOLVE STATEMENT The solve statement with starter s, labelled statements l, destination dest and default jump jr is processed. */ static void solve PROTO_N ( ( s, l, dest, jr, stack ) ) PROTO_T ( exp s X exp l X where dest X exp jr X ash stack ) { exp t ; long r1 ; while ( !last ( l ) ) { allocation dc ; long lb = next_lab () ; exp record = simple_exp ( 0 ) ; if ( props ( son ( bro ( l ) ) ) & 2 ) setlast ( record ) ; no ( record ) = stack ; sonno ( record ) = stack_dec ; ptno ( record ) = lb ; pt ( son ( bro ( l ) ) ) = record ; dc = alloc_variable ( bro ( l ), son ( bro ( l ) ), stack ) ; ptno ( bro ( l ) ) = dc.place ; no ( bro ( l ) ) = dc.num ; l = bro ( l ) ; } r1 = regsinuse ; if ( name ( s ) != goto_tag || pt ( s ) != bro ( s ) ) { /* Code the starting expression */ have_cond = 0 ; coder ( dest, stack, s ) ; } t = s ; do { regsinuse = r1 ; if ( name ( sh ( t ) ) != bothd ) make_jump ( m_bra, ptno ( jr ) ) ; t = bro ( t ) ; if ( no ( son ( t ) ) > 0 ) { make_label ( ptno ( pt ( son ( t ) ) ) ) ; coder ( dest, stack, t ) ; } } while ( !last ( t ) ) ; regsinuse = r1 ; have_cond = 0 ; return ; } /* PRODUCE CODE FOR A CASE STATEMENT The controlling number of the case statement is in the D1 register, from which already has been deducted. The list of options is given as a bro-list in arg. The routine returns the total number which has been deducted from D1 at the end. */ static long caser PROTO_N ( ( arg, already ) ) PROTO_T ( exp arg X long already ) { bool sw, go = 1, diff = 0 ; exp t, jr, jt, split_at ; shape sha = sh ( arg ) ; double low, high ; double lowest = LONG_MAX, highest = LONG_MIN ; long i, j, n, *jtab ; long worth = 0 ; for ( t = bro ( arg ) ; go && ( t != nilexp ) ; t = bro ( t ) ) { if (is_signed(sh(t))) low = no (t) ; else low = (unsigned) no(t) ; if (son(t)) { if (is_signed(sh(son(t)))) high = no(son(t)) ; else high =(unsigned) no(son(t)) ; } else high = low ; if ( low != high ) diff = 1 ; if ( low < lowest ) lowest = low ; if ( high > highest ) highest = high ; worth += ( low == high ? 1 : 2 ) ; if ( bro ( t ) != nilexp ) { double nextlow; if (is_signed(sh(bro(t)))) nextlow = no(bro(t)); else nextlow = (unsigned) no(bro(t)); if ( ( nextlow / 2 ) > ( high / 2 ) + 20 ) { split_at = t ; go = 0 ; } } #ifndef tdf3 if (high/2 > low/2 + 20) { worth = 0 ; } #endif } if ( !go ) { /* Split into two */ long a ; exp new = copyexp ( arg ) ; exp old_bro = bro ( split_at ) ; bro ( new ) = old_bro ; bro ( split_at ) = nilexp ; setlast ( split_at ) ; /* Code the first half */ a = caser ( arg, already ) ; /* Code the second half */ return ( caser ( new, a ) ) ; } if ( worth > 2 ) { /* Construct a jump table */ mach_op *op1, *op2 ; long rlab = next_lab () ; long tlab = next_lab () ; long slab = next_lab () ; n = highest - lowest + 1 ; jtab = ( long * ) xcalloc ( n, sizeof ( long ) ) ; for ( i = 0 ; i < n ; i++ ) jtab [i] = rlab ; for ( t = bro ( arg ) ; t != nilexp ; t = bro ( t ) ) { if (is_signed(sh(t))) low = no (t) ; else low = (unsigned) no(t) ; if (son(t)) { if (is_signed(sh(son(t)))) high = no(son(t)) ; else high =(unsigned) no(son(t)) ; } else high = low ; j = ptno ( pt ( son ( pt ( t ) ) ) ) ; for ( i = low ; i <= high ; i++ ) jtab [ i - (long)lowest ] = j ; } /* Move offset into D1 */ jt = simple_exp ( 0 ) ; ptno ( jt ) = rlab ; /* Subtract the lowest value (minus anything already deducted) */ sub ( slongsh, mnw ( lowest - already ), D1, D1 ) ; sw = cmp ( slongsh, D1, mnw ( highest - lowest ), tst_gr ) ; branch ( tst_gr, jt, 0, sw, 0 ) ; /* Move displacement into D0 */ #if 0 op1 = make_reg_index ( REG_ZA0, REG_D1, 0, 4 ) ; op1->of->plus->plus = make_lab ( slab, 0 ) ; regsinproc |= regmsk ( REG_A0 ) ; debug_warning ( "%%za0 used" ) ; #else op1 = make_lab_ind ( slab, 0 ) ; i = tmp_reg ( m_lea, op1 ) ; op1 = make_reg_index ( i, REG_D1, 0, 4 ) ; #endif op2 = make_register ( REG_D0 ) ; make_instr ( m_movl, op1, op2, regmsk ( REG_D0 ) ) ; /* Do the jump */ op1 = make_reg_index ( REG_PC, REG_D0, 2, 1 ) ; make_instr ( m_jmp, op1, null, 0 ) ; /* Print out table */ make_label ( tlab ) ; #ifndef no_align_directives make_instr ( m_as_align4, null, null, 0 ) ; #endif make_label ( slab ) ; for ( i = 0 ; i < n ; i++ ) { op1 = make_lab_diff ( jtab [i], tlab ) ; make_instr ( m_as_long, op1, null, 0 ) ; } make_label ( rlab ) ; /* Return the total number deducted from D1 */ return ( lowest ) ; } /* If 'high' is not always equal to 'low', restore value of D1 */ if ( diff ) { add ( slongsh, D1, mnw ( already ), D1 ) ; already = 0 ; } /* A series of jumps/comparisons */ for ( t = bro ( arg ) ; t != nilexp ; t = bro ( t ) ) { if (is_signed(sh(t))) low = no (t) ; else low = (unsigned) no(t) ; if (son(t)) { if (is_signed(sh(son(t)))) high = no(son(t)) ; else high =(unsigned) no(son(t)) ; } else high = low ; jr = pt ( son ( pt ( t ) ) ) ; if ( low == high ) { sw = cmp ( sha, D1, mnw ( low - already ), tst_eq ) ; branch ( tst_eq, jr, 1, sw, 0 ) ; } else { jt = simple_exp ( 0 ) ; ptno ( jt ) = next_lab () ; sw = cmp ( sha, D1, mnw ( low - already ), tst_ls ) ; branch ( tst_ls, jt, is_signed ( sh ( t ) ), sw, 0 ) ; sw = cmp ( sha, D1, mnw ( (unsigned)(high - already) ), tst_le ) ; branch ( tst_le, jr, is_signed ( sh ( son ( t ) ) ), sw, 0 ) ; make_label ( ptno ( jt ) ) ; } } /* Return what has been subtracted from D1 */ have_cond = 0 ; return ( already ) ; } /* RESET STACK POINTER FROM APPLICATIONS POINTER sp = AP - (env_size - (sizeof(params) + sizeof(ret-addr) + sizeof(AP))) */ static void reset_stack_pointer PROTO_Z () { mach_op *op1, *op2, *op3 ; make_comment("reset stack pointer ..."); update_stack () ; op1 = make_indirect ( REG_AP, 0 ) ; op2 = op1->of->plus = new_mach_op() ; op2->type = MACH_NEG ; op2->plus = make_ldisp(4); op2 = make_register ( REG_SP ) ; make_instr ( m_lea, op1, op2, regmsk ( REG_SP ) ) ; #if 0 /* gas misinterpret lea a6@(