--- /dev/null
+echo Setting up the environment for debugging gdb.\n
+
+b fatal
+
+b info_command
+commands
+ silent
+ return
+end
+
+define rr
+ run
+end
+
+set prompt (top-gdb)
--- /dev/null
+
+@node Convex,,, Top
+@appendix Convex-specific info
+@cindex Convex notes
+
+Scalar registers are 64 bits long, which is a pain since
+left half of an S register frequently contains noise.
+Therefore there are two ways to obtain the value of an S register.
+
+@table @kbd
+@item $s0
+returns the low half of the register as an int
+
+@item $S0
+returns the whole register as a long long
+@end table
+
+You can print the value in floating point by using @samp{p/f $s0} or @samp{p/f $S0}
+to print a single or double precision value.
+
+@cindex vector registers
+Vector registers are handled similarly, with @samp{$V0} denoting the whole
+64-bit register and @kbd{$v0} denoting the 32-bit low half; @samp{p/f $v0}
+or @samp{p/f $V0} can be used to examine the register in floating point.
+The length of the vector registers is taken from @samp{$vl}.
+
+Individual elements of a vector register are denoted in the obvious way;
+@samp{print $v3[9]} prints the tenth element of register @kbd{v3}, and
+@samp{set $v3[9] = 1234} alters it.
+
+@kbd{$vl} and @kbd{$vs} are int, and @kbd{$vm} is an int vector.
+Elements of @kbd{$vm} can't be assigned to.
+
+@cindex communication registers
+@kindex info comm-registers
+Communication registers have names @kbd{$C0 .. $C63}, with @kbd{$c0 .. $c63}
+denoting the low-order halves. @samp{info comm-registers} will print them
+all out, and tell which are locked. (A communication register is
+locked when a value is sent to it, and unlocked when the value is
+received.) Communication registers are, of course, global to all
+threads, so it does not matter what the currently selected thread is.
+@samp{info comm-reg @var{name}} prints just that one communication
+register; @samp{name} may also be a communication register number
+@samp{nn} or @samp{0xnn}.
+@samp{info comm-reg @var{address}} prints the contents of the resource
+structure at that address.
+
+@kindex info psw
+The command @samp{info psw} prints the processor status word @kbd{$ps}
+bit by bit.
+
+@kindex set base
+GDB normally prints all integers in base 10, but the leading
+@kbd{0x80000000} of pointers is intolerable in decimal, so the default
+output radix has been changed to try to print addresses appropriately.
+The @samp{set base} command can be used to change this.
+
+@table @code
+@item set base 10
+Integer values always print in decimal.
+
+@item set base 16
+Integer values always print in hex.
+
+@item set base
+Go back to the initial state, which prints integer values in hex if they
+look like pointers (specifically, if they start with 0x8 or 0xf in the
+stack), otherwise in decimal.
+@end table
+
+@kindex set pipeline
+When an exception such as a bus error or overflow happens, usually the PC
+is several instructions ahead by the time the exception is detected.
+The @samp{set pipe} command will disable this.
+
+@table @code
+@item set pipeline off
+Forces serial execution of instructions; no vector chaining and no
+scalar instruction overlap. With this, exceptions are detected with
+the PC pointing to the instruction after the one in error.
+
+@item set pipeline on
+Returns to normal, fast, execution. This is the default.
+@end table
+
+@cindex parallel
+In a parallel program, multiple threads may be executing, each
+with its own registers, stack, and local memory. When one of them
+hits a breakpoint, that thread is selected. Other threads do
+not run while the thread is in the breakpoint.
+
+@kindex 1cont
+The selected thread can be single-stepped, given signals, and so
+on. Any other threads remain stopped. When a @samp{cont} command is given,
+all threads are resumed. To resume just the selected thread, use
+the command @samp{1cont}.
+
+@kindex thread
+The @samp{thread} command will show the active threads and the
+instruction they are about to execute. The selected thread is marked
+with an asterisk. The command @samp{thread @var{n}} will select thread @var{n},
+shifting the debugger's attention to it for single-stepping,
+registers, local memory, and so on.
+
+@kindex info threads
+The @samp{info threads} command will show what threads, if any, have
+invisibly hit breakpoints or signals and are waiting to be noticed.
+
+@kindex set parallel
+The @samp{set parallel} command controls how many threads can be active.
+
+@table @code
+@item set parallel off
+One thread. Requests by the program that other threads join in
+(spawn and pfork instructions) do not cause other threads to start up.
+This does the same thing as the @samp{limit concurrency 1} command.
+
+@item set parallel fixed
+All CPUs are assigned to your program whenever it runs. When it
+executes a pfork or spawn instruction, it begins parallel execution
+immediately. This does the same thing as the @samp{mpa -f} command.
+
+@item set parallel on
+One or more threads. Spawn and pfork cause CPUs to join in when and if
+they are free. This is the default. It is very good for system
+throughput, but not very good for finding bugs in parallel code. If you
+suspect a bug in parallel code, you probably want @samp{set parallel fixed.}
+@end table
+
+@subsection Limitations
+
+WARNING: Convex GDB evaluates expressions in long long, because S
+registers are 64 bits long. However, GDB expression semantics are not
+exactly C semantics. This is a bug, strictly speaking, but it's not one I
+know how to fix. If @samp{x} is a program variable of type int, then it
+is also type int to GDB, but @samp{x + 1} is long long, as is @samp{x + y}
+or any other expression requiring computation. So is the expression
+@samp{1}, or any other constant. You only really have to watch out for
+calls. The innocuous expression @samp{list_node (0x80001234)} has an
+argument of type long long. You must explicitly cast it to int.
+
+It is not possible to continue after an uncaught fatal signal by using
+@samp{signal 0}, @samp{return}, @samp{jump}, or anything else. The difficulty is with
+Unix, not GDB.
+
+I have made no big effort to make such things as single-stepping a
+@kbd{join} instruction do something reasonable. If the program seems to
+hang when doing this, type @kbd{ctrl-c} and @samp{cont}, or use
+@samp{thread} to shift to a live thread. Single-stepping a @kbd{spawn}
+instruction apparently causes new threads to be born with their T bit set;
+this is not handled gracefully. When a thread has hit a breakpoint, other
+threads may have invisibly hit the breakpoint in the background; if you
+clear the breakpoint gdb will be surprised when threads seem to continue
+to stop at it. All of these situations produce spurious signal 5 traps;
+if this happens, just type @samp{cont}. If it becomes a nuisance, use
+@samp{handle 5 nostop}. (It will ask if you are sure. You are.)
+
+There is no way in GDB to store a float in a register, as with
+@kbd{set $s0 = 3.1416}. The identifier @kbd{$s0} denotes an integer,
+and like any C expression which assigns to an integer variable, the
+right-hand side is casted to type int. If you should need to do
+something like this, you can assign the value to @kbd{@{float@} ($sp-4)}
+and then do @kbd{set $s0 = $sp[-4]}. Same deal with @kbd{set $v0[69] = 6.9}.
--- /dev/null
+##Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Place to install binaries.
+bindir=/usr/local/bin
+
+# System V: If you compile gdb with a compiler which uses the coff
+# encapsulation feature (this is a function of the compiler used, NOT
+# of the m-?.h file selected by config.gdb), you must make sure that
+# the GNU nm is the one that is used by munch.
+
+# If you are compiling with GCC, make sure that either 1) You use the
+# -traditional flag, or 2) You have the fixed include files where GCC
+# can reach them. Otherwise the ioctl calls in inflow.c and readline.c
+# will be incorrectly compiled. The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+#CC=cc
+#CC=gcc -traditional
+GCC=gcc
+
+VPATH=$(srcdir)
+
+# It is also possible that you will need to add -I/usr/include/sys to the
+# CFLAGS section if your system doesn't have fcntl.h in /usr/include (which
+# is where it should be according to Posix).
+
+YACC=bison -y
+# YACC=yacc
+SHELL=/bin/sh
+MAKE=make
+
+# Set this up with gcc if you have gnu ld and the loader will print out
+# line numbers for undefinded refs.
+#CC-LD=gcc -static
+CC-LD=${CC}
+
+# define this to be "gmalloc.o" if you want to use the gnu malloc routine
+# (useful for debugging memory allocation problems in gdb). To use your
+# system malloc, uncomment the following two lines.
+#GNU_MALLOC =
+#MALLOC_CFLAGS = -DNO_MALLOC_CHECK
+GNU_MALLOC = gmalloc.o mcheck.o
+MALLOC_CFLAGS =
+
+# Where is the "include" directory? Traditionally ../include or ./include
+INCLUDE_DIR = ${srcdir}/../include
+INCLUDE_DEP = $$(INCLUDE_DIR)
+
+# Where is the BFD library? Traditionally ../bfd or ./bfd
+BFD_DIR = ${srcdir}/../bfd
+BFD_DEP = $$(BFD_DIR)
+
+# All the includes used for CFLAGS and for lint.
+# -I. for config files.
+# -I${srcdir} for <obstack.h>, possibly regex.h also.
+INCLUDE_CFLAGS = -I. -I${srcdir} -I$(INCLUDE_DIR) -I${srcdir}/vx-share
+
+# {X,T}M_CFLAGS, if defined, has system-dependent CFLAGS.
+# CFLAGS for both GDB and readline.
+GLOBAL_CFLAGS = -g ${TM_CFLAGS} ${XM_CFLAGS}
+#PROFILE_CFLAGS = -pg
+
+CFLAGS = ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} ${MALLOC_CFLAGS} ${INCLUDE_CFLAGS}
+# None of the things in CFLAGS will do any harm, and on some systems
+# (e.g. SunOS4) it is important to use the M_CFLAGS.
+LDFLAGS = $(CFLAGS)
+
+# define this to be "obstack.o" if you don't have the obstack library installed
+# so that the dependencies work right.
+OBSTACK = obstack.o
+
+# Requires GNU getopt_long features.
+GETOPT = getopt.o getopt1.o
+# Where is the getopt directory? Traditionally ../getopt or ./getopt
+GETOPT_DIR = ${srcdir}/../getopt
+GETOPT_DEP = $$(GETOPT_DIR)
+
+# Flags that describe where you can find the termcap library.
+# You may need to make other arrangements for USG.
+TERMCAP = -ltermcap
+
+# You must define REGEX and REGEX1 on USG machines.
+# If your sysyem is missing alloca(), or, more likely, it's there but
+# it doesn't work, define ALLOCA & ALLOCA1
+
+# {X,T}M_CLIBS, if defined, has system-dependent libs
+# For example, -lPW for System V to get alloca().
+# FIXME STOPGAP FOR BFD LIBRARY: BFD stuff
+CLIBS = ${TERMCAP} $(XM_CLIBS) ${TM_CLIBS} ${BFD_DIR}/libbfd.a
+CDEPS = ${XM_CDEPS} ${TM_CDEPS} ${BFD_DIR}/libbfd.a
+
+ADD_FILES = ${OBSTACK} ${REGEX} ${ALLOCA} ${GNU_MALLOC} ${GETOPT}
+ADD_DEPS = ${OBSTACK} ${REGEX1} ${ALLOCA1} ${GNU_MALLOC} ${GETOPT}
+
+VERSION = 3.94.2
+DIST=gdb-$(VERSION)
+
+LINT=/usr/5bin/lint
+LINTFLAGS=
+
+# Source files in the main directory.
+# Files which are included via a tconfig/* or xconfig/* file
+# should *not* be specified here; they're in "ALLDEPFILES".
+SFILES_MAINDIR = \
+ blockframe.c breakpoint.c command.c core.c \
+ environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
+ main.c printcmd.c \
+ remote.c source.c stack.c symmisc.c symtab.c symfile.c \
+ utils.c valarith.c valops.c valprint.c values.c expread.y \
+ signame.c cplus-dem.c mem-break.c target.c inftarg.c \
+ dbxread.c coffread.c \
+ ieee-float.c
+
+# Source files in subdirectories (which will be handled separately by
+# 'make gdb.tar.Z').
+# Files which are included via a tconfig/* or xconfig/* file
+# should *not* be specified here; they're in "ALLDEPFILES".
+SFILES_SUBDIR = \
+ ${srcdir}/vx-share/dbgRpcLib.h \
+ ${srcdir}/vx-share/ptrace.h \
+ ${srcdir}/vx-share/reg.h \
+ ${srcdir}/vx-share/vxTypes.h \
+ ${srcdir}/vx-share/vxWorks.h \
+ ${srcdir}/vx-share/wait.h \
+ ${srcdir}/vx-share/xdr_ld.h \
+ ${srcdir}/vx-share/xdr_ptrace.h \
+ ${srcdir}/vx-share/xdr_rdb.h \
+ ${srcdir}/vx-share/xdr_regs.h \
+ ${srcdir}/nindy-share/Makefile \
+ ${srcdir}/nindy-share/VERSION \
+ ${srcdir}/nindy-share/b.out.h \
+ ${srcdir}/nindy-share/block_io.h \
+ ${srcdir}/nindy-share/coff.h \
+ ${srcdir}/nindy-share/demux.h \
+ ${srcdir}/nindy-share/env.h \
+ ${srcdir}/nindy-share/stop.h \
+ ${srcdir}/nindy-share/ttycntl.h
+
+# All source files that go into linking GDB, except config-specified files.
+SFILES = $(SFILES_MAINDIR) $(SFILES_SUBDIR)
+
+# All source files that lint should look at
+LINTFILES = $(SFILES) expread.tab.c init.c
+
+# Any additional files specified on these lines should also be added to
+# the OTHERS = definition below, so they go in the tar files.
+SFILES_STAND = $(SFILES) standalone.c
+SFILES_KGDB = $(SFILES) stuff.c kdb-start.c
+
+# Header files that are not named in tconfig/* or xconfig/* go here.
+HFILES= breakpoint.h command.h defs.h environ.h \
+ expression.h frame.h gdbcmd.h gdbcore.h \
+ getpagesize.h ieee-float.h inferior.h param-no-tm.h param.h \
+ signals.h signame.h symfile.h symtab.h \
+ target.h tdesc.h terminal.h tm-68k.h tm-i960.h tm-sunos.h \
+ value.h
+
+OPCODES = pn-opcode.h np1-opcode.h sparc-opcode.h vax-opcode.h m68k-opcode.h \
+ ns32k-opcode.h convex-opcode.h pyr-opcode.h mips-opcode.h \
+ am29k-opcode.h
+
+REMOTE_EXAMPLES = remote-sa.m68k.shar remote-multi.shar
+
+MALLOCSRC = gmalloc.c mcheck.c ansidecl.h stdlib.h gmalloc.h stddef.h
+GETOPTSRC = $(GETOPT_DIR)/getopt.c $(GETOPT_DIR)/getopt1.c
+
+POSSLIBS_MAINDIR = obstack.h obstack.c regex.c regex.h alloca.c \
+ $(MALLOCSRC)
+POSSLIBS = $(POSSLIBS_MAINDIR) $(GETOPTSRC)
+
+TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
+
+# tdesc-lib cannot be named simply tdesc, because if if it were GNU make
+# would try to make it from tdesc.c.
+# tdesc-lib removed from the list due to Motorola copyrights...gnu@cygnus.com
+OTHERS = Makefile.dist depend alldeps.mak Makefile.srcdir \
+ createtags munch config.gdb config.status \
+ ChangeLog ChangeLog-3.x \
+ README TODO TAGS WHATS.NEW \
+ gdb.texinfo gdb-int.texinfo gdbrc.tex threecol.tex \
+ .gdbinit COPYING expread.tab.c stab.def \
+ copying.c Projects Convex.notes copying.awk \
+ saber.suppress standalone.c stuff.c kdb-start.c \
+ hp-include # tests
+
+DEPFILES= ${TDEPFILES} ${XDEPFILES}
+
+SOURCES=$(SFILES) $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${OPCODES} ${ALLPARAM} ${POSSLIBS}
+TAGFILES_MAINDIR = $(SFILES_MAINDIR) $(ALLDEPFILES_MAINDIR) \
+ ${HFILES} ${OPCODES} ${ALLPARAM} ${POSSLIBS_MAINDIR}
+TARFILES = ${TAGFILES_MAINDIR} ${OTHERS} ${REMOTE_EXAMPLES}
+
+OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
+ values.o eval.o valops.o valarith.o valprint.o printcmd.o \
+ symtab.o symfile.o symmisc.o infcmd.o infrun.o remote.o \
+ command.o utils.o expread.o expprint.o environ.o version.o \
+ copying.o $(DEPFILES) signame.o cplus-dem.o mem-break.o target.o \
+ inftarg.o ieee-float.o \
+ dbxread.o coffread.o # mipsread.o
+
+RAPP_OBS = rgdb.o rudp.o rserial.o serial.o udp.o $(XDEPFILES)
+
+TSOBS = core.o inflow.o
+
+NTSOBS = standalone.o
+
+TSSTART = /lib/crt0.o
+
+NTSSTART = kdb-start.o
+
+RL_LIB = readline/libreadline.a
+RL_LIB_DEP = $(RL_LIB)
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ ${CC} -c ${CFLAGS} $<
+
+all: gdb
+
+install: gdb
+ cp gdb $(bindir)/gdb.new
+ mv $(bindir)/gdb.new $(bindir)/gdb
+ $(M_INSTALL)
+
+init.c: $(srcdir)/munch $(MUNCH_DEFINE) $(OBS) $(TSOBS)
+ $(srcdir)/munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) > init.c
+
+gdb: $(OBS) $(TSOBS) ${ADD_DEPS} ${RL_LIB_DEP} ${CDEPS} init.o
+ ${CC-LD} $(LDFLAGS) -o gdb init.o $(OBS) $(TSOBS) $(ADD_FILES) \
+ ${RL_LIB} $(CLIBS)
+
+saber_gdb: $(SFILES) $(GETOPTSRC) $(DEPFILES) copying.c obstack.c version.c
+ #setopt load_flags $(CFLAGS) -I$(BFD_DIR)
+ #load ./init.c $(SFILES)
+ #unload ${srcdir}/expread.y
+ #load ${srcdir}/expread.tab.c readline/libreadline.a
+ #load copying.c version.c
+ #load obstack.c $(GETOPTSRC)
+ #load `echo " "$(DEPFILES) | sed -e 's/\.o/.c/g' -e 's, , ../,g'`
+ #load ${BFD_DIR}/libbfd.a -ltermcap
+ ##void mcheck(a) void (*a)(); { }
+
+
+
+# This is useful when debugging GDB, because some Unix's don't let you run GDB
+# on itself without copying the executable. So "make gdb1" will make
+# gdb and put a copy in gdb1, and you can run it with "gdb gdb1".
+# Removing gdb1 before the copy is the right thing if gdb1 is open
+# in another process.
+gdb1: gdb
+ rm -f gdb1
+ cp gdb gdb1
+
+# This is a remote stub which runs under unix and starts up an
+# inferior process. This is at least useful for debugging GDB's
+# remote support.
+rapp: $(RAPP_OBS)
+ rm -f rapp_init.c
+ ${srcdir}/munch ${RAPP_OBS} > rapp_init.c
+ ${CC-LD} $(LDFLAGS) -o $@ rapp_init.c $(RAPP_OBS)
+
+Makefiles= Makefile.srcdir $(M_MAKEFILE) \
+ ${srcdir}/alldeps.mak ${srcdir}/Makefile.dist
+
+MAKE_MAKEFILE= echo "M_MAKEFILE=$(M_MAKEFILE)" | \
+ cat - ${Makefiles} ${srcdir}/depend >Makefile
+
+Makefile: $(Makefiles)
+ $(MAKE_MAKEFILE)
+
+alldeps.mak: ${srcdir}/tconfig ${srcdir}/xconfig
+ rm -f alldeps.mak alldeps.tmp allparam.tmp allconfig.tmp
+ for i in `ls -d ${srcdir}/tconfig/*[0-9A-Za-z] \
+ ${srcdir}/xconfig/*[0-9A-Za-z] | grep -v RCS` ; do \
+ echo $$i >>allconfig.tmp; \
+ awk <$$i ' \
+ $$1 == "TDEPFILES=" || $$1 == "XDEPFILES=" { \
+ for (i = 2; i <= NF; i++) \
+ print $$i >> "alldeps.tmp" ; \
+ } \
+ $$1 == "TM_FILE=" || $$1 == "XM_FILE=" { \
+ print $$2 >> "allparam.tmp" }' ; \
+ done
+ sort <alldeps.tmp | uniq | \
+ sed -e 's/arm-convert.o/arm-convert.s/' \
+ -e 's!^Onindy.o!nindy-share/Onindy.c!' \
+ -e 's!^nindy.o!nindy-share/nindy.c!' \
+ -e 's!ttybreak.o!nindy-share/ttybreak.c!' \
+ -e 's!ttyflush.o!nindy-share/ttyflush.c!' \
+ -e 's!xdr_ld.o!vx-share/xdr_ld.c!' \
+ -e 's!xdr_ptrace.o!vx-share/xdr_ptrace.c!' \
+ -e 's!xdr_rdb.o!vx-share/xdr_rdb.c!' \
+ -e 's!xdr_regs.o!vx-share/xdr_regs.c!' \
+ -e 's/\.o/.c/' \
+ >alldeps2.tmp
+ echo 'ALLDEPFILES = $$(ALLDEPFILES_MAINDIR) $$(ALLDEPFILES_SUBDIR)' \
+ >>alldeps.mak;
+ grep -v / alldeps2.tmp | \
+ awk 'BEGIN {printf "ALLDEPFILES_MAINDIR="} \
+ NR == 0 {printf $$0;} \
+ NR != 0 {printf "\\\n" $$0} \
+ END {printf "\n\n"}' >>alldeps.mak;
+ grep / alldeps2.tmp | \
+ awk 'BEGIN {printf "ALLDEPFILES_SUBDIR="} \
+ NR == 0 {printf $$0;} \
+ NR != 0 {printf "\\\n" $$0} \
+ END {printf "\n\n"}' >>alldeps.mak;
+ sort <allparam.tmp | uniq | awk 'BEGIN {printf "ALLPARAM="} \
+ NR == 0 {printf $$0;} \
+ NR != 0 {printf "\\\n" $$0} \
+ END {printf "\n\n"}' >>alldeps.mak;
+ sort <allconfig.tmp | uniq | awk 'BEGIN {printf "ALLCONFIG="} \
+ NR == 0 {printf $$0;} \
+ NR != 0 {printf "\\\n" $$0} \
+ END {printf "\n\n"}' >>alldeps.mak;
+ rm -f alldeps.tmp alldeps2.tmp allparam.tmp allconfig.tmp
+
+# The sed script makes everything which depends on {x,t}m.h depend on
+# config.status as well, in case someone reconfigures gdb out from
+# under an already compiled gdb.
+depend: $(SOURCES) Makefile.dist
+ @echo Ignore errors about non-existent system-supplied include files
+ @echo for systems other than the one you are using.
+ @echo "If xm.h and tm.h don't exist, the error messages saying so"
+ @echo can safely be ignored.
+ @echo Also ignore parse errors in valops.c, and any errors in
+ @echo arm-convert.s.
+ -$(GCC) -MM $(CFLAGS) -I$(BFD_DIR) \
+ `ls $(SOURCES) | sort -u` >depend.tmp
+ <depend.tmp sed -e 's/ [xt]m.h/& config.status/g' \
+ -e 's; vx-share/; $${srcdir}/vx-share/;g' \
+ -e 's; nindy-share/; $${srcdir}/nindy-share/;g' \
+ -e 's; $(INCLUDE_DIR)/; $(INCLUDE_DEP)/;g' \
+ -e 's; [a-z0-9./]*bfd/; $(BFD_DEP)/;g' \
+ -e 's; [a-z0-9./]*getopt/; $(GETOPT_DEP)/;g' \
+ -e 's; \./; $${srcdir}/;g' \
+ >depend
+ $(MAKE_MAKEFILE)
+ rm depend.tmp
+
+config.status:
+ @echo "You must configure gdb. Look at the README file for details."
+ @false
+
+# These are not generated by "make depend" because they only are there
+# for some machines.
+tm-isi.h tm-sun3.h tm-news.h tm-hp300bsd.h tm-altos.h : tm-68k.h
+tm-hp300hpux.h tm-sun2.h tm-3b1.h : tm-68k.h
+xm-news1000.h : xm-news.h
+xm-i386-sv32.h : xm-i386.h
+tm-i386gas.h: tm-i386.h
+xm-sun4os4.h : xm-sparc.h
+tm-sun4os4.h : tm-sparc.h
+
+kdb : $(NTSSTART) $(OBS) $(NTSOBS) ${ADD_DEPS} ${RL_LIB_DEP}
+ rm -f init.c
+ $(srcdir)/munch ${MUNCH_DEFINE} $(OBS) $(NTSOBS) > init.c
+ $(CC) $(LDFLAGS) -c init.c $(CLIBS)
+ ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o $(ADD_FILES) \
+ ${RL_LIB} -lc $(CLIBS)
+
+# Put the proper machine-specific files first.
+# createtags will edit the .o in DEPFILES into .c
+TAGS: ${TAGFILES}
+ $(srcdir)/createtags $(TM_FILE) ${XM_FILE} $(DEPFILES) ${TAGFILES}
+tags: TAGS
+
+# FIXME: Get alldeps.mak up to date, config.gdb none, THEN make gdb.tar.Z!
+gdb.tar.Z: ${TARFILES}
+ rm -f gdb.tar; rm -rf $(DIST)
+ cd readline ; make readline.tar
+ mkdir $(DIST)
+ cd $(DIST) ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
+ mkdir $(DIST)/readline
+ cd $(DIST)/readline ; tar xf ../../readline/readline.tar
+ mkdir $(DIST)/xconfig ${DIST}/tconfig
+ cd $(DIST)/tconfig ; \
+ for i in $(ALLCONFIG) ; do ln -s ../../$$i ../$$i ; done
+ mkdir $(DIST)/vx-share $(DIST)/nindy-share
+ cd $(DIST)/tconfig ; \
+ for i in $(SFILES_SUBDIR) $(ALLDEPFILES_SUBDIR); \
+ do ln -s ../../$$i ../$$i ; done
+ tar chf - $(DIST) | compress >gdb.tar.Z
+ rm -rf $(DIST)
+
+clean:
+ rm -f ${OBS} ${TSOBS} ${NTSOBS} ${ADD_FILES}
+ rm -f init.c init.o version.c
+ rm -f gdb core gdb.tar gdb.tar.Z make.log
+ rm -f gdb[0-9]
+ cd readline ; make clean
+
+distclean: clean expread.tab.c TAGS
+ rm -f tm.h xm.h config.status
+ rm -f y.output yacc.acts yacc.tmp
+ rm -f ${TESTS} Makefile
+
+realclean: clean
+ rm -f expread.tab.c TAGS
+ rm -f tm.h xm.h config.status
+ rm -f Makefile
+
+gdb.dvi : gdb.texinfo
+ tex gdb.texinfo
+ texindex gdb.??
+ tex gdb.texinfo
+
+# Make copying.c from COPYING
+copying.c : COPYING copying.awk
+ awk -f copying.awk < COPYING > copying.c
+
+version.c : Makefile.dist
+ echo 'char *version = "$(VERSION)";' >version.c
+
+${srcdir}/expread.tab.c : $(srcdir)/expread.y
+ @echo 'Expect 4 shift/reduce conflict.'
+ ${YACC} $(srcdir)/expread.y
+ mv y.tab.c ${srcdir}/expread.tab.c
+
+expread.o : ${srcdir}/expread.tab.c defs.h param.h symtab.h \
+ frame.h expression.h
+ $(CC) -c ${CFLAGS} `echo ${srcdir}/expread.tab.c | sed 's,^\./,,'`
+ mv expread.tab.o expread.o
+
+# dbxread, coffread, mipsread have dependencies on BFD header files.
+dbxread.o: ${srcdir}/dbxread.c
+ ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/dbxread.c
+
+coffread.o: ${srcdir}/coffread.c
+ ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/coffread.c
+
+mipsread.o: ${srcdir}/mipsread.c
+ ${CC} -c ${CFLAGS} -I$(BFD_DIR) ${srcdir}/mipsread.c
+
+# Drag in the files that are in another directory.
+
+getopt1.o: $(GETOPT_DIR)/getopt1.c
+ ${CC} -c ${CFLAGS} $(GETOPT_DIR)/getopt1.c
+
+getopt.o: $(GETOPT_DIR)/getopt.c
+ ${CC} -c ${CFLAGS} $(GETOPT_DIR)/getopt.c
+
+xdr_ld.o: ${srcdir}/vx-share/xdr_ld.c
+ ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_ld.c
+
+xdr_ptrace.o: ${srcdir}/vx-share/xdr_ptrace.c
+ ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_ptrace.c
+
+xdr_rdb.o: ${srcdir}/vx-share/xdr_rdb.c
+ ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_rdb.c
+
+xdr_regs.o: ${srcdir}/vx-share/xdr_regs.c
+ ${CC} -c ${CFLAGS} ${srcdir}/vx-share/xdr_regs.c
+
+nindy.o: ${srcdir}/nindy-share/nindy.c
+ ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/nindy.c
+
+Onindy.o: ${srcdir}/nindy-share/Onindy.c
+ ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/Onindy.c
+
+ttybreak.o: ${srcdir}/nindy-share/ttybreak.c
+ ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/ttybreak.c
+
+ttyflush.o: ${srcdir}/nindy-share/ttyflush.c
+ ${CC} -c ${CFLAGS} ${srcdir}/nindy-share/ttyflush.c
+
+tdesc-lib/libdc.o : force_update
+ cd tdesc-lib ; ${MAKE} "SYSV_DEFINE=${SYSV_DEFINE}"
+
+# In LOCAL_INCLUDES, -I${srcdir} is right if srcdir is an absolute path,
+# and -I../${srcdir} is right if it is relative (e.g. ".."), so search both.
+readline/libreadline.a : force_update
+ cd readline ; ${MAKE} "SYSV=${SYSV_DEFINE}"\
+ "VPATH=${srcdir}/readline:../${srcdir}/readline"\
+ "LOCAL_INCLUDES=-I../ -I${srcdir}/ -I../${srcdir}/"\
+ "DEBUG_FLAGS=${GLOBAL_CFLAGS}" "CC=${CC}" libreadline.a
+
+lint: $(LINTFILES)
+ $(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES)
+
+gdb.cxref: $(SFILES)
+ cxref -I. $(SFILES) >gdb.cxref
+
+force_update :
+
+# When used with GDB, the demangler should never look for leading underscores
+# because GDB strips them off during symbol read-in. Thus -Dnounderscore.
+cplus-dem.o : cplus-dem.c
+ ${CC} -c -Dnounderscore `echo ${srcdir}/cplus-dem.c | sed 's,^\./,,'`
--- /dev/null
+
+ Suggested projects for aspiring or current GDB hackers
+ ======================================================
+
+ (You should probably chat with bug-gdb@cygnus.com to make sure that
+ no one else is doing the project you chose).
+
+Rewrite proceed, wait_for_inferior, and normal_stop to clean them up.
+Suggestions:
+
+ 1) Make each test in wait_for_inferior a seperate subroutine
+ call.
+ 2) Combine wait_for_inferior and normal_stop to clean up
+ communication via global variables.
+ 3) See if you can find some way to clean up the global
+ variables that are used; possibly group them by data flow
+ and information content?
+
+Work out some kind of way to allow running the inferior to be done as
+a sub-execution of, eg. breakpoint command lists. Currently running
+the inferior interupts any command list execution. This would require
+some rewriting of wait_for_inferior & friends, and hence should
+probably be done in concert with the above.
+
+Add function arguments to gdb user defined functions.
+
+Add convenience variables that refer to exec file, symbol file,
+selected frame source file, selected frame function, selected frame
+line number, etc.
+
+Add a "suspend" subcommand of the "continue" command to suspend gdb
+while continuing execution of the subprocess. Useful when you are
+debugging servers and you want to dodge out and initiate a connection
+to a server running under gdb.
+
+Work out and implement a reasonably general mechanism for multi-threaded
+processies. There are parts of one implemented in convex-dep.c, if
+you want an example.
+
+Add stab information to allow reasonable debugging of inline functions
+(possibly they should show up on a stack backtrace? With a note
+indicating that they weren't "real"?).
+
+Implement support for specifying arbitrary locations of stack frames
+(in practice, this usually requires specification of both the top and
+bottom of the stack frame (fp and sp), since you *must* retrieve the
+pc that was saved in the innermost frame).
+
+Modify the naked "until" command to step until past the current source
+line, rather than past the current pc value. This is tricky simply
+because the low level routines have no way of specifying a multi-line
+step range, and there is no way of saying "don't print stuff when we
+stop" from above (otherwise could just call step many times).
+
+Modify the handling of symbols grouped through BINCL/EINCL stabs to
+allocate a partial symtab for each BINCL/EINCL grouping. This will
+seriously decrease the size of inter-psymtab dependencies and hence
+lessen the amount that needs to be read in when a new source file is
+accessed.
+
+Do an "x/i $pc" after each stepi or nexti.
+
+Modify all of the disassemblers to use printf_filtered to get correct
+more filtering.
+
+Modify gdb to work correctly with Pascal.
+
+Rewrite macros that handle frame chaining and frameless functions.
+They should be able to tell the difference between start, main, and a
+frameless function called from main.
+
+Work out what information would need to be included in an executable
+by the compiler to allow gdb to debug functions which do not have a
+frame pointer. Modify gdb and gcc to do this.
+
+When `attached' to a program (via either OS support or remote
+debugging), gdb should arrange to catch signals which the terminal
+might send, as it is unlikely that the program will be able to notice
+them. SIGINT and SIGTSTP are obvious examples.
+
+Enhance the gdb manual with extra examples where needed.
+
+Arrange for list_command not to use decode_line_1 and thus not require
+symbols to be read in simply to read a source file.
+
+Allow patching of executables, a la "adb -w".
+
+Improve the target interface so that targets can be stacked; e.g. an
+exec file and a core file (memory references that the core file can't
+satisfy are directed to the exec file); those two plus a child process.
+The child doesn't let any refs through, but when the child terminates,
+you are back to debugging the core file -- you might even want to swap
+back and forth between the two, or between two core files.
+
+# Local Variables:
+# mode: text
+# End:
--- /dev/null
+
+ gdb bug list
+ John Gilmore, gnu@cygnus.com
+
+This bug list is probably not up to date or accurate, but it reflects
+some known bugs in gdb, if you are into bug-hunting.
+
+
+Update the TODO list with all the lists of gdb bugs lying around on paper.
+
+"share" command should not need to be manually run. It should be run
+as soon as possible, automatically, both on "run" and on core files.
+
+It should be possible to use symbols from shared libraries before we know
+exactly where the libraries will be loaded. E.g. "b perror" before running
+the program. This could maybe be done as an extension of the "breakpoint
+re-evaluation" after new symbols are loaded.
+
+Make single_step() insert and remove breakpoints in one operation.
+
+Speed up single stepping by avoiding extraneous ptrace calls.
+
+Speed up single stepping by not inserting and removing breakpoints
+each time the inferior starts and stops.
+
+Speed up watchpoints by not single-stepping them, but do something
+faster like single-line execution.
+
+Update gdb.texinfo to include doc on the directory structure and
+the various tricks of building gdb.
+
+Do a tutorial in gdb.texinfo on how to do simple things in gdb.
+E.g. how to set a breakpoint that just prints something and continues.
+How to break on aborts. Etc.
+
+Do a "new features" section for release 4.
+
+Provide "voodoo" debugging of core files. This creates a zombie
+process as a child of the debugger, and loads it up with the data,
+stack, and regs of the core file. This allows you to call functions
+in the executable, to manipulate the data in the core file.
+
+GDB reopens the source file on every line, as you "next" through it.
+
+Referencing the vtbl member of a struct doesn't work. It prints OK
+if you print the struct, but it gets 0 if you try to deref it.
+
+Persistent command history: A feature where you could save off a list
+of the commands you did, so you can edit it into something that will bring
+the target to the same place every time you source it. Sun wants it.
+This would also be useful for automated fast watchpointing; if you go
+past the place where it watchpoints, you just start it over again and
+do it more carefully.
+
+Deal with the Sun ptrace bug that loses the registers if the stack is
+paged out.
+
+Finish the C++ exception handling stub routines. Lint points them out
+as unused statics functions.
+
+"i source" only shows you info about files that it can read. When it
+can't read a file and complains, you can't see any info about it, like
+where it was compiled. Perhaps "i source" should take an argument
+like that of "list".
+
+See if coredep.c's fetch_core_registers can be used on more machines.
+E.g. MIPS (mips-xdep.c).
+
+coredep.c is completely broken. Needs work just to compile, it uses
+"u" and doesn't declare it, etc.
+
+unpack_double() does not handle IEEE float on the target unless the host
+is also IEEE. Death on a vax.
+
+Test cross-debugging Unix-to-Unix.
+
+Check the RAPP remote protocol. What is it? It's in Makefile.dist
+and one ChangeLog entry.
+
+Set up interface between GDB and INFO so that you can hop into interactive
+INFO and back out again. When running under Emacs, should use Emacs
+info, else fork the info program. Installation of GDB should install
+its texinfo files into the info tree automagically, including the readline
+texinfo files..
+
+Improve backtrace output to avoid line wraps. Prettify it.
+
+"help address" ought to find the "help set addressprint" entry.
+
+Remove the VTBL internal guts from printouts of C++ structs, unless
+vtblprint is set.
+
+Remove "at 0xnnnn" from the "b foo" response, if !addressprint and if
+it matches the source line indicated.
+
+The prompt at end of screen should accept space as well as CR.
+
+"List" should put you into a pseudo-"more" where you can hit space
+to get more, forever to eof.
+
+Check STORE_RETURN_VALUE on all architectures. Check near it in tm-sparc.h
+for other bogosities.
+
+Check for storage leaks in GDB, I'm sure there are a lot!
+
+vtblprint of a vtbl should demangle the names it's printing.
+
+Backtrace should point out what the currently selected frame is, in its
+display, perhaps showing ">3 foo (bar, ...)" rather than "#3 foo (bar, ...)".
+
+"i program" should work for core files, and display more info, like what
+actually caused it to die.
+
+Hitting ^Z to an inferior doesn't work right, it takes several continues
+to make it actually go.
+
+"i fun" doesn't show misc function vector symbols.
+
+"x/10i" should shorten the long name, if any, on subsequent lines.
+
+Check through the code for FIXME comments and fix them. dbxread.c,
+blockframe.c, and plenty more.
+
+"next" over a function that longjumps, never stops until next time you happen
+to get to that spot by accident. E.g. "n" over execute_command which has
+an error.
+
+Watchpoints seem not entirely reliable.
+
+"set zeroprint off", don't bother printing members of structs which are entirely
+zero. Useful for those big structs with few useful members.
+
+GDB does four ioctl's for every command, probably switching terminal modes
+to/from inferior or for readline or something.
+
+terminal_ours versus terminal_inferior: cache state. Switch should be a noop
+if the state is the same, too.
+
+ptype $i6 = void??!
+
+Clean up invalid_float handling so gdb doesn't coredump when it tries to
+access a NaN. While this might work on SPARC, other machines are not
+configured right.
+
+"b value_at ; commands ; continue ; end" stops EVERY OTHER TIME!
+Then once you enter a command, it does the command, runs two more
+times, and then stops again! Bizarre... (This behaviour has been
+modified, but it is not yet 100% predictable when e.g. the commands
+call functions in the child, and while there, the child is interrupted
+with a signal, or hits a breakpoint.)
+
+Symbol completion with TAB does not unmangle names!
+
+help completion, help history should work.
+
+Symbol completion doesn't handle e.g. W::f. (symtab.c,
+make_symbol_completion_list).
+
+AMD version: ^C should do ^Ak to stop ebmon.
+
+Check that we can handle stack trace through varargs AND alloca in same
+function, on 29K.
+
+wait_for_inferior loops forever if wait() gives it an error.
+
+"i frame" arg formatting sucks. Should wrap lines.
+"bt" arg formatting needs the same treatment .
+
+"i frame" shows wrong "arglist at" location, doesn't show where the args
+should be found, only their actual values.
+
+Symbolic display of addrs, (& disassembly prefixes), don't show static
+fns, e.g. enable_command in gdb.
+
+'ptype yylval' ==> "union YYSTYPE { ..... }". However, it is not a
+union YYSTYPE, but is simply a YYSTYPE, which is a typedef for an
+unnamed union.
+
+"show all" should work.
+
+There should be a way for "set" commands to validate the new setting
+before it takes effect.
+
+The "display" command should become the "always" command, e.g.
+ "always print XXX"
+ "always p/xxx XXX"
+ "always echo foo"
+ "always call XXX"
+ "always x/i $pc", etc.
+
+A mess of floating point opcodes are missing from sparc-opcode.h.
+Also, a little program should test the table for bits that are
+overspecified or underspecified. E.g. if the must-be-ones bits
+and the must-be-zeroes bits leave some fields unexamined, and the format
+string leaves them unprinted, then point this out. If multiple
+non-alias patterns match, point this out too. Finally, there should
+be a sparc-optest.s file that tries each pattern out. This file
+should end up coming back the same (modulo transformation comments)
+if fed to "gas" then the .o is fed to gdb for disassembly.
+
+Merge the xxx-opcode.h files with gas again...
+
+Eliminate all the core_file_command's in all the xdep files.
+Eliminate separate declarations of registers[] everywhere.
+
+"ena d" is ambiguous, why? "ena delete" seems to think it is a command!
+
+Line numbers are off in some spots. In proceed() at 1st "oneproc = 1",
+it seems to run that statement, but it doesn't actually.
+
+Perhaps the tdep and xdep files, and the tm and xm files, into a config
+subdirectory. If not, at least straighten out their names so that
+they all start with the machine name.
+
+inferior_status should include stop_print_frame. It won't need to be
+reset in wait_for_inferior after bpstat_stop_status call, then.
+
+i line VAR produces "Line number not known for symbol ``var''.". I
+thought we were stashing that info now!
+
+Make sure we can handle executables with no symbol info, e.g. /bin/csh.
+
+We should be able to write to executables that aren't running.
+
+We should be able to write to random files at hex offsets like adb.
+
+Tiemann: It is very painful to look at fp registers that hold
+double precision values. GDB is happy to show them to you as single
+precision, but you cannot look at them as doubles. Perhaps casting
+should be changed to make this work; or maybe a new "set" option that
+sets the default fp precision to single, double, or quad. This is not
+urgent, but would be nice to get into GDB 4.0.
+
+Make "target xxx" command interruptible.
+
+Handle add_file with separate text, data, and bss addresses. Maybe
+handle separate addresses for each segment in the object file?
+
+Handle free_named_symtab to cope with multiply-loaded object files
+in a dynamic linking environment. Should remember the last copy loaded,
+but not get too snowed if it finds references to the older copy.
+
+Implement have_memory, have_stack, have_registers, have_execution.
+Memory: core, exec, child, vxworks even without child.
+stack: core, child, vxworks with child
+registers: core, child, vxworks with child
+execution: child, vxworks with child.
+
+The original BFD core dump reading routine would itself coredump when fed
+a garbage file as a core file. Does the current one?
+
+Breakpoints should not be inserted and deleted all the time. Only the
+one(s) there should be removed when we have to step over one. Support
+breakpoints that don't have to be removed to step over them.
+
+Stop reading stop_registers!
+
+Generalize and Standardize the RPC interface to a target program,
+improve it beyond the "ptrace" interface, and see if it can become a standard
+for remote debugging. Is WRS interested in donating their target-end
+code?
+
+Remove all references to:
+ text_offset
+ data_offset
+ text_data_start
+ text_end
+ exec_data_offset
+ ...
+now that we have BFD. All remaining are in machine dependent files.
+
+When quitting with a running program, if a core file was previously
+examined, you get "Couldn't read float regs from core file"...if
+indeed it can't. generic_mourn_inferior...
+
+...
+
+Check signal argument to remote proceed's and error if set.
+
+Handle floating point registers in core files under BFD. Currently
+they are punted.
+
+Sort help and info output.
+
+Re-organize help categories into things that tend to fit on a screen
+and hang together.
+
+When trying to print source lines but you can't find the file,
+print the file name and line number, and leave it selected anyway
+so "i source" will show it.
+
+renote-nindy.c handles interrupts poorly; it error()s out of badly
+chosen places, e.g. leaving current_frame zero, which causes core dumps
+on the next command.
+
+Add in commands like ADB's for searching for patterns, etc. We should
+be able to examine and patch raw unsymboled binaries as well in gdb as
+we can in adb. (E.g. increase the timeout in /bin/login without source).
+
+Those xdep files that call register_addr without defining it are
+probably simply broken. When reconfiguring this part of gdb, I could
+only make guesses about how to redo some of those files, and I
+probably guessed wrong, or left them "for later" when I have a
+machine that can attempt to build them.
+
+Use the complain() mechanism for handling all the error() calls in dbxread.c,
+and in similar situations in coffread.c and mipsread.c.
+
+When doing "step" or "next", if a few lines of source are skipped between
+the previous line and the current one, print those lines, not just the
+last line of a multiline statement.
+
+When searching for C++ superclasses in value_cast in valops.c, we must
+not search the "fields", only the "superclasses". There might be a
+struct with a field name that matches the superclass name. This can
+happen when the struct was defined before the superclass (before the
+name became a typedef).
+
+For "float point[15];":
+ptype &point[4] ==> Attempt to take address of non-lvalue.
+p &point[4] ==> Dereferences point[4] rather than giving you point+4.
+
+Fix symbol reading in the presence of interrupts. It currently leaves a
+cleanup to blow away the entire symbol table when a QUIT occurs.
+
--- /dev/null
+ GDB 4.0 -- what has changed since 3.5?
+
+ * New Facilities
+
+Gdb now paginates its output, with a ``more''-like interface. You can
+set the screen width and screen height with new ``set'' commands; they
+default to your terminal settings. Wide output is wrapped at good
+places to make the output more readable.
+
+Gdb now reads its input via the ``readline'' interface. This provides
+inline editing of commands, using familiar Emacs or VI commands (like
+``tcsh'' or the korn shell); history substitutions a la the C shell;
+and storage and recall of your command history across debugging
+sessions. The default is Emacs mode; to switch temporarily to vi mode,
+use control-meta-J or ESC control-j. You can switch permanently to vi
+mode by putting the line ``set editing-mode vi'' in the file .inputrc
+in your home directory. For full details, see the description in
+readline/inc-readline.texinfo and readline/inc-history.texinfo.
+
+Gdb now supports cross-debugging from a host machine of one type to a
+target machine of another type. Communication with the target system
+is over serial lines. The ``target'' command handles connecting to the
+remote system; the ``load'' command will download a program into the
+remote system. It also supports debugging of realtime processes
+running under VxWorks, using SunRPC Remote Procedure Calls over TCP/IP
+to talk to a debugger stub on the target system.
+
+New CPUs supported include the AMD 29000 and Intel 960.
+
+GDB now reads object files and symbol tables via a ``binary file''
+library, which allows a single copy of GDB to debug programs of multiple
+object file types such as a.out and coff.
+
+There is now a GDB reference card in "gdbrc.tex".
+
+
+ * Control-Variable user interface simplified
+
+All variables that control the operation of the debugger can be set
+by the ``set'' command, and displayed by the ``show'' command.
+
+For example, ``set prompt new-gdb=>'' will change your prompt to new-gdb=>.
+``Show prompt'' produces the response:
+Gdb's prompt is new-gdb=>.
+
+What follows are the NEW set commands. The command ``help set'' will
+print a complete list of old and new set commands. ``help set FOO''
+will give a longer description of the variable FOO.
+
+caution on/off: Enables warning questions for operations that are
+ hard to recover from, e.g. rerunning the program while
+ it is already running. Default is ON.
+
+editing on/off: Enables EMACS style command line editing
+ of input. Previous lines can be recalled with
+ control-P, the current line can be edited with control-B,
+ you can search for commands with control-R, etc.
+ Default is ON.
+
+history filename NAME: NAME is where the gdb command history
+ will be stored. The default is .gdb_history,
+ or the value of the environment variable
+ GDBHISTFILE.
+
+history size N: The size, in commands, of the command history. The
+ default is 256, or the value of the environment variable
+ HISTSIZE.
+
+history write on/off: If this value is set to ON, the history file will
+ be saved after exiting gdb. If set to OFF, the
+ file will not be saved. The default is OFF.
+
+history expansion on/off: If this value is set to ON, then csh-like
+ history expansion will be performed on
+ command line input. The default is OFF.
+
+radix N: Sets the default radix for input and output. It can be set
+ to 8, 10, or 16. Note that the argument to "radix" is interpreted
+ in the current radix, so "set radix 10" is always a no-op.
+
+screen-height N: This integer value is the number of lines on a page. Default
+ is 24, the current `stty rows'' setting, or the ``li#''
+ setting from the termcap entry matching the environment
+ variable TERM.
+
+screen-width N: This integer value is the number of characters on a line.
+ Default is 80, the current `stty cols'' setting, or the ``co#''
+ setting from the termcap entry matching the environment
+ variable TERM.
+
+Note: ``set screensize'' is obsolete. Use ``set screen-height'' and
+``set screen-width'' instead.
+
+addressprint on/off: Print memory addresses in various command displays,
+ such as stack traces and structure values. Gdb looks
+ more ``symbolic'' if you turn this off; it looks more
+ ``machine level'' with it on. Default is ON.
+
+arrayprint on/off: Prettyprint arrays. New convenient format! Default
+ is OFF.
+
+demangle on/off: Print C++ symbols in "source" form if on, "raw" form if off.
+
+asm-demangle on/off: Same, for assembler level printouts like instructions.
+
+vtblprint on/off: Prettyprint C++ virtual function tables. Default is OFF.
+
+
+ * Support for Epoch Environment.
+
+The epoch environment is a version of Emacs v18 with windowing. One
+new command, ``inspect'', is identical to ``print'', except that if you
+are running in the epoch environment, the value is printed in its own
+window.
+
+
+ * Support for Shared Libraries
+
+GDB can now debug programs and core files that use SunOS shared libraries.
+Symbols from a shared library cannot be referenced
+before the shared library has been linked with the program (this
+happens after you type ``run'' and before the function main() is entered).
+At any time after this linking (including when examining core files
+from dynamically linked programs), gdb reads the symbols from each
+shared library when you type the ``sharedlibrary'' command.
+It can be abbreviated ``share''.
+
+sharedlibrary REGEXP: Load shared object library symbols for files
+ matching a unix regular expression. No argument
+ indicates to load symbols for all shared libraries.
+
+info sharedlibrary: Status of loaded shared libraries.
+
+
+ * Watchpoints
+
+A watchpoint stops execution of a program whenever the value of an
+expression changes. Checking for this slows down execution
+tremendously whenever you are in the scope of the expression, but is
+quite useful for catching tough ``bit-spreader'' or pointer misuse
+problems. Some machines such as the 386 have hardware for doing this
+more quickly, and future versions of gdb will use this hardware.
+
+watch EXP: Set a watchpoint (breakpoint) for an expression.
+
+info watchpoints: Information about your watchpoints.
+
+delete N: Deletes watchpoint number N (same as breakpoints).
+disable N: Temporarily turns off watchpoint number N (same as breakpoints).
+enable N: Re-enables watchpoint number N (same as breakpoints).
+
+
+ * C++ multiple inheritance
+
+When used with a GCC version 2 compiler, GDB supports multiple inheritance
+for C++ programs.
+
+ * C++ exception handling
+
+Gdb now supports limited C++ exception handling. Besides the existing
+ability to breakpoint on an exception handler, gdb can breakpoint on
+the raising of an exception (before the stack is peeled back to the
+handler's context).
+
+catch FOO: If there is a FOO exception handler in the dynamic scope,
+ set a breakpoint to catch exceptions which may be raised there.
+ Multiple exceptions (``catch foo bar baz'') may be caught.
+
+info catch: Lists all exceptions which may be caught in the
+ current stack frame.
+
+
+ * Minor command changes
+
+The command ``call func (arg, arg, ...)'' now acts like the print
+command, except it does not print or save a value if the function's result
+is void. This is similar to dbx usage.
+
+The ``up'' and ``down'' commands now always print the frame they end up
+at; ``up-silently'' and `down-silently'' can be used in scripts to change
+frames without printing.
+
+ * New directory command
+
+'dir' now adds directories to the FRONT of the source search path.
+The path starts off empty. Source files that contain debug information
+about the directory in which they were compiled can be found even
+with an empty path; GCC includes this information. If GDB can't find
+your source file in the current directory, type "dir .".
+
+ * Features removed in this release
+
+``info types'' has been removed, since it printed builtin types in a
+confusing fashion, and did not do useful things with typedefs. ``ptype''
+or ``whatis'' are more useful commands for dealing with types..
+
+
+ * Configuring GDB for compilation
+
+For normal use, type ``config.gdb host''. Hosts now handled are:
+
+3b1 altos altosgas arm bigmips convex hp300bsd hp300hpux i386v i386v-g
+i386v32 i386v32-g isi littlemips m88k merlin news news1000 none np1 pn
+pyramid sun2os3 sun2os4 sun386 sun3os3 sun3os4 sun4os3 sun4os4 symmetry
+umax vax
+
+Type config.gdb +host to get a full description of each host.
+
+You can now build gdb conveniently for several architectures from the
+same sources. If config.gdb is run from a subdirectory, it configures
+the Makefile to use source files from '..'. Each subdirectory can be
+indpendently configured. An explicit source file directory can also
+be specified with the +srcdir=xxx option. Due to obscure search rules
+in the C preprocessor, if you have previously built gdb in the main
+directory, run 'make cleanconfig' in the top level directory before
+building it in a subdirectory.
+
+GDB now handles cross debugging. If you are remotely debugging between
+two different machines, type ``config.gdb host target''.
+Host is the machine where gdb will run; target is the machine
+where the program that you are debugging will run.
+
+Type config.gdb +target to get a full description of each target.
--- /dev/null
+ALLDEPFILES = $(ALLDEPFILES_MAINDIR) $(ALLDEPFILES_SUBDIR)
+ALLDEPFILES_MAINDIR=\
+altos-xdep.c\
+am29k-pinsn.c\
+am29k-tdep.c\
+arm-convert.s\
+arm-pinsn.c\
+arm-tdep.c\
+arm-xdep.c\
+convex-pinsn.c\
+convex-tdep.c\
+convex-xdep.c\
+coredep.c\
+exec.c\
+gould-pinsn.c\
+gould-xdep.c\
+hp300hpux-xdep.c\
+i386-pinsn.c\
+i386-tdep.c\
+i386-xdep.c\
+i960-pinsn.c\
+i960-tdep.c\
+infptrace.c\
+m68k-pinsn.c\
+m68k-tdep.c\
+mips-pinsn.c\
+mips-tdep.c\
+mips-xdep.c\
+mipsread.c\
+news-xdep.c\
+nindy-tdep.c\
+ns32k-pinsn.c\
+pyr-pinsn.c\
+pyr-tdep.c\
+pyr-xdep.c\
+remote-eb.c\
+remote-nindy.c\
+remote-vx.c\
+solib.c\
+sparc-pinsn.c\
+sparc-tdep.c\
+sparc-xdep.c\
+sun3-xdep.c\
+sun386-xdep.c\
+symmetry-tdep.c\
+symmetry-xdep.c\
+tdesc.c\
+umax-xdep.c\
+vax-pinsn.c
+
+ALLDEPFILES_SUBDIR=\
+nindy-share/Onindy.c\
+nindy-share/nindy.c\
+nindy-share/ttybreak.c\
+nindy-share/ttyflush.c\
+vx-share/xdr_ld.c\
+vx-share/xdr_ptrace.c\
+vx-share/xdr_rdb.c\
+vx-share/xdr_regs.c
+
+ALLPARAM=\
+tm-29k.h\
+tm-3b1.h\
+tm-88k.h\
+tm-altos.h\
+tm-altosgas.h\
+tm-arm.h\
+tm-bigmips.h\
+tm-convex.h\
+tm-hp300bsd.h\
+tm-hp300hpux.h\
+tm-i386v-g.h\
+tm-i386v.h\
+tm-isi.h\
+tm-merlin.h\
+tm-mips.h\
+tm-news.h\
+tm-nindy960.h\
+tm-np1.h\
+tm-pn.h\
+tm-pyr.h\
+tm-sparc.h\
+tm-sun2.h\
+tm-sun2os4.h\
+tm-sun3.h\
+tm-sun386.h\
+tm-sun3os4.h\
+tm-sun4os4.h\
+tm-symmetry.h\
+tm-umax.h\
+tm-vax.h\
+tm-vxworks68.h\
+tm-vxworks960.h\
+xm-3b1.h\
+xm-88k.h\
+xm-altos.h\
+xm-arm.h\
+xm-bigmips.h\
+xm-convex.h\
+xm-hp300bsd.h\
+xm-hp300hpux.h\
+xm-i386v.h\
+xm-i386v32.h\
+xm-isi.h\
+xm-merlin.h\
+xm-mips.h\
+xm-news.h\
+xm-news1000.h\
+xm-np1.h\
+xm-pn.h\
+xm-pyr.h\
+xm-sparc.h\
+xm-sun2.h\
+xm-sun3.h\
+xm-sun386.h\
+xm-sun3os4.h\
+xm-sun4os4.h\
+xm-symmetry.h\
+xm-umax.h\
+xm-vax.h
+
+ALLCONFIG=\
+./tconfig/3b1\
+./tconfig/altos\
+./tconfig/altosgas\
+./tconfig/am29k\
+./tconfig/arm\
+./tconfig/bigmips\
+./tconfig/convex\
+./tconfig/hp300bsd\
+./tconfig/hp300hpux\
+./tconfig/i386v\
+./tconfig/i386v-g\
+./tconfig/i386v32\
+./tconfig/i386v32-g\
+./tconfig/i960\
+./tconfig/isi\
+./tconfig/littlemips\
+./tconfig/m88k\
+./tconfig/merlin\
+./tconfig/news\
+./tconfig/news1000\
+./tconfig/nindy960\
+./tconfig/none\
+./tconfig/np1\
+./tconfig/pn\
+./tconfig/pyramid\
+./tconfig/sun2os3\
+./tconfig/sun2os4\
+./tconfig/sun3\
+./tconfig/sun386\
+./tconfig/sun3os3\
+./tconfig/sun3os4\
+./tconfig/sun4\
+./tconfig/sun4os3\
+./tconfig/sun4os4\
+./tconfig/symmetry\
+./tconfig/umax\
+./tconfig/vax\
+./tconfig/vxworks68\
+./tconfig/vxworks960\
+./xconfig/3b1\
+./xconfig/altos\
+./xconfig/altosgas\
+./xconfig/arm\
+./xconfig/bigmips\
+./xconfig/convex\
+./xconfig/hp300bsd\
+./xconfig/hp300hpux\
+./xconfig/i386v\
+./xconfig/i386v-g\
+./xconfig/i386v32\
+./xconfig/i386v32-g\
+./xconfig/isi\
+./xconfig/littlemips\
+./xconfig/m88k\
+./xconfig/merlin\
+./xconfig/news\
+./xconfig/news1000\
+./xconfig/none\
+./xconfig/np1\
+./xconfig/pn\
+./xconfig/pyramid\
+./xconfig/sun2os3\
+./xconfig/sun2os4\
+./xconfig/sun3\
+./xconfig/sun386\
+./xconfig/sun3os3\
+./xconfig/sun3os4\
+./xconfig/sun4\
+./xconfig/sun4os3\
+./xconfig/sun4os4\
+./xconfig/symmetry\
+./xconfig/umax\
+./xconfig/vax
+
--- /dev/null
+/*
+ alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+ last edit: 86/05/30 rms
+ include config.h, since on VMS it renames some symbols.
+ Use xmalloc instead of malloc.
+
+ This implementation of the PWB library alloca() function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+
+ It should work under any C implementation that uses an
+ actual procedure stack (as opposed to a linked list of
+ frames). There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca()-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif static
+#endif emacs
+
+#ifdef __STDC__
+typedef void *pointer; /* generic pointer type */
+#else
+typedef char *pointer; /* generic pointer type */
+#endif
+
+#define NULL 0 /* null pointer constant */
+
+extern void free();
+extern pointer xmalloc();
+
+/*
+ Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+*/
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* known at compile-time */
+
+#else /* STACK_DIRECTION == 0; need run-time code */
+
+static int stack_dir; /* 1 or -1 once known */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+ static char *addr = NULL; /* address of first
+ `dummy', once known */
+ auto char dummy; /* to get stack address */
+
+ if (addr == NULL)
+ { /* initial entry */
+ addr = &dummy;
+
+ find_stack_direction (); /* recurse once */
+ }
+ else /* second entry */
+ if (&dummy > addr)
+ stack_dir = 1; /* stack grew upward */
+ else
+ stack_dir = -1; /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+ An "alloca header" is used to:
+ (a) chain together all alloca()ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc()
+ alignment chunk size. The following default should work okay.
+*/
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* to force sizeof(header) */
+ struct
+ {
+ union hdr *next; /* for chaining headers */
+ char *deep; /* for stack depth measure */
+ } h;
+} header;
+
+/*
+ alloca( size ) returns a pointer to at least `size' bytes of
+ storage which will be automatically reclaimed upon exit from
+ the procedure that called alloca(). Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size) /* returns pointer to storage */
+ unsigned size; /* # bytes to allocate */
+{
+ auto char probe; /* probes stack depth: */
+ register char *depth = &probe;
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* unknown growth direction */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca()ed storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* traverses linked list */
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if (STACK_DIR > 0 && hp->h.deep > depth
+ || STACK_DIR < 0 && hp->h.deep < depth)
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* collect garbage */
+
+ hp = np; /* -> next header */
+ }
+ else
+ break; /* rest are not deeper */
+
+ last_alloca_header = hp; /* -> last valid storage */
+ }
+
+ if (size == 0)
+ return NULL; /* no allocation required */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = xmalloc (sizeof (header) + size);
+ /* address of header */
+
+ ((header *)new)->h.next = last_alloca_header;
+ ((header *)new)->h.deep = depth;
+
+ last_alloca_header = (header *)new;
+
+ /* User storage begins just after header. */
+
+ return (pointer)((char *)new + sizeof(header));
+ }
+}
+
--- /dev/null
+/* Low level interface to ptrace, for GDB when running under m68k SVR2 Unix
+ on Altos 3068. Report bugs to Jyrki Kuoppala <jkp@cs.hut.fi>
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#ifdef USG
+#include <sys/page.h>
+#ifdef ALTOS
+#include <sys/net.h>
+#include <errno.h>
+#endif
+#endif
+
+#include "gdbcore.h"
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+ data_start = exec_data_start;
+
+#if !defined (NBPG)
+#define NBPG NBPP
+#endif
+#if !defined (UPAGES)
+#define UPAGES USIZE
+#endif
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES + exec_data_start % NBPG /* Not sure about this //jkp */;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_state;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+
+ bcopy (&u.u_exdata, &core_aouthdr, sizeof (AOUTHDR));
+ printf ("Core file is from \"%s\".\n", u.u_comm);
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (reg_names[regno])
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
--- /dev/null
+/* Table of opcodes for the AMD 29000
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct am29k_opcode {
+ /* Name of the instruction. */
+ char *name;
+
+ /* Opcode (i.e. most significant byte of the word). */
+ unsigned char opcode;
+
+ /* A string of characters which describe the operands.
+ Valid characters are:
+ , Itself. The character appears in the assembly code.
+ a RA. The register number is in bits 8-15 of the instruction.
+ b RB. The register number is in bits 0-7 of the instruction.
+ c RC. The register number is in bits 16-23 of the instruction.
+ i An immediate operand is in bits 0-7 of the instruction.
+ x Bits 0-7 and 16-23 of the instruction are bits 0-7 and 8-15
+ (respectively) of the immediate operand.
+ h Same as x but the instruction contains bits 16-31 of the
+ immediate operand.
+ X Same as x but bits 16-31 of the signed immediate operand
+ are set to 1 (thus the operand is always negative).
+ P,A Bits 0-7 and 16-23 of the instruction are bits 2-9 and 10-17
+ (respectively) of the immediate operand.
+ P=PC-relative, sign-extended to 32 bits.
+ A=Absolute, zero-extended to 32 bits.
+ e CE bit (bit 23) for a load/store instruction.
+ n Control field (bits 16-22) for a load/store instruction.
+ v Immediate operand in bits 16-23 of the instruction.
+ (used for trap numbers).
+ s SA. Special-purpose register number in bits 8-15
+ of the instruction.
+ u UI--bit 7 of the instruction.
+ r RND--bits 4-6 of the instruction.
+ d FD--bits 2-3 of the instruction.
+ f FS--bits 0-1 of the instruction. */
+ char *args;
+};
+
+static struct am29k_opcode am29k_opcodes[] =
+{
+
+{ "add", 0x14, "c,a,b" },
+{ "add", 0x15, "c,a,i" },
+{ "addc", 0x1c, "c,a,b" },
+{ "addc", 0x1d, "c,a,i" },
+{ "addcs", 0x18, "c,a,b" },
+{ "addcs", 0x19, "c,a,i" },
+{ "addcu", 0x1a, "c,a,b" },
+{ "addcu", 0x1b, "c,a,i" },
+{ "adds", 0x10, "c,a,b" },
+{ "adds", 0x11, "c,a,i" },
+{ "addu", 0x12, "c,a,b" },
+{ "addu", 0x13, "c,a,i" },
+{ "and", 0x90, "c,a,b" },
+{ "and", 0x91, "c,a,i" },
+{ "andn", 0x9c, "c,a,b" },
+{ "andn", 0x9d, "c,a,i" },
+{ "aseq", 0x70, "v,a,b" },
+{ "aseq", 0x71, "v,a,i" },
+{ "asge", 0x5c, "v,a,b" },
+{ "asge", 0x5d, "v,a,i" },
+{ "asgeu", 0x5e, "v,a,b" },
+{ "asgeu", 0x5f, "v,a,i" },
+{ "asgt", 0x58, "v,a,b" },
+{ "asgt", 0x59, "v,a,i" },
+{ "asgtu", 0x5a, "v,a,b" },
+{ "asgtu", 0x5b, "v,a,i" },
+{ "asle", 0x54, "v,a,b" },
+{ "asle", 0x55, "v,a,i" },
+{ "asleu", 0x56, "v,a,b" },
+{ "asleu", 0x57, "v,a,i" },
+{ "aslt", 0x50, "v,a,b" },
+{ "aslt", 0x51, "v,a,i" },
+{ "asltu", 0x52, "v,a,b" },
+{ "asltu", 0x53, "v,a,i" },
+{ "asneq", 0x72, "v,a,b" },
+{ "asneq", 0x73, "v,a,i" },
+{ "call", 0xa8, "a,P" },
+{ "call", 0xa9, "a,A" },
+{ "calli", 0xc8, "a,b" },
+{ "class", 0xe6, "c,a,f" },
+{ "clz", 0x08, "c,b" },
+{ "clz", 0x09, "c,i" },
+{ "const", 0x03, "a,x" },
+{ "consth", 0x02, "a,h" },
+{ "consthz", 0x05, "a,h" },
+{ "constn", 0x01, "a,X" },
+{ "convert", 0xe4, "c,a,u,r,d,f" },
+{ "cpbyte", 0x2e, "c,a,b" },
+{ "cpbyte", 0x2f, "c,a,i" },
+{ "cpeq", 0x60, "c,a,b" },
+{ "cpeq", 0x61, "c,a,i" },
+{ "cpge", 0x4c, "c,a,b" },
+{ "cpge", 0x4d, "c,a,i" },
+{ "cpgeu", 0x4e, "c,a,b" },
+{ "cpgeu", 0x4f, "c,a,i" },
+{ "cpgt", 0x48, "c,a,b" },
+{ "cpgt", 0x49, "c,a,i" },
+{ "cpgtu", 0x4a, "c,a,b" },
+{ "cpgtu", 0x4b, "c,a,i" },
+{ "cple", 0x44, "c,a,b" },
+{ "cple", 0x45, "c,a,i" },
+{ "cpleu", 0x46, "c,a,b" },
+{ "cpleu", 0x47, "c,a,i" },
+{ "cplt", 0x40, "c,a,b" },
+{ "cplt", 0x41, "c,a,i" },
+{ "cpltu", 0x42, "c,a,b" },
+{ "cpltu", 0x43, "c,a,i" },
+{ "cpneq", 0x62, "c,a,b" },
+{ "cpneq", 0x63, "c,a,i" },
+{ "dadd", 0xf1, "c,a,b" },
+{ "ddiv", 0xf7, "c,a,b" },
+{ "deq", 0xeb, "c,a,b" },
+{ "dge", 0xef, "c,a,b" },
+{ "dgt", 0xed, "c,a,b" },
+{ "div", 0x6a, "c,a,b" },
+{ "div", 0x6b, "c,a,i" },
+{ "div0", 0x68, "c,b" },
+{ "div0", 0x69, "c,i" },
+{ "divide", 0xe1, "c,a,b" },
+{ "dividu", 0xe3, "c,a,b" },
+{ "divl", 0x6c, "c,a,b" },
+{ "divl", 0x6d, "c,a,i" },
+{ "divrem", 0x6e, "c,a,b" },
+{ "divrem", 0x6f, "c,a,i" },
+{ "dmac", 0xd9, "F,C,a,b" },
+{ "dmsm", 0xdb, "c,a,b" },
+{ "dmul", 0xf5, "c,a,b" },
+{ "dsub", 0xf3, "c,a,b" },
+{ "emulate", 0xd7, "v,a,b" },
+{ "exbyte", 0x0a, "c,a,b" },
+{ "exbyte", 0x0b, "c,a,i" },
+{ "exhw", 0x7c, "c,a,b" },
+{ "exhw", 0x7d, "c,a,i" },
+{ "exhws", 0x7e, "c,a" },
+{ "extract", 0x7a, "c,a,b" },
+{ "extract", 0x7b, "c,a,i" },
+{ "fadd", 0xf0, "c,a,b" },
+{ "fdiv", 0xf6, "c,a,b" },
+{ "fdmul", 0xf9, "c,a,b" },
+{ "feq", 0xea, "c,a,b" },
+{ "fge", 0xee, "c,a,b" },
+{ "fgt", 0xec, "c,a,b" },
+{ "fmac", 0xd8, "F,C,a,b" },
+{ "fmsm", 0xda, "c,a,b" },
+{ "fmul", 0xf4, "c,a,b" },
+{ "fsub", 0xf2, "c,a,b" },
+{ "halt", 0x89, "" },
+{ "inbyte", 0x0c, "c,a,b" },
+{ "inbyte", 0x0d, "c,a,i" },
+{ "inhw", 0x78, "c,a,b" },
+{ "inhw", 0x79, "c,a,i" },
+{ "inv", 0x9f, "" },
+{ "iret", 0x88, "" },
+{ "iretinv", 0x8c, "" },
+{ "jmp", 0xa0, "P" },
+{ "jmp", 0xa1, "A" },
+{ "jmpf", 0xa4, "a,P" },
+{ "jmpf", 0xa5, "a,A" },
+{ "jmpfdec", 0xb4, "a,P" },
+{ "jmpfdec", 0xb5, "a,A" },
+{ "jmpfi", 0xc4, "a,b" },
+{ "jmpi", 0xc0, "b" },
+{ "jmpt", 0xac, "a,P" },
+{ "jmpt", 0xad, "a,A" },
+{ "jmpti", 0xcc, "a,b" },
+{ "load", 0x16, "e,n,a,b" },
+{ "load", 0x17, "e,n,a,i" },
+{ "loadl", 0x06, "e,n,a,b" },
+{ "loadl", 0x07, "e,n,a,i" },
+{ "loadm", 0x36, "e,n,a,b" },
+{ "loadm", 0x37, "e,n,a,i" },
+{ "loadset", 0x26, "e,n,a,b" },
+{ "loadset", 0x27, "e,n,a,i" },
+{ "mfacc", 0xe9, "c,d,f" },
+{ "mfsr", 0xc6, "c,s" },
+{ "mftlb", 0xb6, "c,a" },
+{ "mtacc", 0xe8, "c,d,f" },
+{ "mtsr", 0xce, "s,b" },
+{ "mtsrim", 0x04, "s,x" },
+{ "mttlb", 0xbe, "a,b" },
+{ "mul", 0x64, "c,a,b" },
+{ "mul", 0x65, "c,a,i" },
+{ "mull", 0x66, "c,a,b" },
+{ "mull", 0x67, "c,a,i" },
+{ "multiplu", 0xe2, "c,a,b" },
+{ "multiply", 0xe0, "c,a,b" },
+{ "multm", 0xde, "c,a,b" },
+{ "multmu", 0xdf, "c,a,b" },
+{ "mulu", 0x74, "c,a,b" },
+{ "mulu", 0x75, "c,a,i" },
+{ "nand", 0x9a, "c,a,b" },
+{ "nand", 0x9b, "c,a,i" },
+{ "nor", 0x98, "c,a,b" },
+{ "nor", 0x99, "c,a,i" },
+{ "or", 0x92, "c,a,b" },
+{ "or", 0x93, "c,a,i" },
+{ "orn", 0xaa, "c,a,b" },
+{ "orn", 0xab, "c,a,i" },
+
+/* The description of "setip" in Chapter 8 ("instruction set") of the user's
+ manual claims that these are absolute register numbers. But section
+ 7.2.1 explains that they are not. The latter is correct, so print
+ these normally ("lr0", "lr5", etc.). */
+{ "setip", 0x9e, "c,a,b" },
+
+{ "sll", 0x80, "c,a,b" },
+{ "sll", 0x81, "c,a,i" },
+{ "sqrt", 0xe5, "c,a,f" },
+{ "sra", 0x86, "c,a,b" },
+{ "sra", 0x87, "c,a,i" },
+{ "srl", 0x82, "c,a,b" },
+{ "srl", 0x83, "c,a,i" },
+{ "store", 0x1e, "e,n,a,b" },
+{ "store", 0x1f, "e,n,a,i" },
+{ "storel", 0x0e, "e,n,a,b" },
+{ "storel", 0x0f, "e,n,a,i" },
+{ "storem", 0x3e, "e,n,a,b" },
+{ "storem", 0x3f, "e,n,a,i" },
+{ "sub", 0x24, "c,a,b" },
+{ "sub", 0x25, "c,a,i" },
+{ "subc", 0x2c, "c,a,b" },
+{ "subc", 0x2d, "c,a,i" },
+{ "subcs", 0x28, "c,a,b" },
+{ "subcs", 0x29, "c,a,i" },
+{ "subcu", 0x2a, "c,a,b" },
+{ "subcu", 0x2b, "c,a,i" },
+{ "subr", 0x34, "c,a,b" },
+{ "subr", 0x35, "c,a,i" },
+{ "subrc", 0x3c, "c,a,b" },
+{ "subrc", 0x3d, "c,a,i" },
+{ "subrcs", 0x38, "c,a,b" },
+{ "subrcs", 0x39, "c,a,i" },
+{ "subrcu", 0x3a, "c,a,b" },
+{ "subrcu", 0x3b, "c,a,i" },
+{ "subrs", 0x30, "c,a,b" },
+{ "subrs", 0x31, "c,a,i" },
+{ "subru", 0x32, "c,a,b" },
+{ "subru", 0x33, "c,a,i" },
+{ "subs", 0x20, "c,a,b" },
+{ "subs", 0x21, "c,a,i" },
+{ "subu", 0x22, "c,a,b" },
+{ "subu", 0x23, "c,a,i" },
+{ "xnor", 0x96, "c,a,b" },
+{ "xnor", 0x97, "c,a,i" },
+{ "xor", 0x94, "c,a,b" },
+{ "xor", 0x95, "c,a,i" }
+
+};
+
+#define NUM_OPCODES ((sizeof am29k_opcodes) / (sizeof am29k_opcodes[0]))
+
--- /dev/null
+/* Instruction printing code for the AMD 29000
+ Copyright (C) 1990 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "target.h"
+#include "am29k-opcode.h"
+
+/* Print a symbolic representation of a general-purpose
+ register number NUM on STREAM.
+ NUM is a number as found in the instruction, not as found in
+ debugging symbols; it must be in the range 0-255. */
+static void
+print_general (num, stream)
+ int num;
+ FILE *stream;
+{
+ if (num < 128)
+ fprintf_filtered (stream, "gr%d", num);
+ else
+ fprintf_filtered (stream, "lr%d", num - 128);
+}
+
+/* Like print_general but a special-purpose register.
+
+ The mnemonics used by the AMD assembler are not quite the same
+ as the ones in the User's Manual. We use the ones that the
+ assembler uses. */
+static void
+print_special (num, stream)
+ int num;
+ FILE *stream;
+{
+ /* Register names of registers 0-SPEC0_NUM-1. */
+ static char *spec0_names[] = {
+ "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr",
+ "pc0", "pc1", "pc2", "mmu", "lru"
+ };
+#define SPEC0_NUM ((sizeof spec0_names) / (sizeof spec0_names[0]))
+
+ /* Register names of registers 128-128+SPEC128_NUM-1. */
+ static char *spec128_names[] = {
+ "ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr"
+ };
+#define SPEC128_NUM ((sizeof spec128_names) / (sizeof spec128_names[0]))
+
+ /* Register names of registers 160-160+SPEC160_NUM-1. */
+ static char *spec160_names[] = {
+ "fpe", "inte", "fps", "sr163", "exop"
+ };
+#define SPEC160_NUM ((sizeof spec160_names) / (sizeof spec160_names[0]))
+
+ if (num < SPEC0_NUM)
+ fprintf_filtered (stream, spec0_names[num]);
+ else if (num >= 128 && num < 128 + SPEC128_NUM)
+ fprintf_filtered (stream, spec128_names[num-128]);
+ else if (num >= 160 && num < 160 + SPEC160_NUM)
+ fprintf_filtered (stream, spec160_names[num-160]);
+ else
+ fprintf_filtered (stream, "sr%d", num);
+}
+
+/* Is an instruction with OPCODE a delayed branch? */
+static int
+is_delayed_branch (opcode)
+ int opcode;
+{
+ return (opcode == 0xa8 || opcode == 0xa9 || opcode == 0xa0 || opcode == 0xa1
+ || opcode == 0xa4 || opcode == 0xa5
+ || opcode == 0xb4 || opcode == 0xb5
+ || opcode == 0xc4 || opcode == 0xc0
+ || opcode == 0xac || opcode == 0xad
+ || opcode == 0xcc);
+}
+
+/* Now find the four bytes of INSN and put them in *INSN{0,8,16,24}.
+ Note that the amd can be set up as either
+ big or little-endian (the tm file says which) and we can't assume
+ the host machine is the same. */
+static void
+find_bytes (insn, insn0, insn8, insn16, insn24)
+ char *insn;
+ unsigned char *insn0;
+ unsigned char *insn8;
+ unsigned char *insn16;
+ unsigned char *insn24;
+{
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+ *insn24 = insn[0];
+ *insn16 = insn[1];
+ *insn8 = insn[2];
+ *insn0 = insn[3];
+#else /* Little-endian. */
+ *insn24 = insn[3];
+ *insn16 = insn[2];
+ *insn8 = insn[1];
+ *insn0 = insn[0];
+#endif /* Little-endian. */
+}
+
+/* Print one instruction from MEMADDR on STREAM.
+ Return the size of the instruction (always 4 on am29k). */
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ /* The raw instruction. */
+ char insn[4];
+
+ /* The four bytes of the instruction. */
+ unsigned char insn24, insn16, insn8, insn0;
+
+ struct am29k_opcode *opcode;
+
+ read_memory (memaddr, &insn[0], 4);
+
+ find_bytes (insn, &insn0, &insn8, &insn16, &insn24);
+
+ /* The opcode is always in insn24. */
+ for (opcode = &am29k_opcodes[0];
+ opcode < &am29k_opcodes[NUM_OPCODES];
+ ++opcode)
+ {
+ if (insn24 == opcode->opcode)
+ {
+ char *s;
+
+ fprintf_filtered (stream, "%s ", opcode->name);
+ for (s = opcode->args; *s != '\0'; ++s)
+ {
+ switch (*s)
+ {
+ case 'a':
+ print_general (insn8, stream);
+ break;
+
+ case 'b':
+ print_general (insn0, stream);
+ break;
+
+ case 'c':
+ print_general (insn16, stream);
+ break;
+
+ case 'i':
+ fprintf_filtered (stream, "%d", insn0);
+ break;
+
+ case 'x':
+ fprintf_filtered (stream, "%d", (insn16 << 8) + insn0);
+ break;
+
+ case 'h':
+ fprintf_filtered (stream, "0x%x",
+ (insn16 << 24) + (insn0 << 16));
+ break;
+
+ case 'X':
+ fprintf_filtered (stream, "%d",
+ ((insn16 << 8) + insn0) | 0xffff0000);
+ break;
+
+ case 'P':
+ /* This output looks just like absolute addressing, but
+ maybe that's OK (it's what the GDB 68k and EBMON
+ 29k disassemblers do). */
+ /* All the shifting is to sign-extend it. p*/
+ print_address
+ (memaddr +
+ (((int)((insn16 << 10) + (insn0 << 2)) << 14) >> 14),
+ stream);
+ break;
+
+ case 'A':
+ print_address ((insn16 << 10) + (insn0 << 2), stream);
+ break;
+
+ case 'e':
+ fprintf_filtered (stream, "%d", insn16 >> 7);
+ break;
+
+ case 'n':
+ fprintf_filtered (stream, "0x%x", insn16 & 0x7f);
+ break;
+
+ case 'v':
+ fprintf_filtered (stream, "%#x", insn16);
+ break;
+
+ case 's':
+ print_special (insn8, stream);
+ break;
+
+ case 'u':
+ fprintf_filtered (stream, "%d", insn0 >> 7);
+ break;
+
+ case 'r':
+ fprintf_filtered (stream, "%d", (insn0 >> 4) & 7);
+ break;
+
+ case 'd':
+ fprintf_filtered (stream, "%d", (insn0 >> 2) & 3);
+ break;
+
+ case 'f':
+ fprintf_filtered (stream, "%d", insn0 & 3);
+ break;
+
+ case 'F':
+ fprintf_filtered (stream, "%d", (insn0 >> 18) & 15);
+ break;
+
+ case 'C':
+ fprintf_filtered (stream, "%d", (insn0 >> 16) & 3);
+ break;
+
+ default:
+ fprintf_filtered (stream, "%c", *s);
+ }
+ }
+
+ /* Now we look for a const,consth pair of instructions,
+ in which case we try to print the symbolic address. */
+ if (insn24 == 2) /* consth */
+ {
+ int errcode;
+ char prev_insn[4];
+ unsigned char prev_insn0, prev_insn8, prev_insn16, prev_insn24;
+
+ errcode = target_read_memory (memaddr - 4,
+ &prev_insn[0],
+ 4);
+ if (errcode == 0)
+ {
+ /* If it is a delayed branch, we need to look at the
+ instruction before the delayed brach to handle
+ things like
+
+ const _foo
+ call _printf
+ consth _foo
+ */
+ find_bytes (prev_insn, &prev_insn0, &prev_insn8,
+ &prev_insn16, &prev_insn24);
+ if (is_delayed_branch (prev_insn24))
+ {
+ errcode = target_read_memory
+ (memaddr - 8, &prev_insn[0], 4);
+ find_bytes (prev_insn, &prev_insn0, &prev_insn8,
+ &prev_insn16, &prev_insn24);
+ }
+ }
+
+ /* If there was a problem reading memory, then assume
+ the previous instruction was not const. */
+ if (errcode == 0)
+ {
+ /* Is it const to the same register? */
+ if (prev_insn24 == 3
+ && prev_insn8 == insn8)
+ {
+ fprintf_filtered (stream, "\t; ");
+ print_address (((insn16 << 24) + (insn0 << 16)
+ + (prev_insn16 << 8) + (prev_insn0)),
+ stream);
+ }
+ }
+ }
+
+ return 4;
+ }
+ }
+ fprintf_filtered (stream, ".word %#8x",
+ (insn24 << 24) + (insn16 << 16) + (insn8 << 8) + insn0);
+ return 4;
+}
--- /dev/null
+/* Target-machine dependent code for the AMD 29000
+ Copyright (C) 1990 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include <stdio.h>
+#include "frame.h"
+#include "value.h"
+#include "param.h"
+#include "symtab.h"
+#include "inferior.h"
+
+/* Structure to hold cached info about function prologues. */
+struct prologue_info
+{
+ CORE_ADDR pc; /* First addr after fn prologue */
+ unsigned rsize, msize; /* register stack frame size, mem stack ditto */
+ unsigned mfp_used : 1; /* memory frame pointer used */
+ unsigned rsize_valid : 1; /* Validity bits for the above */
+ unsigned msize_valid : 1;
+ unsigned mfp_valid : 1;
+};
+
+/* Examine the prologue of a function which starts at PC. Return
+ the first addess past the prologue. If MSIZE is non-NULL, then
+ set *MSIZE to the memory stack frame size. If RSIZE is non-NULL,
+ then set *RSIZE to the register stack frame size (not including
+ incoming arguments and the return address & frame pointer stored
+ with them). If no prologue is found, *RSIZE is set to zero.
+ If no prologue is found, or a prologue which doesn't involve
+ allocating a memory stack frame, then set *MSIZE to zero.
+
+ Note that both msize and rsize are in bytes. This is not consistent
+ with the _User's Manual_ with respect to rsize, but it is much more
+ convenient.
+
+ If MFP_USED is non-NULL, *MFP_USED is set to nonzero if a memory
+ frame pointer is being used. */
+CORE_ADDR
+examine_prologue (pc, rsize, msize, mfp_used)
+ CORE_ADDR pc;
+ unsigned *msize;
+ unsigned *rsize;
+ int *mfp_used;
+{
+ long insn;
+ CORE_ADDR p = pc;
+ int misc_index = find_pc_misc_function (pc);
+ struct prologue_info *mi = 0;
+
+ if (misc_index >= 0)
+ mi = (struct prologue_info *)misc_function_vector[misc_index].misc_info;
+
+ if (mi != 0)
+ {
+ int valid = 1;
+ if (rsize != NULL)
+ {
+ *rsize = mi->rsize;
+ valid &= mi->rsize_valid;
+ }
+ if (msize != NULL)
+ {
+ *msize = mi->msize;
+ valid &= mi->msize_valid;
+ }
+ if (mfp_used != NULL)
+ {
+ *mfp_used = mi->mfp_used;
+ valid &= mi->mfp_valid;
+ }
+ if (valid)
+ return mi->pc;
+ }
+
+ if (rsize != NULL)
+ *rsize = 0;
+ if (msize != NULL)
+ *msize = 0;
+ if (mfp_used != NULL)
+ *mfp_used = 0;
+
+ /* Prologue must start with subtracting a constant from gr1.
+ Normally this is sub gr1,gr1,<rsize * 4>. */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) != 0x25010100)
+ {
+ /* If the frame is large, instead of a single instruction it
+ might be a pair of instructions:
+ const <reg>, <rsize * 4>
+ sub gr1,gr1,<reg>
+ */
+ int reg;
+ /* Possible value for rsize. */
+ unsigned int rsize0;
+
+ if ((insn & 0xff000000) != 0x03000000)
+ {
+ p = pc;
+ goto done;
+ }
+ reg = (insn >> 8) & 0xff;
+ rsize0 = (((insn >> 8) & 0xff00) | (insn & 0xff));
+ p += 4;
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) != 0x24010100
+ || (insn & 0xff) != reg)
+ {
+ p = pc;
+ goto done;
+ }
+ if (rsize != NULL)
+ *rsize = rsize0;
+ }
+ else
+ {
+ if (rsize != NULL)
+ *rsize = (insn & 0xff);
+ }
+ p += 4;
+
+ /* Next instruction must be asgeu V_SPILL,gr1,rab. */
+ insn = read_memory_integer (p, 4);
+ if (insn != 0x5e40017e)
+ {
+ p = pc;
+ goto done;
+ }
+ p += 4;
+
+ /* Next instruction usually sets the frame pointer (lr1) by adding
+ <size * 4> from gr1. However, this can (and high C does) be
+ deferred until anytime before the first function call. So it is
+ OK if we don't see anything which sets lr1. */
+ /* Normally this is just add lr1,gr1,<size * 4>. */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) == 0x15810100)
+ p += 4;
+ else
+ {
+ /* However, for large frames it can be
+ const <reg>, <size *4>
+ add lr1,gr1,<reg>
+ */
+ int reg;
+ CORE_ADDR q;
+
+ if ((insn & 0xff000000) == 0x03000000)
+ {
+ reg = (insn >> 8) & 0xff;
+ q = p + 4;
+ insn = read_memory_integer (q, 4);
+ if ((insn & 0xffffff00) == 0x14810100
+ && (insn & 0xff) == reg)
+ p = q;
+ }
+ }
+
+ /* Next comes "add lr{<rsize-1>},msp,0", but only if a memory
+ frame pointer is in use. We just check for add lr<anything>,msp,0;
+ we don't check this rsize against the first instruction, and
+ we don't check that the trace-back tag indicates a memory frame pointer
+ is in use.
+
+ The recommended instruction is actually "sll lr<whatever>,msp,0".
+ We check for that, too. Originally Jim Kingdon's code seemed
+ to be looking for a "sub" instruction here, but the mask was set
+ up to lose all the time. */
+ insn = read_memory_integer (p, 4);
+ if (((insn & 0xff80ffff) == 0x15807d00) /* add */
+ || ((insn & 0xff80ffff) == 0x81807d00) ) /* sll */
+ {
+ p += 4;
+ if (mfp_used != NULL)
+ *mfp_used = 1;
+ }
+
+ /* Next comes a subtraction from msp to allocate a memory frame,
+ but only if a memory frame is
+ being used. We don't check msize against the trace-back tag.
+
+ Normally this is just
+ sub msp,msp,<msize>
+ */
+ insn = read_memory_integer (p, 4);
+ if ((insn & 0xffffff00) == 0x257d7d00)
+ {
+ p += 4;
+ if (msize != NULL)
+ *msize = insn & 0xff;
+ }
+ else
+ {
+ /* For large frames, instead of a single instruction it might
+ be
+
+ const <reg>, <msize>
+ consth <reg>, <msize> ; optional
+ sub msp,msp,<reg>
+ */
+ int reg;
+ unsigned msize0;
+ CORE_ADDR q = p;
+
+ if ((insn & 0xff000000) == 0x03000000)
+ {
+ reg = (insn >> 8) & 0xff;
+ msize0 = ((insn >> 8) & 0xff00) | (insn & 0xff);
+ q += 4;
+ insn = read_memory_integer (q, 4);
+ /* Check for consth. */
+ if ((insn & 0xff000000) == 0x02000000
+ && (insn & 0x0000ff00) == reg)
+ {
+ msize0 |= (insn << 8) & 0xff000000;
+ msize0 |= (insn << 16) & 0x00ff0000;
+ q += 4;
+ insn = read_memory_integer (q, 4);
+ }
+ /* Check for sub msp,msp,<reg>. */
+ if ((insn & 0xffffff00) == 0x247d7d00
+ && (insn & 0xff) == reg)
+ {
+ p = q + 4;
+ if (msize != NULL)
+ *msize = msize0;
+ }
+ }
+ }
+
+ done:
+ if (misc_index >= 0)
+ {
+ if (mi == 0)
+ {
+ /* Add a new cache entry. */
+ mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info));
+ misc_function_vector[misc_index].misc_info = (char *)mi;
+ mi->rsize_valid = 0;
+ mi->msize_valid = 0;
+ mi->mfp_valid = 0;
+ }
+ /* else, cache entry exists, but info is incomplete. */
+ mi->pc = p;
+ if (rsize != NULL)
+ {
+ mi->rsize = *rsize;
+ mi->rsize_valid = 1;
+ }
+ if (msize != NULL)
+ {
+ mi->msize = *msize;
+ mi->msize_valid = 1;
+ }
+ if (mfp_used != NULL)
+ {
+ mi->mfp_used = *mfp_used;
+ mi->mfp_valid = 1;
+ }
+ }
+ return p;
+}
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+CORE_ADDR
+skip_prologue (pc)
+ CORE_ADDR pc;
+{
+ return examine_prologue (pc, (unsigned *)NULL, (unsigned *)NULL,
+ (int *)NULL);
+}
+
+/* Initialize the frame. In addition to setting "extra" frame info,
+ we also set ->frame because we use it in a nonstandard way, and ->pc
+ because we need to know it to get the other stuff. See the diagram
+ of stacks and the frame cache in tm-29k.h for more detail. */
+static void
+init_frame_info (innermost_frame, fci)
+ int innermost_frame;
+ struct frame_info *fci;
+{
+ CORE_ADDR p;
+ long insn;
+ unsigned rsize;
+ unsigned msize;
+ int mfp_used;
+ struct symbol *func;
+
+ p = fci->pc;
+
+ if (innermost_frame)
+ fci->frame = read_register (GR1_REGNUM);
+ else
+ fci->frame = fci->next_frame + fci->next->rsize;
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+ This wont work;
+#else
+ if (PC_IN_CALL_DUMMY (p, 0, 0))
+#endif
+ {
+ fci->rsize = DUMMY_FRAME_RSIZE;
+ /* This doesn't matter since we never try to get locals or args
+ from a dummy frame. */
+ fci->msize = 0;
+ /* Dummy frames always use a memory frame pointer. */
+ fci->saved_msp =
+ read_register_stack_integer (fci->frame + DUMMY_FRAME_RSIZE - 4, 4);
+ return;
+ }
+
+ func = find_pc_function (p);
+ if (func != NULL)
+ p = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
+ else
+ {
+ /* Search backward to find the trace-back tag. However,
+ do not trace back beyond the start of the text segment
+ (just as a sanity check to avoid going into never-never land). */
+ while (p >= text_start
+ && ((insn = read_memory_integer (p, 4)) & 0xff000000) != 0)
+ p -= 4;
+
+ if (p < text_start)
+ {
+ /* Couldn't find the trace-back tag.
+ Something strange is going on. */
+ fci->saved_msp = 0;
+ fci->rsize = 0;
+ fci->msize = 0;
+ return;
+ }
+ else
+ /* Advance to the first word of the function, i.e. the word
+ after the trace-back tag. */
+ p += 4;
+ }
+ /* We've found the start of the function. Since High C interchanges
+ the meanings of bits 23 and 22 (as of Jul 90), and we
+ need to look at the prologue anyway to figure out
+ what rsize is, ignore the contents of the trace-back tag. */
+ examine_prologue (p, &rsize, &msize, &mfp_used);
+ fci->rsize = rsize;
+ fci->msize = msize;
+ if (innermost_frame)
+ {
+ fci->saved_msp = read_register (MSP_REGNUM) + msize;
+ }
+ else
+ {
+ if (mfp_used)
+ fci->saved_msp =
+ read_register_stack_integer (fci->frame + rsize - 1, 4);
+ else
+ fci->saved_msp = fci->next->saved_msp + msize;
+ }
+}
+
+void
+init_extra_frame_info (fci)
+ struct frame_info *fci;
+{
+ if (fci->next == 0)
+ /* Assume innermost frame. May produce strange results for "info frame"
+ but there isn't any way to tell the difference. */
+ init_frame_info (1, fci);
+ else
+ /* We're in get_prev_frame_info.
+ Take care of everything in init_frame_pc. */
+ ;
+}
+
+void
+init_frame_pc (fromleaf, fci)
+ int fromleaf;
+ struct frame_info *fci;
+{
+ fci->pc = (fromleaf ? SAVED_PC_AFTER_CALL (fci->next) :
+ fci->next ? FRAME_SAVED_PC (fci->next) : read_pc ());
+ init_frame_info (0, fci);
+}
+\f
+/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
+ offsets being relative to the memory stack pointer (high C) or
+ saved_msp (gcc). */
+
+CORE_ADDR
+frame_locals_address (fi)
+ struct frame_info *fi;
+{
+ struct block *b = block_for_pc (fi->pc);
+ /* If compiled without -g, assume GCC. */
+ if (b == NULL || BLOCK_GCC_COMPILED (b))
+ return fi->saved_msp;
+ else
+ return fi->saved_msp - fi->msize;
+}
+\f
+/* Routines for reading the register stack. The caller gets to treat
+ the register stack as a uniform stack in memory, from address $gr1
+ straight through $rfb and beyond. */
+
+/* Analogous to read_memory except the length is understood to be 4.
+ Also, myaddr can be NULL (meaning don't bother to read), and
+ if actual_mem_addr is non-NULL, store there the address that it
+ was fetched from (or if from a register the offset within
+ registers). Set *LVAL to lval_memory or lval_register, depending
+ on where it came from. */
+void
+read_register_stack (memaddr, myaddr, actual_mem_addr, lval)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ CORE_ADDR *actual_mem_addr;
+ enum lval_type *lval;
+{
+ long rfb = read_register (RFB_REGNUM);
+ long rsp = read_register (RSP_REGNUM);
+ if (memaddr < rfb)
+ {
+ /* It's in a register. */
+ int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
+ if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127)
+ error ("Attempt to read register stack out of range.");
+ if (myaddr != NULL)
+ read_register_gen (regnum, myaddr);
+ if (lval != NULL)
+ *lval = lval_register;
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = REGISTER_BYTE (regnum);
+ }
+ else
+ {
+ /* It's in the memory portion of the register stack. */
+ if (myaddr != NULL)
+ read_memory (memaddr, myaddr, 4);
+ if (lval != NULL)
+ *lval = lval_memory;
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr == memaddr;
+ }
+}
+
+/* Analogous to read_memory_integer
+ except the length is understood to be 4. */
+long
+read_register_stack_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ long buf;
+ read_register_stack (memaddr, &buf, NULL, NULL);
+ SWAP_TARGET_AND_HOST (&buf, 4);
+ return buf;
+}
+
+/* Copy 4 bytes from GDB memory at MYADDR into inferior memory
+ at MEMADDR and put the actual address written into in
+ *ACTUAL_MEM_ADDR. */
+static void
+write_register_stack (memaddr, myaddr, actual_mem_addr)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ CORE_ADDR *actual_mem_addr;
+{
+ long rfb = read_register (RFB_REGNUM);
+ long rsp = read_register (RSP_REGNUM);
+ if (memaddr < rfb)
+ {
+ /* It's in a register. */
+ int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
+ if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127)
+ error ("Attempt to read register stack out of range.");
+ if (myaddr != NULL)
+ write_register (regnum, *(long *)myaddr);
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr = NULL;
+ }
+ else
+ {
+ /* It's in the memory portion of the register stack. */
+ if (myaddr != NULL)
+ write_memory (memaddr, myaddr, 4);
+ if (actual_mem_addr != NULL)
+ *actual_mem_addr == memaddr;
+ }
+}
+\f
+/* Find register number REGNUM relative to FRAME and put its
+ (raw) contents in *RAW_BUFFER. Set *OPTIMIZED if the variable
+ was optimized out (and thus can't be fetched). If the variable
+ was fetched from memory, set *ADDRP to where it was fetched from,
+ otherwise it was fetched from a register.
+
+ The argument RAW_BUFFER must point to aligned memory. */
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ FRAME frame;
+ int regnum;
+ enum lval_type *lvalp;
+{
+ struct frame_info *fi = get_frame_info (frame);
+ CORE_ADDR addr;
+ enum lval_type lval;
+
+ /* Once something has a register number, it doesn't get optimized out. */
+ if (optimized != NULL)
+ *optimized = 0;
+ if (regnum == RSP_REGNUM)
+ {
+ if (raw_buffer != NULL)
+ *(CORE_ADDR *)raw_buffer = fi->frame;
+ if (lvalp != NULL)
+ *lvalp = not_lval;
+ return;
+ }
+ else if (regnum == PC_REGNUM)
+ {
+ if (raw_buffer != NULL)
+ *(CORE_ADDR *)raw_buffer = fi->pc;
+
+ /* Not sure we have to do this. */
+ if (lvalp != NULL)
+ *lvalp = not_lval;
+
+ return;
+ }
+ else if (regnum == MSP_REGNUM)
+ {
+ if (raw_buffer != NULL)
+ {
+ if (fi->next != NULL)
+ *(CORE_ADDR *)raw_buffer = fi->next->saved_msp;
+ else
+ *(CORE_ADDR *)raw_buffer = read_register (MSP_REGNUM);
+ }
+ /* The value may have been computed, not fetched. */
+ if (lvalp != NULL)
+ *lvalp = not_lval;
+ return;
+ }
+ else if (regnum < LR0_REGNUM || regnum >= LR0_REGNUM + 128)
+ {
+ /* These registers are not saved over procedure calls,
+ so just print out the current values. */
+ if (raw_buffer != NULL)
+ *(CORE_ADDR *)raw_buffer = read_register (regnum);
+ if (lvalp != NULL)
+ *lvalp = lval_register;
+ if (addrp != NULL)
+ *addrp = REGISTER_BYTE (regnum);
+ return;
+ }
+
+ addr = fi->frame + (regnum - LR0_REGNUM) * 4;
+ if (raw_buffer != NULL)
+ read_register_stack (addr, raw_buffer, &addr, &lval);
+ if (lvalp != NULL)
+ *lvalp = lval;
+ if (addrp != NULL)
+ *addrp = addr;
+}
+\f
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+void
+pop_frame ()
+{
+ FRAME frame = get_current_frame ();
+ struct frame_info *fi = get_frame_info (frame);
+ CORE_ADDR rfb = read_register (RFB_REGNUM);
+ CORE_ADDR gr1 = fi->frame + fi->rsize;
+ CORE_ADDR lr1;
+ CORE_ADDR ret_addr;
+ int i;
+
+ /* If popping a dummy frame, need to restore registers. */
+ if (PC_IN_CALL_DUMMY (read_register (PC_REGNUM),
+ read_register (SP_REGNUM),
+ FRAME_FP (fi)))
+ {
+ for (i = 0; i < DUMMY_SAVE_SR128; ++i)
+ write_register
+ (SR_REGNUM (i + 128),
+ read_register (LR0_REGNUM + DUMMY_ARG / 4 + i));
+ for (i = 0; i < DUMMY_SAVE_GR96; ++i)
+ write_register
+ (GR96_REGNUM + i,
+ read_register (LR0_REGNUM + DUMMY_ARG / 4 + DUMMY_SAVE_SR128 + i));
+ }
+
+ /* Restore the memory stack pointer. */
+ write_register (MSP_REGNUM, fi->saved_msp);
+ /* Restore the register stack pointer. */
+ write_register (GR1_REGNUM, gr1);
+ /* Check whether we need to fill registers. */
+ lr1 = read_register (LR0_REGNUM + 1);
+ if (lr1 > rfb)
+ {
+ /* Fill. */
+ int num_bytes = lr1 - rfb;
+ int i;
+ long word;
+ write_register (RAB_REGNUM, read_register (RAB_REGNUM) + num_bytes);
+ write_register (RFB_REGNUM, lr1);
+ for (i = 0; i < num_bytes; i += 4)
+ {
+ /* Note: word is in host byte order. */
+ word = read_memory_integer (rfb + i, 4);
+ write_register (LR0_REGNUM + ((rfb - gr1) % 0x80) + i / 4, word);
+ }
+ }
+ ret_addr = read_register (LR0_REGNUM);
+ write_register (PC_REGNUM, ret_addr);
+ write_register (NPC_REGNUM, ret_addr + 4);
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (0, read_pc()));
+}
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+void
+push_dummy_frame ()
+{
+ long w;
+ CORE_ADDR rab, gr1;
+ CORE_ADDR msp = read_register (MSP_REGNUM);
+ int i;
+
+ /* Save the PC. */
+ write_register (LR0_REGNUM, read_register (PC_REGNUM));
+
+ /* Allocate the new frame. */
+ gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE;
+ write_register (GR1_REGNUM, gr1);
+
+ rab = read_register (RAB_REGNUM);
+ if (gr1 < rab)
+ {
+ /* We need to spill registers. */
+ int num_bytes = rab - gr1;
+ CORE_ADDR rfb = read_register (RFB_REGNUM);
+ int i;
+ long word;
+
+ write_register (RFB_REGNUM, rfb - num_bytes);
+ write_register (RAB_REGNUM, gr1);
+ for (i = 0; i < num_bytes; i += 4)
+ {
+ /* Note: word is in target byte order. */
+ read_register_gen (LR0_REGNUM + i / 4, &word, 4);
+ write_memory (rfb - num_bytes + i, &word, 4);
+ }
+ }
+
+ /* There are no arguments in to the dummy frame, so we don't need
+ more than rsize plus the return address and lr1. */
+ write_register (LR0_REGNUM + 1, gr1 + DUMMY_FRAME_RSIZE + 2 * 4);
+
+ /* Set the memory frame pointer. */
+ write_register (LR0_REGNUM + DUMMY_FRAME_RSIZE / 4 - 1, msp);
+
+ /* Allocate arg_slop. */
+ write_register (MSP_REGNUM, msp - 16 * 4);
+
+ /* Save registers. */
+ for (i = 0; i < DUMMY_SAVE_SR128; ++i)
+ write_register (LR0_REGNUM + DUMMY_ARG / 4 + i,
+ read_register (SR_REGNUM (i + 128)));
+ for (i = 0; i < DUMMY_SAVE_GR96; ++i)
+ write_register (LR0_REGNUM + DUMMY_ARG / 4 + DUMMY_SAVE_SR128 + i,
+ read_register (GR96_REGNUM + i));
+}
--- /dev/null
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the GNU C Library; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macros
+ PTR - Generic pointer type
+ LONG_DOUBLE - `long double' type
+ CONST - `const' keyword
+ VOLATILE - `volatile' keyword
+ SIGNED - `signed' keyword
+ PTRCONST - Generic const pointer (void *const)
+
+ EXFUN(name, prototype) - declare external function NAME
+ with prototype PROTOTYPE
+ DEFUN(name, arglist, args) - define function NAME with
+ args ARGLIST of types in ARGS
+ DEFUN_VOID(name) - define function NAME with no args
+ AND - argument separator for ARGS
+ NOARGS - null arglist
+ DOTS - `...' in args
+
+ For example:
+ extern int EXFUN(printf, (CONST char *format DOTS));
+ int DEFUN(fprintf, (stream, format),
+ FILE *stream AND CONST char *format DOTS) { ... }
+ void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef _ANSIDECL_H
+
+#define _ANSIDECL_H 1
+
+
+/* Every source file includes this file,
+ so they will all get the switch for lint. */
+/* LINTLIBRARY */
+
+
+#ifdef __STDC__
+
+#define PTR void *
+#define PTRCONST void *CONST
+#define LONG_DOUBLE long double
+
+#define AND ,
+#define NOARGS void
+#define CONST const
+#define VOLATILE volatile
+#define SIGNED signed
+#define DOTS , ...
+
+#define EXFUN(name, proto) name proto
+#define DEFUN(name, arglist, args) name(args)
+#define DEFUN_VOID(name) name(NOARGS)
+
+#else /* Not ANSI C. */
+
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define AND ;
+#define NOARGS
+#define CONST
+#define VOLATILE
+#define SIGNED
+#define DOTS
+
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+
+#endif /* ANSI C. */
+
+
+#endif /* ansidecl.h */
--- /dev/null
+ .text
+ .global _convert_from_extended
+
+_convert_from_extended:
+
+ ldfe f0,[a1]
+ stfd f0,[a2]
+ movs pc,lr
+
+ .global _convert_to_extended
+
+_convert_to_extended:
+
+ ldfd f0,[a1]
+ stfe f0,[a2]
+ movs pc,lr
--- /dev/null
+/* Print ARM instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "arm-opcode.h"
+
+extern char *reg_names[];
+
+static char *shift_names[] = {
+ "lsl", "lsr", "asr", "ror",
+};
+
+static char *cond_names[] = {
+ "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "", "nv"
+};
+
+static char float_precision[] = "sdep";
+static char float_rounding[] = " pmz";
+static float float_immed[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 0.5, 10.0 };
+
+static void print_ldr_str_offset();
+static void print_ldc_stc_offset();
+static long immediate_value();
+\f
+/* Print the ARM instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned long ins;
+ register struct opcode *op;
+ register char *p;
+ register int i, c;
+ int s, e, val;
+
+ ins = read_memory_integer(memaddr, 4);
+ for (i = 0, op = opcodes; i < N_OPCODES; i++, op++)
+ if ((ins & op->mask) == op->value) break;
+ assert(i != N_OPCODES);
+
+ for (p = op->assembler; *p;) {
+ c = *p++;
+ if (c == '%') {
+ s = e = 0;
+ while (isdigit(*p))
+ s = s*10 + (*p++ - '0');
+ if (*p == '-') {
+ p++;
+ while (isdigit(*p))
+ e = e*10 + (*p++ - '0');
+ } else
+ e = s;
+ assert(s >= 0 && s <= 31 && e >= 0 && e <= 31);
+ val = (ins >> s) & ((1 << (e + 1 - s)) - 1);
+ switch (*p++) {
+ case '%' :
+ putc('%', stream);
+ break;
+ case 'd' :
+ fprintf(stream, "%d", val);
+ break;
+ case 'x' :
+ fprintf(stream, "%x", val);
+ break;
+ case 'r' :
+ assert(val >= 0 && val <= 15);
+ fprintf(stream, "%s", reg_names[val]);
+ break;
+ case 'c' :
+ fprintf(stream, "%s", cond_names[ins >> 28]);
+ break;
+ case '\'' :
+ assert(*p);
+ c = *p++;
+ if (val)
+ putc(c, stream);
+ break;
+ case '`' :
+ assert(*p);
+ c = *p++;
+ if (!val)
+ putc(c, stream);
+ break;
+ case '?' :
+ assert(*p);
+ c = *p++;
+ assert(*p);
+ if (val)
+ p++;
+ else
+ c = *p++;
+ putc(c, stream);
+ break;
+ case 'p' :
+ if (((ins >> 12) & 0xf) == 0xf)
+ putc('p', stream);
+ break;
+ case 'o' :
+ if (ins & (1<<25)) {
+ int immed = immediate_value(ins & 0xfff);
+ fprintf (stream, "#%d (0x%x)", immed, immed);
+ } else {
+ int operand2 = ins & 0xfff;
+ /* in operand2 :
+ bits 0-3 are the base register
+ bits 5-6 are the shift (0=lsl, 1=lsr, 2=asr, 3=ror)
+ if bit 4 is zero then bits 7-11 are an immediate shift count
+ else bit 7 must be zero and bits 8-11 are the register
+ to be used as a shift count.
+ Note: no shift at all is encoded as "reg lsl #0" */
+ fprintf (stream, "%s", reg_names[operand2 & 0xf]);
+ if (operand2 & 0xff0) {
+ /* ror #0 is really rrx (rotate right extend) */
+ if ((operand2 & 0xff0) == 0x060)
+ fprintf (stream, ", rrx");
+ else {
+ fprintf (stream, ", %s ",
+ shift_names[(operand2 >> 5) & 3]);
+ if (operand2 & (1<<4)) /* register shift */
+ fprintf (stream, "%s",
+ reg_names[operand2 >> 8]);
+ else /* immediate shift */
+ fprintf (stream, "#%d",
+ operand2 >> 7);
+ }
+ }
+ }
+ break;
+ case 'a' :
+ fprintf (stream, "[%s", reg_names[(ins >> 16) & 0xf]);
+ if (ins & (1<<24)) {
+ fprintf (stream, ", ");
+ print_ldr_str_offset (ins, stream);
+ putc (']', stream);
+ if (ins & (1<<21)) putc('!', stream);
+ /* If it is a pc relative load, then it is probably
+ a constant so print it */
+ if (((ins >> 16) & 0xf) == 15 &&
+ (ins & (1<<25)) == 0 &&
+ (ins & (1<<20))) {
+ int addr = memaddr + 8 +
+ (ins & 0xfff) * ((ins & (1<<23)) ? 1 : -1);
+ fprintf (stream, " (contents=");
+ print_address (read_memory_integer(addr, 4), stream);
+ fprintf (stream, ")");
+ }
+ } else {
+ fprintf (stream, "]," );
+ print_ldr_str_offset (ins, stream);
+ }
+ break;
+ case 'b' :
+ print_address (memaddr + 8 + (((int)ins << 8) >> 6), stream);
+ break;
+ case 'A' :
+ fprintf (stream, "[%s", reg_names[(ins >> 16) & 0xf]);
+ if (ins & (1<<24)) {
+ fprintf (stream, ", ");
+ print_ldc_stc_offset (ins, stream);
+ putc(']', stream);
+ if (ins & (1<<21))
+ putc('!', stream);
+ } else {
+ fprintf (stream, "], ");
+ print_ldc_stc_offset (ins, stream);
+ }
+ break;
+ case 'm' :
+ {
+ int regnum, first = 1;
+ putc('{', stream);
+ for (regnum = 0; regnum < 16; regnum++)
+ if (ins & (1<<regnum)) {
+ if (!first)
+ putc (',', stream);
+ first = 0;
+ fprintf (stream, "%s", reg_names[regnum]);
+ }
+ putc('}', stream);
+ }
+ break;
+ case 'P' :
+ val = ((ins >> 18) & 2) | ((ins >> 7) & 1);
+ putc(float_precision[val], stream);
+ break;
+ case 'Q' :
+ val = ((ins >> 21) & 2) | ((ins >> 15) & 1);
+ putc(float_precision[val], stream);
+ break;
+ case 'R' :
+ val = ((ins >> 5) & 3);
+ if (val) putc(float_rounding[val], stream);
+ break;
+ case 'f' :
+ assert(val >= 0 && val <= 15);
+ if (val > 7)
+ fprintf (stream, "#%3.1f", float_immed[val - 8]);
+ else
+ fprintf (stream, "f%d", val);
+ break;
+ default:
+ abort();
+ }
+ } else
+ putc(c, stream);
+ }
+ return 4;
+}
+
+static long
+immediate_value(operand)
+int operand;
+{
+ int val = operand & 0xff;
+ int shift = 2*(operand >> 8);
+ /* immediate value is (val ror shift) */
+ return (val >> shift) | (val << (32 - shift));
+}
+
+static void
+print_ldr_str_offset(ins, stream)
+unsigned long ins;
+FILE *stream;
+{
+ if ((ins & (1<<25)) == 0)
+ fprintf (stream, "#%d",
+ (ins & 0xfff) * ((ins & (1<<23)) ? 1 : -1));
+ else {
+ fprintf (stream, "%s%s", reg_names[ins & 0xf],
+ (ins & (1<<23)) ? "" : "-");
+ if (ins & 0xff0)
+ fprintf (stream, ", %s #%d",
+ shift_names[(ins >> 5) & 3],
+ (ins >> 7) & 0x1f);
+ }
+}
+
+static void
+print_ldc_stc_offset(ins, stream)
+unsigned long ins;
+FILE *stream;
+{
+ fprintf (stream, "#%d",
+ 4 * (ins & 0xff) * ((ins & (1<<23)) ? 1 : -1));
+}
--- /dev/null
+/* Acorn Risc Machine host machine support.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "arm-opcode.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#define N_TXTADDR(hdr) 0x8000
+#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
+
+#include "gdbcore.h"
+
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ register int regno;
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct user u;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (PT_READ_U, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+ registers_fetched ();
+
+ for (regno = 0; regno < 16; regno++)
+ {
+ regaddr = offset + regno * 4;
+ *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid, regaddr, 0);
+ if (regno == PC_REGNUM)
+ *(int *)&buf[0] = GET_PC_PART(*(int *)&buf[0]);
+ supply_register (regno, buf);
+ }
+ *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid, offset + PC*4);
+ supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */
+
+ /* read the floating point registers */
+ offset = (char *) &u.u_fp_regs - (char *)&u;
+ *(int *)buf = ptrace (PT_READ_U, inferior_pid, offset, 0);
+ supply_register (FPS_REGNUM, buf);
+ for (regno = 16; regno < 24; regno++) {
+ regaddr = offset + 4 + 12 * (regno - 16);
+ for (i = 0; i < 12; i += sizeof(int))
+ *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid, regaddr + i, 0);
+ supply_register (regno, buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct user u;
+ unsigned long value;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (PT_READ_U, inferior_pid, offset, 0) - KERNEL_U_ADDR;
+
+ if (regno >= 0) {
+ if (regno >= 16) return;
+ regaddr = offset + 4 * regno;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (PT_WRITE_U, inferior_pid, regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else for (regno = 0; regno < 15; regno++)
+ {
+ regaddr = offset + regno * 4;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (6, inferior_pid, regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+\f
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+/* Structure to describe the chain of shared libraries used
+ by the execfile.
+ e.g. prog shares Xt which shares X11 which shares c. */
+
+struct shared_library {
+ struct exec_header header;
+ char name[SHLIBLEN];
+ CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
+ long data_offset; /* offset of data section in file */
+ int chan; /* file descriptor for the file */
+ struct shared_library *shares; /* library this one shares */
+};
+static struct shared_library *shlib = 0;
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+static CORE_ADDR unshared_text_start;
+
+/* extended header from exec file (for shared library info) */
+
+static struct exec_header exec_header;
+\f
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset, fp_reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+
+ /* We are depending on exec_file_command having been called
+ previously to set exec_data_start. Since the executable
+ and the core file share the same text segment, the address
+ of the data segment will be the same in both. */
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+ fp_reg_offset = (char *) &u.u_fp_regs - (char *)&u;
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ if (regno < 16)
+ val = lseek (corechan, reg_offset + 4 * regno, 0);
+ else if (regno < 24)
+ val = lseek (corechan, fp_reg_offset + 4 + 12*(regno - 24), 0);
+ else if (regno == 24)
+ val = lseek (corechan, fp_reg_offset, 0);
+ else if (regno == 25)
+ val = lseek (corechan, reg_offset + 4 * PC, 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (reg_names[regno])
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+
+ if (regno == PC_REGNUM)
+ *(int *)buf = GET_PC_PART(*(int *)buf);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
--- /dev/null
+/* Library for reading command lines and decoding commands.
+ Copyright (C) 1986, 1989, 1990 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+extern char *getenv ();
+
+/* Add element named NAME to command list *LIST.
+ FUN should be the function to execute the command;
+ it will get a character string as argument, with leading
+ and trailing blanks already eliminated.
+
+ DOC is a documentation string for the command.
+ Its first line should be a complete sentence.
+ It should start with ? for a command that is an abbreviation
+ or with * for a command that most users don't need to know about. */
+
+struct cmd_list_element *
+add_cmd (name, class, fun, doc, list)
+ char *name;
+ enum command_class class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+ delete_cmd (name, list);
+ c->next = *list;
+ c->name = name;
+ c->class = class;
+ c->function = fun;
+ c->doc = doc;
+ c->prefixlist = 0;
+ c->prefixname = (char *)NULL;
+ c->allow_unknown = 0;
+ c->abbrev_flag = 0;
+ c->aux = 0;
+ c->type = not_set_cmd;
+ c->completer = make_symbol_completion_list;
+ c->var = 0;
+ c->var_type = var_boolean;
+ c->user_commands = 0;
+ *list = c;
+ return c;
+}
+
+/* Same as above, except that the abbrev_flag is set. */
+
+struct cmd_list_element *
+add_abbrev_cmd (name, class, fun, doc, list)
+ char *name;
+ enum command_class class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = add_cmd (name, class, fun, doc, list);
+
+ c->abbrev_flag = 1;
+ return c;
+}
+
+struct cmd_list_element *
+add_alias_cmd (name, oldname, class, abbrev_flag, list)
+ char *name;
+ char *oldname;
+ enum command_class class;
+ int abbrev_flag;
+ struct cmd_list_element **list;
+{
+ /* Must do this since lookup_cmd tries to side-effect its first arg */
+ char *copied_name;
+ register struct cmd_list_element *old;
+ register struct cmd_list_element *c;
+ copied_name = (char *) alloca (strlen (oldname) + 1);
+ strcpy (copied_name, oldname);
+ old = lookup_cmd (&copied_name, *list, "", 1, 1);
+
+ if (old == 0)
+ {
+ delete_cmd (name, list);
+ return 0;
+ }
+
+ c = add_cmd (name, class, old->function, old->doc, list);
+ c->prefixlist = old->prefixlist;
+ c->prefixname = old->prefixname;
+ c->allow_unknown = old->allow_unknown;
+ c->abbrev_flag = abbrev_flag;
+ c->aux = old->aux;
+ return c;
+}
+
+/* Like add_cmd but adds an element for a command prefix:
+ a name that should be followed by a subcommand to be looked up
+ in another command list. PREFIXLIST should be the address
+ of the variable containing that list. */
+
+struct cmd_list_element *
+add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+ allow_unknown, list)
+ char *name;
+ enum command_class class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ return c;
+}
+
+/* Like add_prefix_cmd butsets the abbrev_flag on the new command. */
+
+struct cmd_list_element *
+add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+ allow_unknown, list)
+ char *name;
+ enum command_class class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ c->abbrev_flag = 1;
+ return c;
+}
+
+void
+not_just_help_class_command (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+}
+
+/* Add element named NAME to command list LIST (the list for set
+ or some sublist thereof).
+ CLASS is as in add_cmd.
+ VAR_TYPE is the kind of thing we are setting.
+ VAR is address of the variable being controlled by this command.
+ DOC is the documentation string. */
+struct cmd_list_element *
+add_set_cmd (name, class, var_type, var, doc, list)
+ char *name;
+ enum command_class class;
+ var_types var_type;
+ char *var;
+ char *doc;
+ struct cmd_list_element **list;
+{
+ /* For set/show, we have to call do_setshow_command
+ differently than an ordinary function (take commandlist as
+ well as arg), so the function field isn't helpful. However,
+ function == NULL means that it's a help class, so set the function
+ to not_just_help_class_command. */
+ struct cmd_list_element *c
+ = add_cmd (name, class, not_just_help_class_command, doc, list);
+
+ c->type = set_cmd;
+ c->var_type = var_type;
+ c->var = var;
+ return c;
+}
+
+/* Where SETCMD has already been added, add the corresponding show
+ command to LIST and return a pointer to it. */
+struct cmd_list_element *
+add_show_from_set (setcmd, list)
+ struct cmd_list_element *setcmd;
+ struct cmd_list_element **list;
+{
+ struct cmd_list_element *showcmd =
+ (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+ bcopy (setcmd, showcmd, sizeof (struct cmd_list_element));
+ delete_cmd (showcmd->name, list);
+ showcmd->type = show_cmd;
+
+ /* Replace "set " at start of docstring with "show ". */
+ if (setcmd->doc[0] == 'S' && setcmd->doc[1] == 'e'
+ && setcmd->doc[2] == 't' && setcmd->doc[3] == ' ')
+ showcmd->doc = concat ("Show ", setcmd->doc + 4, "");
+ else
+ fprintf (stderr, "GDB internal error: Bad docstring for set command\n");
+
+ showcmd->next = *list;
+ *list = showcmd;
+ return showcmd;
+}
+
+/* Remove the command named NAME from the command list. */
+
+void
+delete_cmd (name, list)
+ char *name;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c;
+ struct cmd_list_element *p;
+
+ while (*list && !strcmp ((*list)->name, name))
+ {
+ p = (*list)->next;
+ free (*list);
+ *list = p;
+ }
+
+ if (*list)
+ for (c = *list; c->next;)
+ {
+ if (!strcmp (c->next->name, name))
+ {
+ p = c->next->next;
+ free (c->next);
+ c->next = p;
+ }
+ else
+ c = c->next;
+ }
+}
+
+void help_cmd (), help_list (), help_cmd_list ();
+
+/* This command really has to deal with two things:
+ * 1) I want documentation on *this string* (usually called by
+ * "help commandname").
+ * 2) I want documentation on *this list* (usually called by
+ * giving a command that requires subcommands. Also called by saying
+ * just "help".)
+ *
+ * I am going to split this into two seperate comamnds, help_cmd and
+ * help_list.
+ */
+
+void
+help_cmd (command, stream)
+ char *command;
+ FILE *stream;
+{
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
+
+ if (!command)
+ {
+ help_list (cmdlist, "", all_classes, stream);
+ return;
+ }
+
+ c = lookup_cmd (&command, cmdlist, "", 0, 0);
+
+ if (c == 0)
+ return;
+
+ /* There are three cases here.
+ If c->prefixlist is nonzero, we have a prefix command.
+ Print its documentation, then list its subcommands.
+
+ If c->function is nonzero, we really have a command.
+ Print its documentation and return.
+
+ If c->function is zero, we have a class name.
+ Print its documentation (as if it were a command)
+ and then set class to the number of this class
+ so that the commands in the class will be listed. */
+
+ fputs_filtered (c->doc, stream);
+ fputs_filtered ("\n", stream);
+
+ if (c->prefixlist == 0 && c->function != 0)
+ return;
+ fprintf_filtered (stream, "\n");
+
+ /* If this is a prefix command, print it's subcommands */
+ if (c->prefixlist)
+ help_list (*c->prefixlist, c->prefixname, all_commands, stream);
+
+ /* If this is a class name, print all of the commands in the class */
+ if (c->function == 0)
+ help_list (cmdlist, "", c->class, stream);
+}
+
+/*
+ * Get a specific kind of help on a command list.
+ *
+ * LIST is the list.
+ * CMDTYPE is the prefix to use in the title string.
+ * CLASS is the class with which to list the nodes of this list (see
+ * documentation for help_cmd_list below), As usual, ALL_COMMANDS for
+ * everything, ALL_CLASSES for just classes, and non-negative for only things
+ * in a specific class.
+ * and STREAM is the output stream on which to print things.
+ * If you call this routine with a class >= 0, it recurses.
+ */
+void
+help_list (list, cmdtype, class, stream)
+ struct cmd_list_element *list;
+ char *cmdtype;
+ enum command_class class;
+ FILE *stream;
+{
+ int len;
+ char *cmdtype1, *cmdtype2;
+
+ /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */
+ len = strlen (cmdtype);
+ cmdtype1 = (char *) alloca (len + 1);
+ cmdtype1[0] = 0;
+ cmdtype2 = (char *) alloca (len + 4);
+ cmdtype2[0] = 0;
+ if (len)
+ {
+ cmdtype1[0] = ' ';
+ strncpy (cmdtype1 + 1, cmdtype, len - 1);
+ cmdtype1[len] = 0;
+ strncpy (cmdtype2, cmdtype, len - 1);
+ strcpy (cmdtype2 + len - 1, " sub");
+ }
+
+ if (class == all_classes)
+ fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
+ else
+ fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
+
+ help_cmd_list (list, class, cmdtype, (int)class >= 0, stream);
+
+ if (class == all_classes)
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by a class name for a list of commands in that class.",
+ cmdtype1);
+
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by %scommand name for full documentation.\n\
+Command name abbreviations are allowed if unambiguous.\n",
+ cmdtype1, cmdtype2);
+}
+
+/* Print only the first line of STR on STREAM. */
+static void
+print_doc_line (stream, str)
+ FILE *stream;
+ char *str;
+{
+ static char *line_buffer = 0;
+ static int line_size;
+ register char *p;
+
+ if (!line_buffer)
+ {
+ line_size = 80;
+ line_buffer = (char *) xmalloc (line_size);
+ }
+
+ p = str;
+ while (*p && *p != '\n' && *p != '.' && *p != ',')
+ p++;
+ if (p - str > line_size - 1)
+ {
+ line_size = p - str + 1;
+ free (line_buffer);
+ line_buffer = (char *) xmalloc (line_size);
+ }
+ strncpy (line_buffer, str, p - str);
+ line_buffer[p - str] = '\0';
+ if (islower (line_buffer[0]))
+ line_buffer[0] = toupper (line_buffer[0]);
+ fputs_filtered (line_buffer, stream);
+}
+
+/*
+ * Implement a help command on command list LIST.
+ * RECURSE should be non-zero if this should be done recursively on
+ * all sublists of LIST.
+ * PREFIX is the prefix to print before each command name.
+ * STREAM is the stream upon which the output should be written.
+ * CLASS should be:
+ * A non-negative class number to list only commands in that
+ * class.
+ * ALL_COMMANDS to list all commands in list.
+ * ALL_CLASSES to list all classes in list.
+ *
+ * Note that RECURSE will be active on *all* sublists, not just the
+ * ones seclected by the criteria above (ie. the selection mechanism
+ * is at the low level, not the high-level).
+ */
+void
+help_cmd_list (list, class, prefix, recurse, stream)
+ struct cmd_list_element *list;
+ enum command_class class;
+ char *prefix;
+ int recurse;
+ FILE *stream;
+{
+ register struct cmd_list_element *c;
+
+ for (c = list; c; c = c->next)
+ {
+ if (c->abbrev_flag == 0 &&
+ (class == all_commands
+ || (class == all_classes && c->function == 0)
+ || (class == c->class && c->function != 0)))
+ {
+ fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+ print_doc_line (stream, c->doc);
+ fputs_filtered ("\n", stream);
+ }
+ if (recurse
+ && c->prefixlist != 0
+ && c->abbrev_flag == 0)
+ help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
+ }
+}
+\f
+/* This routine takes a line of TEXT and a CLIST in which to
+ start the lookup. When it returns it will have incremented the text
+ pointer past the section of text it matched, set *RESULT_LIST to
+ the list in which the last word was matched, and will return the
+ cmd list element which the text matches. It will return 0 if no
+ match at all was possible. It will return -1 if ambigous matches are
+ possible; in this case *RESULT_LIST will be set to the list in which
+ there are ambiguous choices (and text will be set to the ambiguous
+ text string).
+
+ It does no error reporting whatsoever; control will always return
+ to the superior routine.
+
+ In the case of an ambiguous return (-1), *RESULT_LIST will be set to
+ point at the prefix_command (ie. the best match) *or* (special
+ case) will be 0 if no prefix command was ever found. For example,
+ in the case of "info a", "info" matches without ambiguity, but "a"
+ could be "args" or "address", so *RESULT_LIST is set to
+ the cmd_list_element for "info". So in this case
+ result list should not be interpeted as a pointer to the beginning
+ of a list; it simply points to a specific command.
+
+ If RESULT_LIST is NULL, don't set *RESULT_LIST (but don't otherwise
+ affect the operation).
+
+ This routine does *not* modify the text pointed to by TEXT.
+
+ If IGNORE_HELP_CLASSES is nonzero, ignore any command list
+ elements which are actually help classes rather than commands (i.e.
+ the function field of the struct cmd_list_element is 0). */
+
+struct cmd_list_element *
+lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
+ char **text;
+ struct cmd_list_element *clist, **result_list;
+ int ignore_help_classes;
+{
+ char *p, *command;
+ int len, tmp, nfound;
+ struct cmd_list_element *found, *c;
+
+ while (**text == ' ' || **text == '\t')
+ (*text)++;
+
+ /* Treating underscores as part of command words is important
+ so that "set args_foo()" doesn't get interpreted as
+ "set args _foo()". */
+ for (p = *text;
+ *p && (isalnum(*p) || *p == '-' || *p == '_');
+ p++)
+ ;
+
+ /* If nothing but whitespace, return 0. */
+ if (p == *text)
+ return 0;
+
+ len = p - *text;
+
+ /* *text and p now bracket the first command word to lookup (and
+ it's length is len). We copy this into a local temporary,
+ converting to lower case as we go. */
+
+ command = (char *) alloca (len + 1);
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = (*text)[tmp];
+ command[tmp] = (x >= 'A' && x <= 'Z') ? x - 'A' + 'a' : x;
+ }
+ command[len] = '\0';
+
+ /* Look it up. */
+ found = 0;
+ nfound = 0;
+ for (c = clist; c; c = c->next)
+ if (!strncmp (command, c->name, len)
+ && (!ignore_help_classes || c->function))
+ {
+ found = c;
+ nfound++;
+ if (c->name[len] == '\0')
+ {
+ nfound = 1;
+ break;
+ }
+ }
+
+ /* If nothing matches, we have a simple failure. */
+ if (nfound == 0)
+ return 0;
+
+ if (nfound > 1)
+ {
+ if (result_list != NULL)
+ /* Will be modified in calling routine
+ if we know what the prefix command is. */
+ *result_list = 0;
+ return (struct cmd_list_element *) -1; /* Ambiguous. */
+ }
+
+ /* We've matched something on this list. Move text pointer forward. */
+
+ *text = p;
+ if (found->prefixlist)
+ {
+ c = lookup_cmd_1 (text, *found->prefixlist, result_list,
+ ignore_help_classes);
+ if (!c)
+ {
+ /* Didn't find anything; this is as far as we got. */
+ if (result_list != NULL)
+ *result_list = clist;
+ return found;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* We've gotten this far properley, but the next step
+ is ambiguous. We need to set the result list to the best
+ we've found (if an inferior hasn't already set it). */
+ if (result_list != NULL)
+ if (!*result_list)
+ /* This used to say *result_list = *found->prefixlist
+ If that was correct, need to modify the documentation
+ at the top of this function to clarify what is supposed
+ to be going on. */
+ *result_list = found;
+ return c;
+ }
+ else
+ {
+ /* We matched! */
+ return c;
+ }
+ }
+ else
+ {
+ if (result_list != NULL)
+ *result_list = clist;
+ return found;
+ }
+}
+
+/* Look up the contents of *LINE as a command in the command list LIST.
+ LIST is a chain of struct cmd_list_element's.
+ If it is found, return the struct cmd_list_element for that command
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message.
+
+ If INGNORE_HELP_CLASSES is nonzero, ignore any command list
+ elements which are actually help classes rather than commands (i.e.
+ the function field of the struct cmd_list_element is 0). */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+ int ignore_help_classes;
+{
+ struct cmd_list_element *last_list = 0;
+ struct cmd_list_element *c =
+ lookup_cmd_1 (line, list, &last_list, ignore_help_classes);
+ char *ptr = (*line) + strlen (*line) - 1;
+
+ /* Clear off trailing whitespace. */
+ while (ptr >= *line && (*ptr == ' ' || *ptr == '\t'))
+ ptr--;
+ *(ptr + 1) = '\0';
+
+ if (!c)
+ {
+ if (!allow_unknown)
+ {
+ if (!*line)
+ error ("Lack of needed %scommand", cmdtype);
+ else
+ {
+ char *p = *line, *q;
+
+ while (isalnum(*p) || *p == '-')
+ p++;
+
+ q = (char *) alloca (p - *line + 1);
+ strncpy (q, *line, p - *line);
+ q[p-*line] = '\0';
+
+ error ("Undefined %scommand: \"%s\".", cmdtype, q);
+ }
+ }
+ else
+ return 0;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* Ambigous. Local values should be off prefixlist or called
+ values. */
+ int local_allow_unknown = (last_list ? last_list->allow_unknown :
+ allow_unknown);
+ char *local_cmdtype = last_list ? last_list->prefixname : cmdtype;
+ struct cmd_list_element *local_list =
+ (last_list ? *(last_list->prefixlist) : list);
+
+ if (local_allow_unknown < 0)
+ {
+ if (last_list)
+ return last_list; /* Found something. */
+ else
+ return 0; /* Found nothing. */
+ }
+ else
+ {
+ /* Report as error. */
+ int amb_len;
+ char ambbuf[100];
+
+ for (amb_len = 0;
+ ((*line)[amb_len] && (*line)[amb_len] != ' '
+ && (*line)[amb_len] != '\t');
+ amb_len++)
+ ;
+
+ ambbuf[0] = 0;
+ for (c = local_list; c; c = c->next)
+ if (!strncmp (*line, c->name, amb_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < (int)sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
+ *line, ambbuf);
+ return 0; /* lint */
+ }
+ }
+ else
+ {
+ /* We've got something. It may still not be what the caller
+ wants (if this command *needs* a subcommand). */
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ if (c->prefixlist && **line && !c->allow_unknown)
+ error ("Undefined %scommand: \"%s\".", c->prefixname, *line);
+
+ /* Seems to be what he wants. Return it. */
+ return c;
+ }
+ return 0;
+}
+
+#if 0
+/* Look up the contents of *LINE as a command in the command list LIST.
+ LIST is a chain of struct cmd_list_element's.
+ If it is found, return the struct cmd_list_element for that command
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message. */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+{
+ register char *p;
+ register struct cmd_list_element *c, *found;
+ int nfound;
+ char ambbuf[100];
+ char *processed_cmd;
+ int i, cmd_len;
+
+ /* Skip leading whitespace. */
+
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ /* Clear out trailing whitespace. */
+
+ p = *line + strlen (*line);
+ while (p != *line && (p[-1] == ' ' || p[-1] == '\t'))
+ p--;
+ *p = 0;
+
+ /* Find end of command name. */
+
+ p = *line;
+ while (*p == '-'
+ || (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z')
+ || (*p >= '0' && *p <= '9'))
+ p++;
+
+ /* Look up the command name.
+ If exact match, keep that.
+ Otherwise, take command abbreviated, if unique. Note that (in my
+ opinion) a null string does *not* indicate ambiguity; simply the
+ end of the argument. */
+
+ if (p == *line)
+ {
+ if (!allow_unknown)
+ error ("Lack of needed %scommand", cmdtype);
+ return 0;
+ }
+
+ /* Copy over to a local buffer, converting to lowercase on the way.
+ This is in case the command being parsed is a subcommand which
+ doesn't match anything, and that's ok. We want the original
+ untouched for the routine of the original command. */
+
+ processed_cmd = (char *) alloca (p - *line + 1);
+ for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
+ {
+ char x = (*line)[cmd_len];
+ if (x >= 'A' && x <= 'Z')
+ processed_cmd[cmd_len] = x - 'A' + 'a';
+ else
+ processed_cmd[cmd_len] = x;
+ }
+ processed_cmd[cmd_len] = '\0';
+
+ /* Check all possibilities in the current command list. */
+ found = 0;
+ nfound = 0;
+ for (c = list; c; c = c->next)
+ {
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ found = c;
+ nfound++;
+ if (c->name[cmd_len] == 0)
+ {
+ nfound = 1;
+ break;
+ }
+ }
+ }
+
+ /* Report error for undefined command name. */
+
+ if (nfound != 1)
+ {
+ if (nfound > 1 && allow_unknown >= 0)
+ {
+ ambbuf[0] = 0;
+ for (c = list; c; c = c->next)
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
+ processed_cmd, ambbuf);
+ }
+ else if (!allow_unknown)
+ error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
+ return 0;
+ }
+
+ /* Skip whitespace before the argument. */
+
+ while (*p == ' ' || *p == '\t') p++;
+ *line = p;
+
+ if (found->prefixlist && *p)
+ {
+ c = lookup_cmd (line, *found->prefixlist, found->prefixname,
+ found->allow_unknown);
+ if (c)
+ return c;
+ }
+
+ return found;
+}
+#endif
+
+/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
+
+/* Return a vector of char pointers which point to the different
+ possible completions in LIST of TEXT. */
+
+char **
+complete_on_cmdlist (list, text)
+ struct cmd_list_element *list;
+ char *text;
+{
+ struct cmd_list_element *ptr;
+ char **matchlist;
+ int sizeof_matchlist;
+ int matches;
+ int textlen = strlen (text);
+
+ sizeof_matchlist = 10;
+ matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
+ matches = 0;
+
+ for (ptr = list; ptr; ptr = ptr->next)
+ if (!strncmp (ptr->name, text, textlen)
+ && !ptr->abbrev_flag
+ && (ptr->function
+ || ptr->prefixlist))
+ {
+ if (matches == sizeof_matchlist)
+ {
+ sizeof_matchlist *= 2;
+ matchlist = (char **) xrealloc ((char *)matchlist,
+ (sizeof_matchlist
+ * sizeof (char *)));
+ }
+
+ matchlist[matches] = (char *)
+ xmalloc (strlen (ptr->name) + 1);
+ strcpy (matchlist[matches++], ptr->name);
+ }
+
+ if (matches == 0)
+ {
+ free (matchlist);
+ matchlist = 0;
+ }
+ else
+ {
+ matchlist = (char **) xrealloc ((char *)matchlist, ((matches + 1)
+ * sizeof (char *)));
+ matchlist[matches] = (char *) 0;
+ }
+
+ return matchlist;
+}
+
+static int
+parse_binary_operation (arg)
+ char *arg;
+{
+ int length;
+
+ if (!arg || !*arg)
+ return 1;
+
+ length = strlen (arg);
+
+ while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
+ length--;
+
+ if (!strncmp (arg, "on", length)
+ || !strncmp (arg, "1", length)
+ || !strncmp (arg, "yes", length))
+ return 1;
+ else
+ if (!strncmp (arg, "off", length)
+ || !strncmp (arg, "0", length)
+ || !strncmp (arg, "no", length))
+ return 0;
+ else
+ {
+ error ("\"on\" or \"off\" expected.");
+ return 0;
+ }
+}
+
+/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
+ of the argument, and FROM_TTY is nonzero if this command is being entered
+ directly by the user (i.e. these are just like any other
+ command). C is the command list element for the command. */
+void
+do_setshow_command (arg, from_tty, c)
+ char *arg;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (c->type == set_cmd)
+ {
+ switch (c->var_type)
+ {
+ case var_string:
+ {
+ char *new;
+ char *p;
+ char *q;
+ int ch;
+
+ if (arg == NULL)
+ arg = "";
+ new = (char *) xmalloc (strlen (arg) + 2);
+ p = arg; q = new;
+ while (ch = *p++)
+ {
+ if (ch == '\\')
+ {
+ /* \ at end of argument is used after spaces
+ so they won't be lost. */
+ if (*p == 0)
+ break;
+ ch = parse_escape (&p);
+ if (ch == 0)
+ break; /* C loses */
+ else if (ch > 0)
+ *q++ = ch;
+ }
+ else
+ *q++ = ch;
+ }
+ if (*(p - 1) != '\\')
+ *q++ = ' ';
+ *q++ = '\0';
+ new = (char *) xrealloc (new, q - new);
+ if (*(char **)c->var != NULL)
+ free (*(char **)c->var);
+ *(char **) c->var = new;
+ }
+ break;
+ case var_string_noescape:
+ if (arg == NULL)
+ arg = "";
+ if (*(char **)c->var != NULL)
+ free (*(char **)c->var);
+ *(char **) c->var = savestring (arg, strlen (arg));
+ break;
+ case var_filename:
+ if (arg == NULL)
+ error_no_arg ("filename to set it to.");
+ if (*(char **)c->var != NULL)
+ free (*(char **)c->var);
+ *(char **)c->var = tilde_expand (arg);
+ break;
+ case var_boolean:
+ *(int *) c->var = parse_binary_operation (arg);
+ break;
+ case var_uinteger:
+ if (arg == NULL)
+ error_no_arg ("integer to set it to.");
+ *(int *) c->var = parse_and_eval_address (arg);
+ if (*(int *) c->var == 0)
+ *(int *) c->var = UINT_MAX;
+ break;
+ case var_zinteger:
+ if (arg == NULL)
+ error_no_arg ("integer to set it to.");
+ *(int *) c->var = parse_and_eval_address (arg);
+ break;
+ default:
+ error ("gdb internal error: bad var_type in do_setshow_command");
+ }
+ }
+ else if (c->type == show_cmd)
+ {
+ /* Print doc minus "show" at start. */
+ print_doc_line (stdout, c->doc + 5);
+
+ fputs_filtered (" is ", stdout);
+ wrap_here (" ");
+ switch (c->var_type)
+ {
+ case var_string:
+ {
+ unsigned char *p;
+ fputs_filtered ("\"", stdout);
+ for (p = *(unsigned char **) c->var; *p != '\0'; p++)
+ printchar (*p, stdout, '"');
+ fputs_filtered ("\"", stdout);
+ }
+ break;
+ case var_string_noescape:
+ case var_filename:
+ fputs_filtered ("\"", stdout);
+ fputs_filtered (*(char **) c->var, stdout);
+ fputs_filtered ("\"", stdout);
+ break;
+ case var_boolean:
+ fputs_filtered (*(int *) c->var ? "on" : "off", stdout);
+ break;
+ case var_uinteger:
+ if (*(unsigned int *) c->var == UINT_MAX) {
+ fputs_filtered ("unlimited", stdout);
+ break;
+ }
+ /* else fall through */
+ case var_zinteger:
+ fprintf_filtered (stdout, "%d", *(unsigned int *) c->var);
+ break;
+ default:
+ error ("gdb internal error: bad var_type in do_setshow_command");
+ }
+ fputs_filtered (".\n", stdout);
+ }
+ else
+ error ("gdb internal error: bad cmd_type in do_setshow_command");
+ (*c->function) (NULL, from_tty, c);
+}
+
+/* Show all the settings in a list of show commands. */
+
+void
+cmd_show_list (list, from_tty, prefix)
+ struct cmd_list_element *list;
+ int from_tty;
+ char *prefix;
+{
+ for (; list != NULL; list = list->next) {
+ /* If we find a prefix, run its list, prefixing our output by its
+ prefix (with "show " skipped). */
+ if (list->prefixlist && !list->abbrev_flag)
+ cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
+ if (list->type == show_cmd)
+ {
+ fputs_filtered (prefix, stdout);
+ fputs_filtered (list->name, stdout);
+ fputs_filtered (": ", stdout);
+ do_setshow_command ((char *)NULL, from_tty, list);
+ }
+ }
+}
+
+static void
+shell_escape (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int rc, status, pid;
+ char *p, *user_shell;
+ extern char *rindex ();
+
+ if ((user_shell = (char *) getenv ("SHELL")) == NULL)
+ user_shell = "/bin/sh";
+
+ /* Get the name of the shell for arg0 */
+ if ((p = rindex (user_shell, '/')) == NULL)
+ p = user_shell;
+ else
+ p++; /* Get past '/' */
+
+ if ((pid = fork()) == 0)
+ {
+ if (!arg)
+ execl (user_shell, p, 0);
+ else
+ execl (user_shell, p, "-c", arg, 0);
+
+ fprintf (stderr, "Exec of shell failed\n");
+ exit (0);
+ }
+
+ if (pid != -1)
+ while ((rc = wait (&status)) != pid && rc != -1)
+ ;
+ else
+ error ("Fork failed");
+}
+
+static void
+make_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char *p;
+
+ if (arg == 0)
+ p = "make";
+ else
+ {
+ p = xmalloc (sizeof("make ") + strlen(arg));
+ strcpy (p, "make ");
+ strcpy (p + sizeof("make ")-1, arg);
+ }
+
+ shell_escape (p, from_tty);
+}
+
+void
+_initialize_command ()
+{
+ add_com ("shell", class_support, shell_escape,
+ "Execute the rest of the line as a shell command. \n\
+With no arguments, run an inferior shell.");
+
+ add_com ("make", class_support, make_command,
+ "Run the ``make'' program using the rest of the line as arguments.");
+}
--- /dev/null
+#!/bin/sh
+
+# Shell script to do machine-dependent things in
+# preparation for compiling gdb.
+#
+# Usage: config.gdb machine
+#
+# If config.gdb succeeds, it leaves its status in config.status.
+# If config.gdb fails after disturbing the status quo,
+# config.status is removed.
+
+progname=$0
+host=
+target=
+list_hosts=
+list_targets=
+srcdir=
+
+for arg in $*; do
+ case $arg in
+ -srcdir=*|+srcdir=*)
+ srcdir=`echo $arg | sed 's/[+-]srcdir=//'`
+ ;;
+ -host|+host)
+ list_hosts=true
+ ;;
+ -target|+target)
+ list_targets=true
+ ;;
+ -host=*|+host=*)
+ if [ "$host" = "" ]; then
+ host=`echo $arg | sed 's/[+-]host=//'`
+ else
+ echo Error: Attempt to specify host machine twice
+ bad=true
+ fi
+ ;;
+ -target=*|+target=*)
+ if [ "$target" = "" ]; then
+ target=`echo $arg | sed 's/[+-]target=//'`
+ else
+ echo Error: Attempt to specify target machine twice
+ bad=true
+ fi
+ ;;
+ *)
+ if [ "$host" = "" ]; then
+ host=$arg
+ else
+ if [ "$target" = "" ]; then
+ target=$arg
+ else
+ echo Error: More arguments than host and target machine names
+ bad=true
+ fi
+ fi
+ ;;
+ esac
+done
+
+if [ "$target" = "" ]; then target=$host; fi
+if [ "$host" = "" ]; then bad=true; fi
+
+# Find the source files, if location was not specified
+if [ "$srcdir" = "" ]; then
+ srcdirdefaulted=true
+ srcdir=.
+ if [ ! -r main.c ]; then
+ srcdir=..
+ fi
+fi
+if [ ! -r ${srcdir}/main.c ]; then
+ if [ "$srcdirdefaulted" != "true" ]; then
+ echo "$progname: Can't find debugger sources in \`${srcdir}'." 1>&2
+ else
+ echo "$progname: Can't find debugger sources in \`.' or \`..'." 1>&2
+ fi
+ exit 1
+fi
+
+if [ "$list_hosts" = "true" ]; then
+ cd $srcdir/xconfig
+ for i in * ; do
+# The {} in ${i} are required or else /bin/sh in sony newsos 3.2 removes
+# the quote after it.
+ awk <$i "NR == 1 { lastchar = substr(\"${i}\", length(\"${i}\"), 1)
+if (lastchar != \"~\" && lastchar != \"#\") \
+printf \"%-12s %s\n\", \"${i}\", substr(\$0,2) }"
+ done
+fi
+
+if [ "$list_targets" = "true" ]; then
+ cd $srcdir/tconfig
+ for i in * ; do
+ awk <$i "NR == 1 { lastchar = substr(\"${i}\", length(\"${i}\"), 1)
+if (lastchar != \"~\" && lastchar != \"#\") \
+printf \"%-12s %s\n\", \"${i}\", substr(\$0,2) }"
+ done
+fi
+
+if [ "$list_hosts" = "true" -o "$list_targets" = "true" ]; then
+ exit 0
+fi
+
+if [ "$host" != "" -a ! -f $srcdir/xconfig/$host ]; then
+ echo "No such host $host"
+ bad=true
+fi
+
+if [ "$target" != "" -a ! -f $srcdir/tconfig/$target ]; then
+ echo "No such target $target"
+ bad=true
+fi
+
+if [ "$bad" = "true" ] ; then
+ echo "Usage: "
+ echo " $progname [+srcdir=\`dir'] machine"
+ echo " For normal usage"
+ echo " $progname [+srcdir=\`dir'] \`host' \`target'"
+ echo " $progname [+srcdir=\`dir'] +host=\`host' +target=\`target'"
+ echo " If you are doing remote debugging between machines of two"
+ echo " different types (cross-debugging). \`host' is the type of"
+ echo " machine on which GDB will be running. \`target' is the"
+ echo " machine that the program you are debugging will be"
+ echo " running on."
+ echo " $progname +host"
+ echo " Print a list of valid host machine types."
+ echo " $progname +target"
+ echo " Print a list of valid target machine types."
+ echo
+ echo " +srcdir=\`dir' means that the sources are in \`dir'. For"
+ echo " example, \`cd /obj/hp300; config.gdb +srcdir=/src/gdb hp300'"
+ echo " If +srcdir is not specified, sources can either be in \`.'"
+ echo " or \`..'."
+ echo
+
+ if [ -r config.status ]
+ then
+ cat config.status
+ fi
+ exit 1
+fi
+
+rm -f tm.h xm.h
+
+cat $srcdir/xconfig/$host $srcdir/tconfig/$target | awk '$1 == "#msg" {
+ print substr($0,6)}'
+paramfile=${srcdir}/`awk '
+ $1 == "TM_FILE=" { print $2 }' <$srcdir/tconfig/$target`
+if [ "$paramfile" != "${srcdir}/" ] ; then
+ # Make a symlink if possible, otherwise try a hard link
+ ln -s $paramfile tm.h 2>/dev/null || ln $paramfile tm.h
+fi
+
+paramfile=${srcdir}/`awk '
+ $1 == "XM_FILE=" { print $2 }' <$srcdir/xconfig/$host`
+if [ "$paramfile" != "${srcdir}/" ] ; then
+ # Make a symlink if possible, otherwise try a hard link
+ ln -s $paramfile xm.h 2>/dev/null || ln $paramfile xm.h
+fi
+
+rm -f config.status
+
+case ${srcdir} in
+ .)
+ ;;
+ *)
+ echo "srcdir=${srcdir}" >./Makefile.srcdir
+ grep -s "source ${srcdir}/.gdbinit" .gdbinit 2>/dev/null || \
+ echo "source ${srcdir}/.gdbinit" >> .gdbinit
+ if [ ! -d readline ]; then
+ mkdir readline
+ # This could be a symlink, but getting the name right (because
+ # srcdir can be either relative or absolute) would be hairy.
+ cp ${srcdir}/readline/Makefile readline
+ fi
+esac
+
+make "srcdir=${srcdir}" \
+ "M_MAKEFILE=$srcdir/tconfig/$target $srcdir/xconfig/$host" \
+ -f $srcdir/Makefile.dist Makefile
+
+echo "GDB is now set up for host machine $host and target machine $target." \
+ | tee config.status
+exit 0
--- /dev/null
+GDB is now set up for host machine none and target machine none.
--- /dev/null
+# AT&T 3b1/Unix pc
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# I don't think cc has been tried. -traditional for <sys/ioctl.h>
+# (not sure whether necessary).
+CC= gcc -traditional
+# GCC runs out of virtual memory.
+PINSN_CC= cc
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-3b1.h
--- /dev/null
+# AT&T 3b1/Unix pc
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-3b1.h
--- /dev/null
+# Altos 3068 (68k, System V release 2)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o altos-xdep.o
+XM_FILE= xm-altos.h
+REGEX=regex.o
+REGEX1=regex.o
+SYSV_DEFINE=-DSYSV
--- /dev/null
+# Altos 3068 (68k, System V release 2)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-altos.h
--- /dev/null
+# Altos 3068 (68k, System V release 2), using COFF encapsulation
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the coff encapsulation features require the GNU binutils utilities
+#msg To be ahead of their System V counterparts in your path.
+
+XDEPFILES= infptrace.o altos-xdep.o
+XM_FILE= xm-altos.h
+REGEX=regex.o
+REGEX1=regex.o
+SYSV_DEFINE=-DSYSV
--- /dev/null
+# Altos 3068 (68k, System V release 2), using COFF encapsulation
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the coff encapsulation features require the GNU binutils utilities
+#msg To be ahead of their System V counterparts in your path.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-altosgas.h
--- /dev/null
+# AMD 29000 on EB29K board over a serial line.
+# Copyright (C) 1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o am29k-pinsn.o remote-eb.o am29k-tdep.o
+TM_FILE= tm-29k.h
+# The following is for ../include/a.out.encap.h
+TM_CFLAGS = -DCOFF_ENCAPSULATE -DTARGET=TARGET_AM29K
--- /dev/null
+# Acorn RISC machine running RISCiX (4.3bsd)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o arm-xdep.o arm-convert.o
+XM_FILE= xm-arm.h
--- /dev/null
+# Acorn RISC machine running RISCiX (4.3bsd)
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= arm-tdep.o arm-pinsn.o
+TM_FILE= tm-arm.h
--- /dev/null
+# Big-endian MIPS machine such as Sony News
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o mips-xdep.o coredep.o
+XM_FILE= xm-bigmips.h
--- /dev/null
+# Big-endian MIPS machine such as Sony News
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= mips-pinsn.o mips-tdep.o mipsread.o exec.o
+TM_FILE= tm-bigmips.h
--- /dev/null
+# Convex Unix (4bsd)
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= convex-xdep.o
+XM_FILE= xm-convex.h
--- /dev/null
+# Convex Unix (4bsd)
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= convex-tdep.o convex-pinsn.o
+TM_FILE= tm-convex.h
--- /dev/null
+# Hewlett-Packard 9000 series 300, running BSD
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-hp300bsd.h
--- /dev/null
+# Hewlett-Packard 9000 series 300, running BSD
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-hp300bsd.h
--- /dev/null
+# Hewlett-Packard 9000 series 300, running HPUX
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The following is true because gcc uses a different .o file format
+# than the native HPUX compiler
+#msg If you compile GDB with GCC on HPUX, you must make sure
+#msg that the `nm' used in `munch' is GNU nm
+#msg
+
+# The headers in the directory hp-include override system headers
+# and tell GDB to use BSD executable file format (hence -Ihp-include)
+XDEPFILES= infptrace.o hp300hpux-xdep.o
+XM_FILE= xm-hp300hpux.h
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
+ALLOCA=alloca.o
--- /dev/null
+# Hewlett-Packard 9000 series 300, running HPUX
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Note that GDB only can read symbols from programs that were
+#msg compiled with GCC
+#msg
+
+# The headers in the directory hp-include override system headers
+# and tell GDB to use BSD executable file format (hence -Ihp-include)
+TM_CFLAGS=-Ihp-include
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-hp300hpux.h
--- /dev/null
+# Intel 386 running System V, using COFF encapsulation
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
--- /dev/null
+# Intel 386 running System V, using COFF encapsulation
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the COFF encapsulation features requires the GNU binary utilities
+#msg to be ahead of their System V counterparts in your path.
+#msg
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v-g.h
--- /dev/null
+# Intel 386 running System V
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
--- /dev/null
+# Intel 386 running System V
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v.h
--- /dev/null
+# Intel 386 running System V release 2, using COFF encapsulation
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v32.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
--- /dev/null
+# Intel 386 running System V release 2, using COFF encapsulation
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Use of the COFF encapsulation features requires the GNU binary utilities
+#msg to be ahead of their System V counterparts in your path.
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v-g.h
--- /dev/null
+# Intel 386 running System V release 2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o i386-xdep.o
+XM_FILE= xm-i386v32.h
+XM_CLIBS= -lPW
+SYSV_DEFINE=-DSYSV
+REGEX=regex.o
+REGEX1=regex.o
--- /dev/null
+# Intel 386 running System V release 2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i386-tdep.o i386-pinsn.o
+TM_FILE= tm-i386v.h
--- /dev/null
+# Intel 80960, under NINDY or under VxWorks, selected at runtime.
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg
+#msg You must specify either "nindy960" or "vxworks960"; there is no
+#msg generic i960 target any more.
+#msg
--- /dev/null
+# ISI Optimum V (3.05) under 4.3bsd.
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-isi.h
--- /dev/null
+# ISI Optimum V (3.05) under 4.3bsd.
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o
+TM_FILE= tm-isi.h
--- /dev/null
+# Little-endian MIPS machine such as DECstation.
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o mips-xdep.o coredep.o
+XM_FILE= xm-mips.h
--- /dev/null
+# Little-endian MIPS machine such as DECstation.
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= mips-pinsn.o mips-tdep.o mipsread.o exec.o
+TM_FILE= tm-mips.h
--- /dev/null
+# Motorola 88000 running DGUX
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES=
+XM_FILE= xm-88k.h
--- /dev/null
+# Motorola 88000 running DGUX
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= tdesc.o
+TM_CLIBS= tdesc/libdc.o
+TM_CDEPS= tdesc/libdc.o
+TM_FILE= tm-88k.h
--- /dev/null
+# Merlin running utek 2.1
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-merlin.h
+# See SHELL_FILE in m-merlin.h for a explanation of this.
+M_INSTALL=cp /bin/sh /usr/local/lib/gdb-sh; \
+chmod ogu+rw /usr/local/lib/gdb-sh
--- /dev/null
+# Merlin running utek 2.1
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o ns32k-pinsn.o
+TM_FILE= tm-merlin.h
--- /dev/null
+# DEC VAX running BSD or Ultrix
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The following types of /bin/cc failures have been observed:
+# 1. Something in readline.c which I have never seen
+# 2. ``"values.c", line 816: compiler error: schain botch''
+#msg /bin/cc has been known to fail on VAXen running BSD4.3
+#msg If this occurs, use gcc
+#msg (but see comments in Makefile.dist about compiling with gcc).
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-vax.h
--- /dev/null
+# Sony news series 700/800/900 (68020) running NewsOS version 3.
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o news-xdep.o
+XM_FILE= xm-news.h
--- /dev/null
+# Sony news series 700/800/900 (68020) running NewsOS version 3.
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-news.h
--- /dev/null
+# Sony news series 1000 (68030) running NewsOS version 3.
+# Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o news-xdep.o
+XM_FILE= xm-news1000.h
--- /dev/null
+# Sony news series 1000 (68030) running NewsOS version 3.
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= m68k-pinsn.o exec.o
+TM_FILE= tm-news.h
--- /dev/null
+# Intel 80960, in an embedded system under the NINDY monitor
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i960-pinsn.o i960-tdep.o nindy-tdep.o remote-nindy.o nindy.o Onindy.o ttybreak.o ttyflush.o
+TM_FILE= tm-nindy960.h
+TM_CFLAGS=
--- /dev/null
+# Target config file for "no target". This can be used to build you
+# a Makefile that only runs administrative commands like 'clean',
+# 'gdb.tar.Z', etc.
+#
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
--- /dev/null
+# "no target".
+# This can be used to build you a Makefile that only runs administrative
+# commands like 'clean', 'gdb.tar.Z', etc.
--- /dev/null
+# Gould NP1
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o gould-xdep.o
+XM_FILE= xm-np1.h
--- /dev/null
+# Gould NP1
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o gould-pinsn.o
+TM_FILE= tm-np1.h
--- /dev/null
+# Gould Powernode
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o coredep.o
+XM_FILE= xm-pn.h
--- /dev/null
+# Gould Powernode
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o gould-pinsn.o
+TM_FILE= tm-pn.h
--- /dev/null
+# Pyramidax under OSx 4.0 (4.2bsd).
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg If you don't compile GDB with GCC, you'll need to add
+#msg ALLOCA=alloca.o and ALLOCA1=alloca.o to the Makefile.
+#msg
+
+XDEPFILES= pyr-xdep.o infptrace.o
+XM_FILE= xm-pyr.h
--- /dev/null
+# Pyramid under OSx 4.0 (4.2bsd).
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#msg Note that GDB on Pyramids only works with GCC,
+#msg at least for some programs.
+#msg
+
+TDEPFILES= pyr-pinsn.o pyr-tdep.o exec.o
+TM_FILE= tm-pyr.h
--- /dev/null
+# Sun 2, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun2.h
--- /dev/null
+# Sun 2, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o m68k-pinsn.o m68k-tdep.o
+TM_FILE= tm-sun2.h
--- /dev/null
+# Sun 2, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun2.h
--- /dev/null
+# Sun 2, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o m68k-pinsn.o solib.o m68k-tdep.o
+TM_FILE= tm-sun2os4.h
--- /dev/null
+# Sun 3, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun3os4.h
--- /dev/null
+# Sun 3, running SunOS 4, as a target system
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o solib.o m68k-tdep.o
+TM_FILE= tm-sun3os4.h
--- /dev/null
+# Sun 386i
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun386-xdep.o
+XM_FILE= xm-sun386.h
--- /dev/null
+# Sun 386i target configuration file.
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i386-pinsn.o solib.o
+TM_FILE= tm-sun386.h
--- /dev/null
+# Sun 3, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun3.h
--- /dev/null
+# Sun 3, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o m68k-pinsn.o m68k-tdep.o
+TM_FILE= tm-sun3.h
--- /dev/null
+# Sun 3, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+XDEPFILES= infptrace.o sun3-xdep.o
+XM_FILE= xm-sun3os4.h
--- /dev/null
+# Sun 3, running SunOS 4, as a target system
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o solib.o m68k-tdep.o
+TM_FILE= tm-sun3os4.h
--- /dev/null
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sparc-xdep.o
+XM_FILE= xm-sun4os4.h
--- /dev/null
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o sparc-tdep.o sparc-pinsn.o solib.o
+TM_FILE= tm-sun4os4.h
--- /dev/null
+# Sun 4 or Sparcstation, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sparc-xdep.o
+XM_FILE= xm-sparc.h
--- /dev/null
+# Sun 4 or Sparcstation, running SunOS 3
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o sparc-tdep.o sparc-pinsn.o
+TM_FILE= tm-sparc.h
--- /dev/null
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o sparc-xdep.o
+XM_FILE= xm-sun4os4.h
--- /dev/null
+# Sun 4 or Sparcstation, running SunOS 4
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The system-supplied assembler re-orders the symbols so that gdb
+# can't find "gcc_compiled.".
+#msg If you compile your program with GCC, use the GNU assembler.
+#msg
+
+TDEPFILES= exec.o sparc-tdep.o sparc-pinsn.o solib.o
+TM_FILE= tm-sun4os4.h
--- /dev/null
+# Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o symmetry-xdep.o
+XM_FILE= xm-symmetry.h
--- /dev/null
+# Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= symmetry-tdep.o i386-pinsn.o
+TM_FILE= tm-symmetry.h
--- /dev/null
+# Encore running umax 4.2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+XDEPFILES= infptrace.o umax-xdep.o
+XM_FILE= xm-umax.h
--- /dev/null
+# Encore running umax 4.2
+# Copyright (C) 1990 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o ns32k-pinsn.o
+TM_FILE= tm-umax.h
--- /dev/null
+# DEC VAX running BSD or Ultrix
+# Copyright (C) 1989-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= vax-pinsn.o exec.o
+TM_FILE= tm-vax.h
--- /dev/null
+# VxWorks running on a 68000, as a target system
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o m68k-pinsn.o m68k-tdep.o remote-vx.o xdr_ld.o xdr_ptrace.o xdr_rdb.o xdr_regs.o
+TM_FILE= tm-vxworks68.h
--- /dev/null
+# VxWorks running on an Intel 960, as a target system
+# Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+TDEPFILES= exec.o i960-pinsn.o i960-tdep.o remote-vx.o xdr_ld.o xdr_ptrace.o xdr_rdb.o xdr_regs.o
+TM_FILE= tm-vxworks960.h
+# Define this for the vx-share routines, which don't see param.h.
+TM_CFLAGS= -DI80960
--- /dev/null
+/* Include information for instruction dissasembly on the Convex.
+ Copyright (C) 1989, Free Software Foundation.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define xxx 0
+#define rrr 1
+#define rr 2
+#define rxr 3
+#define r 4
+#define nops 5
+#define nr 6
+#define pcrel 7
+#define lr 8
+#define rxl 9
+#define rlr 10
+#define rrl 11
+#define iml 12
+#define imr 13
+#define a1r 14
+#define a1l 15
+#define a2r 16
+#define a2l 17
+#define a3 18
+#define a4 19
+#define a5 20
+#define V 1
+#define S 2
+#define VM 3
+#define A 4
+#define VL 5
+#define VS 6
+#define VLS 7
+#define PSW 8
+/* Prevent an error during "make depend". */
+#if !defined (PC)
+#define PC 9
+#endif
+#define ITR 10
+#define VV 11
+#define ITSR 12
+#define TOC 13
+#define CIR 14
+#define TTR 15
+#define VMU 16
+#define VML 17
+#define ICR 18
+#define TCPU 19
+#define CPUID 20
+#define TID 21
+char *op[] = {
+ "",
+ "v0\0v1\0v2\0v3\0v4\0v5\0v6\0v7",
+ "s0\0s1\0s2\0s3\0s4\0s5\0s6\0s7",
+ "vm",
+ "sp\0a1\0a2\0a3\0a4\0a5\0ap\0fp",
+ "vl",
+ "vs",
+ "vls",
+ "psw",
+ "pc",
+ "itr",
+ "vv",
+ "itsr",
+ "toc",
+ "cir",
+ "ttr",
+ "vmu",
+ "vml",
+ "icr",
+ "tcpu",
+ "cpuid",
+ "tid",
+};
+struct formstr format0[] = {
+ {0,0,rrr,V,S,S}, /* mov */
+ {0,0,rrr,S,S,V}, /* mov */
+ {1,1,rrr,V,V,V}, /* merg.t */
+ {2,1,rrr,V,V,V}, /* mask.t */
+ {1,2,rrr,V,S,V}, /* merg.f */
+ {2,2,rrr,V,S,V}, /* mask.f */
+ {1,1,rrr,V,S,V}, /* merg.t */
+ {2,1,rrr,V,S,V}, /* mask.t */
+ {3,3,rrr,V,V,V}, /* mul.s */
+ {3,4,rrr,V,V,V}, /* mul.d */
+ {4,3,rrr,V,V,V}, /* div.s */
+ {4,4,rrr,V,V,V}, /* div.d */
+ {3,3,rrr,V,S,V}, /* mul.s */
+ {3,4,rrr,V,S,V}, /* mul.d */
+ {4,3,rrr,V,S,V}, /* div.s */
+ {4,4,rrr,V,S,V}, /* div.d */
+ {5,0,rrr,V,V,V}, /* and */
+ {6,0,rrr,V,V,V}, /* or */
+ {7,0,rrr,V,V,V}, /* xor */
+ {8,0,rrr,V,V,V}, /* shf */
+ {5,0,rrr,V,S,V}, /* and */
+ {6,0,rrr,V,S,V}, /* or */
+ {7,0,rrr,V,S,V}, /* xor */
+ {8,0,rrr,V,S,V}, /* shf */
+ {9,3,rrr,V,V,V}, /* add.s */
+ {9,4,rrr,V,V,V}, /* add.d */
+ {10,3,rrr,V,V,V}, /* sub.s */
+ {10,4,rrr,V,V,V}, /* sub.d */
+ {9,3,rrr,V,S,V}, /* add.s */
+ {9,4,rrr,V,S,V}, /* add.d */
+ {10,3,rrr,V,S,V}, /* sub.s */
+ {10,4,rrr,V,S,V}, /* sub.d */
+ {9,5,rrr,V,V,V}, /* add.b */
+ {9,6,rrr,V,V,V}, /* add.h */
+ {9,7,rrr,V,V,V}, /* add.w */
+ {9,8,rrr,V,V,V}, /* add.l */
+ {9,5,rrr,V,S,V}, /* add.b */
+ {9,6,rrr,V,S,V}, /* add.h */
+ {9,7,rrr,V,S,V}, /* add.w */
+ {9,8,rrr,V,S,V}, /* add.l */
+ {10,5,rrr,V,V,V}, /* sub.b */
+ {10,6,rrr,V,V,V}, /* sub.h */
+ {10,7,rrr,V,V,V}, /* sub.w */
+ {10,8,rrr,V,V,V}, /* sub.l */
+ {10,5,rrr,V,S,V}, /* sub.b */
+ {10,6,rrr,V,S,V}, /* sub.h */
+ {10,7,rrr,V,S,V}, /* sub.w */
+ {10,8,rrr,V,S,V}, /* sub.l */
+ {3,5,rrr,V,V,V}, /* mul.b */
+ {3,6,rrr,V,V,V}, /* mul.h */
+ {3,7,rrr,V,V,V}, /* mul.w */
+ {3,8,rrr,V,V,V}, /* mul.l */
+ {3,5,rrr,V,S,V}, /* mul.b */
+ {3,6,rrr,V,S,V}, /* mul.h */
+ {3,7,rrr,V,S,V}, /* mul.w */
+ {3,8,rrr,V,S,V}, /* mul.l */
+ {4,5,rrr,V,V,V}, /* div.b */
+ {4,6,rrr,V,V,V}, /* div.h */
+ {4,7,rrr,V,V,V}, /* div.w */
+ {4,8,rrr,V,V,V}, /* div.l */
+ {4,5,rrr,V,S,V}, /* div.b */
+ {4,6,rrr,V,S,V}, /* div.h */
+ {4,7,rrr,V,S,V}, /* div.w */
+ {4,8,rrr,V,S,V}, /* div.l */
+};
+struct formstr format1[] = {
+ {11,0,xxx,0,0,0}, /* exit */
+ {12,0,a3,0,0,0}, /* jmp */
+ {13,2,a3,0,0,0}, /* jmpi.f */
+ {13,1,a3,0,0,0}, /* jmpi.t */
+ {14,2,a3,0,0,0}, /* jmpa.f */
+ {14,1,a3,0,0,0}, /* jmpa.t */
+ {15,2,a3,0,0,0}, /* jmps.f */
+ {15,1,a3,0,0,0}, /* jmps.t */
+ {16,0,a3,0,0,0}, /* tac */
+ {17,0,a1r,A,0,0}, /* ldea */
+ {18,8,a1l,VLS,0,0}, /* ld.l */
+ {18,9,a1l,VM,0,0}, /* ld.x */
+ {19,0,a3,0,0,0}, /* tas */
+ {20,0,a3,0,0,0}, /* pshea */
+ {21,8,a2l,VLS,0,0}, /* st.l */
+ {21,9,a2l,VM,0,0}, /* st.x */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {22,0,a3,0,0,0}, /* call */
+ {23,0,a3,0,0,0}, /* calls */
+ {24,0,a3,0,0,0}, /* callq */
+ {25,0,a1r,A,0,0}, /* pfork */
+ {26,5,a2r,S,0,0}, /* ste.b */
+ {26,6,a2r,S,0,0}, /* ste.h */
+ {26,7,a2r,S,0,0}, /* ste.w */
+ {26,8,a2r,S,0,0}, /* ste.l */
+ {18,5,a1r,A,0,0}, /* ld.b */
+ {18,6,a1r,A,0,0}, /* ld.h */
+ {18,7,a1r,A,0,0}, /* ld.w */
+ {27,7,a1r,A,0,0}, /* incr.w */
+ {21,5,a2r,A,0,0}, /* st.b */
+ {21,6,a2r,A,0,0}, /* st.h */
+ {21,7,a2r,A,0,0}, /* st.w */
+ {27,8,a1r,S,0,0}, /* incr.l */
+ {18,5,a1r,S,0,0}, /* ld.b */
+ {18,6,a1r,S,0,0}, /* ld.h */
+ {18,7,a1r,S,0,0}, /* ld.w */
+ {18,8,a1r,S,0,0}, /* ld.l */
+ {21,5,a2r,S,0,0}, /* st.b */
+ {21,6,a2r,S,0,0}, /* st.h */
+ {21,7,a2r,S,0,0}, /* st.w */
+ {21,8,a2r,S,0,0}, /* st.l */
+ {18,5,a1r,V,0,0}, /* ld.b */
+ {18,6,a1r,V,0,0}, /* ld.h */
+ {18,7,a1r,V,0,0}, /* ld.w */
+ {18,8,a1r,V,0,0}, /* ld.l */
+ {21,5,a2r,V,0,0}, /* st.b */
+ {21,6,a2r,V,0,0}, /* st.h */
+ {21,7,a2r,V,0,0}, /* st.w */
+ {21,8,a2r,V,0,0}, /* st.l */
+};
+struct formstr format2[] = {
+ {28,5,rr,A,A,0}, /* cvtw.b */
+ {28,6,rr,A,A,0}, /* cvtw.h */
+ {29,7,rr,A,A,0}, /* cvtb.w */
+ {30,7,rr,A,A,0}, /* cvth.w */
+ {28,5,rr,S,S,0}, /* cvtw.b */
+ {28,6,rr,S,S,0}, /* cvtw.h */
+ {29,7,rr,S,S,0}, /* cvtb.w */
+ {30,7,rr,S,S,0}, /* cvth.w */
+ {28,3,rr,S,S,0}, /* cvtw.s */
+ {31,7,rr,S,S,0}, /* cvts.w */
+ {32,3,rr,S,S,0}, /* cvtd.s */
+ {31,4,rr,S,S,0}, /* cvts.d */
+ {31,8,rr,S,S,0}, /* cvts.l */
+ {32,8,rr,S,S,0}, /* cvtd.l */
+ {33,3,rr,S,S,0}, /* cvtl.s */
+ {33,4,rr,S,S,0}, /* cvtl.d */
+ {34,0,rr,A,A,0}, /* ldpa */
+ {8,0,nr,A,0,0}, /* shf */
+ {18,6,nr,A,0,0}, /* ld.h */
+ {18,7,nr,A,0,0}, /* ld.w */
+ {33,7,rr,S,S,0}, /* cvtl.w */
+ {28,8,rr,S,S,0}, /* cvtw.l */
+ {35,1,rr,S,S,0}, /* plc.t */
+ {36,0,rr,S,S,0}, /* tzc */
+ {37,6,rr,A,A,0}, /* eq.h */
+ {37,7,rr,A,A,0}, /* eq.w */
+ {37,6,nr,A,0,0}, /* eq.h */
+ {37,7,nr,A,0,0}, /* eq.w */
+ {37,5,rr,S,S,0}, /* eq.b */
+ {37,6,rr,S,S,0}, /* eq.h */
+ {37,7,rr,S,S,0}, /* eq.w */
+ {37,8,rr,S,S,0}, /* eq.l */
+ {38,6,rr,A,A,0}, /* leu.h */
+ {38,7,rr,A,A,0}, /* leu.w */
+ {38,6,nr,A,0,0}, /* leu.h */
+ {38,7,nr,A,0,0}, /* leu.w */
+ {38,5,rr,S,S,0}, /* leu.b */
+ {38,6,rr,S,S,0}, /* leu.h */
+ {38,7,rr,S,S,0}, /* leu.w */
+ {38,8,rr,S,S,0}, /* leu.l */
+ {39,6,rr,A,A,0}, /* ltu.h */
+ {39,7,rr,A,A,0}, /* ltu.w */
+ {39,6,nr,A,0,0}, /* ltu.h */
+ {39,7,nr,A,0,0}, /* ltu.w */
+ {39,5,rr,S,S,0}, /* ltu.b */
+ {39,6,rr,S,S,0}, /* ltu.h */
+ {39,7,rr,S,S,0}, /* ltu.w */
+ {39,8,rr,S,S,0}, /* ltu.l */
+ {40,6,rr,A,A,0}, /* le.h */
+ {40,7,rr,A,A,0}, /* le.w */
+ {40,6,nr,A,0,0}, /* le.h */
+ {40,7,nr,A,0,0}, /* le.w */
+ {40,5,rr,S,S,0}, /* le.b */
+ {40,6,rr,S,S,0}, /* le.h */
+ {40,7,rr,S,S,0}, /* le.w */
+ {40,8,rr,S,S,0}, /* le.l */
+ {41,6,rr,A,A,0}, /* lt.h */
+ {41,7,rr,A,A,0}, /* lt.w */
+ {41,6,nr,A,0,0}, /* lt.h */
+ {41,7,nr,A,0,0}, /* lt.w */
+ {41,5,rr,S,S,0}, /* lt.b */
+ {41,6,rr,S,S,0}, /* lt.h */
+ {41,7,rr,S,S,0}, /* lt.w */
+ {41,8,rr,S,S,0}, /* lt.l */
+ {9,7,rr,S,A,0}, /* add.w */
+ {8,0,rr,A,A,0}, /* shf */
+ {0,0,rr,A,A,0}, /* mov */
+ {0,0,rr,S,A,0}, /* mov */
+ {0,7,rr,S,S,0}, /* mov.w */
+ {8,0,rr,S,S,0}, /* shf */
+ {0,0,rr,S,S,0}, /* mov */
+ {0,0,rr,A,S,0}, /* mov */
+ {5,0,rr,A,A,0}, /* and */
+ {6,0,rr,A,A,0}, /* or */
+ {7,0,rr,A,A,0}, /* xor */
+ {42,0,rr,A,A,0}, /* not */
+ {5,0,rr,S,S,0}, /* and */
+ {6,0,rr,S,S,0}, /* or */
+ {7,0,rr,S,S,0}, /* xor */
+ {42,0,rr,S,S,0}, /* not */
+ {40,3,rr,S,S,0}, /* le.s */
+ {40,4,rr,S,S,0}, /* le.d */
+ {41,3,rr,S,S,0}, /* lt.s */
+ {41,4,rr,S,S,0}, /* lt.d */
+ {9,3,rr,S,S,0}, /* add.s */
+ {9,4,rr,S,S,0}, /* add.d */
+ {10,3,rr,S,S,0}, /* sub.s */
+ {10,4,rr,S,S,0}, /* sub.d */
+ {37,3,rr,S,S,0}, /* eq.s */
+ {37,4,rr,S,S,0}, /* eq.d */
+ {43,6,rr,A,A,0}, /* neg.h */
+ {43,7,rr,A,A,0}, /* neg.w */
+ {3,3,rr,S,S,0}, /* mul.s */
+ {3,4,rr,S,S,0}, /* mul.d */
+ {4,3,rr,S,S,0}, /* div.s */
+ {4,4,rr,S,S,0}, /* div.d */
+ {9,6,rr,A,A,0}, /* add.h */
+ {9,7,rr,A,A,0}, /* add.w */
+ {9,6,nr,A,0,0}, /* add.h */
+ {9,7,nr,A,0,0}, /* add.w */
+ {9,5,rr,S,S,0}, /* add.b */
+ {9,6,rr,S,S,0}, /* add.h */
+ {9,7,rr,S,S,0}, /* add.w */
+ {9,8,rr,S,S,0}, /* add.l */
+ {10,6,rr,A,A,0}, /* sub.h */
+ {10,7,rr,A,A,0}, /* sub.w */
+ {10,6,nr,A,0,0}, /* sub.h */
+ {10,7,nr,A,0,0}, /* sub.w */
+ {10,5,rr,S,S,0}, /* sub.b */
+ {10,6,rr,S,S,0}, /* sub.h */
+ {10,7,rr,S,S,0}, /* sub.w */
+ {10,8,rr,S,S,0}, /* sub.l */
+ {3,6,rr,A,A,0}, /* mul.h */
+ {3,7,rr,A,A,0}, /* mul.w */
+ {3,6,nr,A,0,0}, /* mul.h */
+ {3,7,nr,A,0,0}, /* mul.w */
+ {3,5,rr,S,S,0}, /* mul.b */
+ {3,6,rr,S,S,0}, /* mul.h */
+ {3,7,rr,S,S,0}, /* mul.w */
+ {3,8,rr,S,S,0}, /* mul.l */
+ {4,6,rr,A,A,0}, /* div.h */
+ {4,7,rr,A,A,0}, /* div.w */
+ {4,6,nr,A,0,0}, /* div.h */
+ {4,7,nr,A,0,0}, /* div.w */
+ {4,5,rr,S,S,0}, /* div.b */
+ {4,6,rr,S,S,0}, /* div.h */
+ {4,7,rr,S,S,0}, /* div.w */
+ {4,8,rr,S,S,0}, /* div.l */
+};
+struct formstr format3[] = {
+ {32,3,rr,V,V,0}, /* cvtd.s */
+ {31,4,rr,V,V,0}, /* cvts.d */
+ {33,4,rr,V,V,0}, /* cvtl.d */
+ {32,8,rr,V,V,0}, /* cvtd.l */
+ {0,0,rrl,S,S,VM}, /* mov */
+ {0,0,rlr,S,VM,S}, /* mov */
+ {0,0,0,0,0,0},
+ {44,0,rr,S,S,0}, /* lop */
+ {36,0,rr,V,V,0}, /* tzc */
+ {44,0,rr,V,V,0}, /* lop */
+ {0,0,0,0,0,0},
+ {42,0,rr,V,V,0}, /* not */
+ {8,0,rr,S,V,0}, /* shf */
+ {35,1,rr,V,V,0}, /* plc.t */
+ {45,2,rr,V,V,0}, /* cprs.f */
+ {45,1,rr,V,V,0}, /* cprs.t */
+ {37,3,rr,V,V,0}, /* eq.s */
+ {37,4,rr,V,V,0}, /* eq.d */
+ {43,3,rr,V,V,0}, /* neg.s */
+ {43,4,rr,V,V,0}, /* neg.d */
+ {37,3,rr,S,V,0}, /* eq.s */
+ {37,4,rr,S,V,0}, /* eq.d */
+ {43,3,rr,S,S,0}, /* neg.s */
+ {43,4,rr,S,S,0}, /* neg.d */
+ {40,3,rr,V,V,0}, /* le.s */
+ {40,4,rr,V,V,0}, /* le.d */
+ {41,3,rr,V,V,0}, /* lt.s */
+ {41,4,rr,V,V,0}, /* lt.d */
+ {40,3,rr,S,V,0}, /* le.s */
+ {40,4,rr,S,V,0}, /* le.d */
+ {41,3,rr,S,V,0}, /* lt.s */
+ {41,4,rr,S,V,0}, /* lt.d */
+ {37,5,rr,V,V,0}, /* eq.b */
+ {37,6,rr,V,V,0}, /* eq.h */
+ {37,7,rr,V,V,0}, /* eq.w */
+ {37,8,rr,V,V,0}, /* eq.l */
+ {37,5,rr,S,V,0}, /* eq.b */
+ {37,6,rr,S,V,0}, /* eq.h */
+ {37,7,rr,S,V,0}, /* eq.w */
+ {37,8,rr,S,V,0}, /* eq.l */
+ {40,5,rr,V,V,0}, /* le.b */
+ {40,6,rr,V,V,0}, /* le.h */
+ {40,7,rr,V,V,0}, /* le.w */
+ {40,8,rr,V,V,0}, /* le.l */
+ {40,5,rr,S,V,0}, /* le.b */
+ {40,6,rr,S,V,0}, /* le.h */
+ {40,7,rr,S,V,0}, /* le.w */
+ {40,8,rr,S,V,0}, /* le.l */
+ {41,5,rr,V,V,0}, /* lt.b */
+ {41,6,rr,V,V,0}, /* lt.h */
+ {41,7,rr,V,V,0}, /* lt.w */
+ {41,8,rr,V,V,0}, /* lt.l */
+ {41,5,rr,S,V,0}, /* lt.b */
+ {41,6,rr,S,V,0}, /* lt.h */
+ {41,7,rr,S,V,0}, /* lt.w */
+ {41,8,rr,S,V,0}, /* lt.l */
+ {43,5,rr,V,V,0}, /* neg.b */
+ {43,6,rr,V,V,0}, /* neg.h */
+ {43,7,rr,V,V,0}, /* neg.w */
+ {43,8,rr,V,V,0}, /* neg.l */
+ {43,5,rr,S,S,0}, /* neg.b */
+ {43,6,rr,S,S,0}, /* neg.h */
+ {43,7,rr,S,S,0}, /* neg.w */
+ {43,8,rr,S,S,0}, /* neg.l */
+};
+struct formstr format4[] = {
+ {46,0,nops,0,0,0}, /* nop */
+ {47,0,pcrel,0,0,0}, /* br */
+ {48,2,pcrel,0,0,0}, /* bri.f */
+ {48,1,pcrel,0,0,0}, /* bri.t */
+ {49,2,pcrel,0,0,0}, /* bra.f */
+ {49,1,pcrel,0,0,0}, /* bra.t */
+ {50,2,pcrel,0,0,0}, /* brs.f */
+ {50,1,pcrel,0,0,0}, /* brs.t */
+};
+struct formstr format5[] = {
+ {51,5,rr,V,V,0}, /* ldvi.b */
+ {51,6,rr,V,V,0}, /* ldvi.h */
+ {51,7,rr,V,V,0}, /* ldvi.w */
+ {51,8,rr,V,V,0}, /* ldvi.l */
+ {28,3,rr,V,V,0}, /* cvtw.s */
+ {31,7,rr,V,V,0}, /* cvts.w */
+ {28,8,rr,V,V,0}, /* cvtw.l */
+ {33,7,rr,V,V,0}, /* cvtl.w */
+ {52,5,rxr,V,V,0}, /* stvi.b */
+ {52,6,rxr,V,V,0}, /* stvi.h */
+ {52,7,rxr,V,V,0}, /* stvi.w */
+ {52,8,rxr,V,V,0}, /* stvi.l */
+ {52,5,rxr,S,V,0}, /* stvi.b */
+ {52,6,rxr,S,V,0}, /* stvi.h */
+ {52,7,rxr,S,V,0}, /* stvi.w */
+ {52,8,rxr,S,V,0}, /* stvi.l */
+};
+struct formstr format6[] = {
+ {53,0,r,A,0,0}, /* ldsdr */
+ {54,0,r,A,0,0}, /* ldkdr */
+ {55,3,r,S,0,0}, /* ln.s */
+ {55,4,r,S,0,0}, /* ln.d */
+ {56,0,nops,0,0,0}, /* patu */
+ {57,0,r,A,0,0}, /* pate */
+ {58,0,nops,0,0,0}, /* pich */
+ {59,0,nops,0,0,0}, /* plch */
+ {0,0,lr,PSW,A,0}, /* mov */
+ {0,0,rxl,A,PSW,0}, /* mov */
+ {0,0,lr,PC,A,0}, /* mov */
+ {60,0,r,S,0,0}, /* idle */
+ {0,0,lr,ITR,S,0}, /* mov */
+ {0,0,rxl,S,ITR,0}, /* mov */
+ {0,0,0,0,0,0},
+ {0,0,rxl,S,ITSR,0}, /* mov */
+ {61,0,nops,0,0,0}, /* rtnq */
+ {62,0,nops,0,0,0}, /* cfork */
+ {63,0,nops,0,0,0}, /* rtn */
+ {64,0,nops,0,0,0}, /* wfork */
+ {65,0,nops,0,0,0}, /* join */
+ {66,0,nops,0,0,0}, /* rtnc */
+ {67,3,r,S,0,0}, /* exp.s */
+ {67,4,r,S,0,0}, /* exp.d */
+ {68,3,r,S,0,0}, /* sin.s */
+ {68,4,r,S,0,0}, /* sin.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {69,3,r,S,0,0}, /* cos.s */
+ {69,4,r,S,0,0}, /* cos.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {70,7,r,A,0,0}, /* psh.w */
+ {0,0,0,0,0,0},
+ {71,7,r,A,0,0}, /* pop.w */
+ {0,0,0,0,0,0},
+ {70,7,r,S,0,0}, /* psh.w */
+ {70,8,r,S,0,0}, /* psh.l */
+ {71,7,r,S,0,0}, /* pop.w */
+ {71,8,r,S,0,0}, /* pop.l */
+ {72,0,nops,0,0,0}, /* eni */
+ {73,0,nops,0,0,0}, /* dsi */
+ {74,0,nops,0,0,0}, /* bkpt */
+ {75,0,nops,0,0,0}, /* msync */
+ {76,0,r,S,0,0}, /* mski */
+ {77,0,r,S,0,0}, /* xmti */
+ {0,0,rxl,S,VV,0}, /* mov */
+ {78,0,nops,0,0,0}, /* tstvv */
+ {0,0,lr,VS,A,0}, /* mov */
+ {0,0,rxl,A,VS,0}, /* mov */
+ {0,0,lr,VL,A,0}, /* mov */
+ {0,0,rxl,A,VL,0}, /* mov */
+ {0,7,lr,VS,S,0}, /* mov.w */
+ {0,7,rxl,S,VS,0}, /* mov.w */
+ {0,7,lr,VL,S,0}, /* mov.w */
+ {0,7,rxl,S,VL,0}, /* mov.w */
+ {79,0,r,A,0,0}, /* diag */
+ {80,0,nops,0,0,0}, /* pbkpt */
+ {81,3,r,S,0,0}, /* sqrt.s */
+ {81,4,r,S,0,0}, /* sqrt.d */
+ {82,0,nops,0,0,0}, /* casr */
+ {0,0,0,0,0,0},
+ {83,3,r,S,0,0}, /* atan.s */
+ {83,4,r,S,0,0}, /* atan.d */
+};
+struct formstr format7[] = {
+ {84,5,r,V,0,0}, /* sum.b */
+ {84,6,r,V,0,0}, /* sum.h */
+ {84,7,r,V,0,0}, /* sum.w */
+ {84,8,r,V,0,0}, /* sum.l */
+ {85,0,r,V,0,0}, /* all */
+ {86,0,r,V,0,0}, /* any */
+ {87,0,r,V,0,0}, /* parity */
+ {0,0,0,0,0,0},
+ {88,5,r,V,0,0}, /* max.b */
+ {88,6,r,V,0,0}, /* max.h */
+ {88,7,r,V,0,0}, /* max.w */
+ {88,8,r,V,0,0}, /* max.l */
+ {89,5,r,V,0,0}, /* min.b */
+ {89,6,r,V,0,0}, /* min.h */
+ {89,7,r,V,0,0}, /* min.w */
+ {89,8,r,V,0,0}, /* min.l */
+ {84,3,r,V,0,0}, /* sum.s */
+ {84,4,r,V,0,0}, /* sum.d */
+ {90,3,r,V,0,0}, /* prod.s */
+ {90,4,r,V,0,0}, /* prod.d */
+ {88,3,r,V,0,0}, /* max.s */
+ {88,4,r,V,0,0}, /* max.d */
+ {89,3,r,V,0,0}, /* min.s */
+ {89,4,r,V,0,0}, /* min.d */
+ {90,5,r,V,0,0}, /* prod.b */
+ {90,6,r,V,0,0}, /* prod.h */
+ {90,7,r,V,0,0}, /* prod.w */
+ {90,8,r,V,0,0}, /* prod.l */
+ {35,2,lr,VM,S,0}, /* plc.f */
+ {35,1,lr,VM,S,0}, /* plc.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr formatx[] = {
+ {0,0,0,0,0,0},
+};
+struct formstr format1a[] = {
+ {91,0,imr,A,0,0}, /* halt */
+ {92,0,a4,0,0,0}, /* sysc */
+ {18,6,imr,A,0,0}, /* ld.h */
+ {18,7,imr,A,0,0}, /* ld.w */
+ {5,0,imr,A,0,0}, /* and */
+ {6,0,imr,A,0,0}, /* or */
+ {7,0,imr,A,0,0}, /* xor */
+ {8,0,imr,A,0,0}, /* shf */
+ {9,6,imr,A,0,0}, /* add.h */
+ {9,7,imr,A,0,0}, /* add.w */
+ {10,6,imr,A,0,0}, /* sub.h */
+ {10,7,imr,A,0,0}, /* sub.w */
+ {3,6,imr,A,0,0}, /* mul.h */
+ {3,7,imr,A,0,0}, /* mul.w */
+ {4,6,imr,A,0,0}, /* div.h */
+ {4,7,imr,A,0,0}, /* div.w */
+ {18,7,iml,VL,0,0}, /* ld.w */
+ {18,7,iml,VS,0,0}, /* ld.w */
+ {0,0,0,0,0,0},
+ {8,7,imr,S,0,0}, /* shf.w */
+ {93,0,a5,0,0,0}, /* trap */
+ {0,0,0,0,0,0},
+ {37,6,imr,A,0,0}, /* eq.h */
+ {37,7,imr,A,0,0}, /* eq.w */
+ {38,6,imr,A,0,0}, /* leu.h */
+ {38,7,imr,A,0,0}, /* leu.w */
+ {39,6,imr,A,0,0}, /* ltu.h */
+ {39,7,imr,A,0,0}, /* ltu.w */
+ {40,6,imr,A,0,0}, /* le.h */
+ {40,7,imr,A,0,0}, /* le.w */
+ {41,6,imr,A,0,0}, /* lt.h */
+ {41,7,imr,A,0,0}, /* lt.w */
+};
+struct formstr format1b[] = {
+ {18,4,imr,S,0,0}, /* ld.d */
+ {18,10,imr,S,0,0}, /* ld.u */
+ {18,8,imr,S,0,0}, /* ld.l */
+ {18,7,imr,S,0,0}, /* ld.w */
+ {5,0,imr,S,0,0}, /* and */
+ {6,0,imr,S,0,0}, /* or */
+ {7,0,imr,S,0,0}, /* xor */
+ {8,0,imr,S,0,0}, /* shf */
+ {9,6,imr,S,0,0}, /* add.h */
+ {9,7,imr,S,0,0}, /* add.w */
+ {10,6,imr,S,0,0}, /* sub.h */
+ {10,7,imr,S,0,0}, /* sub.w */
+ {3,6,imr,S,0,0}, /* mul.h */
+ {3,7,imr,S,0,0}, /* mul.w */
+ {4,6,imr,S,0,0}, /* div.h */
+ {4,7,imr,S,0,0}, /* div.w */
+ {9,3,imr,S,0,0}, /* add.s */
+ {10,3,imr,S,0,0}, /* sub.s */
+ {3,3,imr,S,0,0}, /* mul.s */
+ {4,3,imr,S,0,0}, /* div.s */
+ {40,3,imr,S,0,0}, /* le.s */
+ {41,3,imr,S,0,0}, /* lt.s */
+ {37,6,imr,S,0,0}, /* eq.h */
+ {37,7,imr,S,0,0}, /* eq.w */
+ {38,6,imr,S,0,0}, /* leu.h */
+ {38,7,imr,S,0,0}, /* leu.w */
+ {39,6,imr,S,0,0}, /* ltu.h */
+ {39,7,imr,S,0,0}, /* ltu.w */
+ {40,6,imr,S,0,0}, /* le.h */
+ {40,7,imr,S,0,0}, /* le.w */
+ {41,6,imr,S,0,0}, /* lt.h */
+ {41,7,imr,S,0,0}, /* lt.w */
+};
+struct formstr e0_format0[] = {
+ {10,3,rrr,S,V,V}, /* sub.s */
+ {10,4,rrr,S,V,V}, /* sub.d */
+ {4,3,rrr,S,V,V}, /* div.s */
+ {4,4,rrr,S,V,V}, /* div.d */
+ {10,11,rrr,S,V,V}, /* sub.s.f */
+ {10,12,rrr,S,V,V}, /* sub.d.f */
+ {4,11,rrr,S,V,V}, /* div.s.f */
+ {4,12,rrr,S,V,V}, /* div.d.f */
+ {3,11,rrr,V,V,V}, /* mul.s.f */
+ {3,12,rrr,V,V,V}, /* mul.d.f */
+ {4,11,rrr,V,V,V}, /* div.s.f */
+ {4,12,rrr,V,V,V}, /* div.d.f */
+ {3,11,rrr,V,S,V}, /* mul.s.f */
+ {3,12,rrr,V,S,V}, /* mul.d.f */
+ {4,11,rrr,V,S,V}, /* div.s.f */
+ {4,12,rrr,V,S,V}, /* div.d.f */
+ {5,2,rrr,V,V,V}, /* and.f */
+ {6,2,rrr,V,V,V}, /* or.f */
+ {7,2,rrr,V,V,V}, /* xor.f */
+ {8,2,rrr,V,V,V}, /* shf.f */
+ {5,2,rrr,V,S,V}, /* and.f */
+ {6,2,rrr,V,S,V}, /* or.f */
+ {7,2,rrr,V,S,V}, /* xor.f */
+ {8,2,rrr,V,S,V}, /* shf.f */
+ {9,11,rrr,V,V,V}, /* add.s.f */
+ {9,12,rrr,V,V,V}, /* add.d.f */
+ {10,11,rrr,V,V,V}, /* sub.s.f */
+ {10,12,rrr,V,V,V}, /* sub.d.f */
+ {9,11,rrr,V,S,V}, /* add.s.f */
+ {9,12,rrr,V,S,V}, /* add.d.f */
+ {10,11,rrr,V,S,V}, /* sub.s.f */
+ {10,12,rrr,V,S,V}, /* sub.d.f */
+ {9,13,rrr,V,V,V}, /* add.b.f */
+ {9,14,rrr,V,V,V}, /* add.h.f */
+ {9,15,rrr,V,V,V}, /* add.w.f */
+ {9,16,rrr,V,V,V}, /* add.l.f */
+ {9,13,rrr,V,S,V}, /* add.b.f */
+ {9,14,rrr,V,S,V}, /* add.h.f */
+ {9,15,rrr,V,S,V}, /* add.w.f */
+ {9,16,rrr,V,S,V}, /* add.l.f */
+ {10,13,rrr,V,V,V}, /* sub.b.f */
+ {10,14,rrr,V,V,V}, /* sub.h.f */
+ {10,15,rrr,V,V,V}, /* sub.w.f */
+ {10,16,rrr,V,V,V}, /* sub.l.f */
+ {10,13,rrr,V,S,V}, /* sub.b.f */
+ {10,14,rrr,V,S,V}, /* sub.h.f */
+ {10,15,rrr,V,S,V}, /* sub.w.f */
+ {10,16,rrr,V,S,V}, /* sub.l.f */
+ {3,13,rrr,V,V,V}, /* mul.b.f */
+ {3,14,rrr,V,V,V}, /* mul.h.f */
+ {3,15,rrr,V,V,V}, /* mul.w.f */
+ {3,16,rrr,V,V,V}, /* mul.l.f */
+ {3,13,rrr,V,S,V}, /* mul.b.f */
+ {3,14,rrr,V,S,V}, /* mul.h.f */
+ {3,15,rrr,V,S,V}, /* mul.w.f */
+ {3,16,rrr,V,S,V}, /* mul.l.f */
+ {4,13,rrr,V,V,V}, /* div.b.f */
+ {4,14,rrr,V,V,V}, /* div.h.f */
+ {4,15,rrr,V,V,V}, /* div.w.f */
+ {4,16,rrr,V,V,V}, /* div.l.f */
+ {4,13,rrr,V,S,V}, /* div.b.f */
+ {4,14,rrr,V,S,V}, /* div.h.f */
+ {4,15,rrr,V,S,V}, /* div.w.f */
+ {4,16,rrr,V,S,V}, /* div.l.f */
+};
+struct formstr e0_format1[] = {
+ {0,0,0,0,0,0},
+ {94,0,a3,0,0,0}, /* tst */
+ {95,0,a3,0,0,0}, /* lck */
+ {96,0,a3,0,0,0}, /* ulk */
+ {17,0,a1r,S,0,0}, /* ldea */
+ {97,0,a1r,A,0,0}, /* spawn */
+ {98,0,a1r,A,0,0}, /* ldcmr */
+ {99,0,a2r,A,0,0}, /* stcmr */
+ {100,0,a1r,A,0,0}, /* popr */
+ {101,0,a2r,A,0,0}, /* pshr */
+ {102,7,a1r,A,0,0}, /* rcvr.w */
+ {103,7,a2r,A,0,0}, /* matm.w */
+ {104,7,a2r,A,0,0}, /* sndr.w */
+ {104,8,a2r,S,0,0}, /* sndr.l */
+ {102,8,a1r,S,0,0}, /* rcvr.l */
+ {103,8,a2r,S,0,0}, /* matm.l */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {105,7,a2r,A,0,0}, /* putr.w */
+ {105,8,a2r,S,0,0}, /* putr.l */
+ {106,7,a1r,A,0,0}, /* getr.w */
+ {106,8,a1r,S,0,0}, /* getr.l */
+ {26,13,a2r,S,0,0}, /* ste.b.f */
+ {26,14,a2r,S,0,0}, /* ste.h.f */
+ {26,15,a2r,S,0,0}, /* ste.w.f */
+ {26,16,a2r,S,0,0}, /* ste.l.f */
+ {107,7,a2r,A,0,0}, /* matr.w */
+ {108,7,a2r,A,0,0}, /* mat.w */
+ {109,7,a1r,A,0,0}, /* get.w */
+ {110,7,a1r,A,0,0}, /* rcv.w */
+ {0,0,0,0,0,0},
+ {111,7,a1r,A,0,0}, /* inc.w */
+ {112,7,a2r,A,0,0}, /* put.w */
+ {113,7,a2r,A,0,0}, /* snd.w */
+ {107,8,a2r,S,0,0}, /* matr.l */
+ {108,8,a2r,S,0,0}, /* mat.l */
+ {109,8,a1r,S,0,0}, /* get.l */
+ {110,8,a1r,S,0,0}, /* rcv.l */
+ {0,0,0,0,0,0},
+ {111,8,a1r,S,0,0}, /* inc.l */
+ {112,8,a2r,S,0,0}, /* put.l */
+ {113,8,a2r,S,0,0}, /* snd.l */
+ {18,13,a1r,V,0,0}, /* ld.b.f */
+ {18,14,a1r,V,0,0}, /* ld.h.f */
+ {18,15,a1r,V,0,0}, /* ld.w.f */
+ {18,16,a1r,V,0,0}, /* ld.l.f */
+ {21,13,a2r,V,0,0}, /* st.b.f */
+ {21,14,a2r,V,0,0}, /* st.h.f */
+ {21,15,a2r,V,0,0}, /* st.w.f */
+ {21,16,a2r,V,0,0}, /* st.l.f */
+};
+struct formstr e0_format2[] = {
+ {28,5,rr,V,V,0}, /* cvtw.b */
+ {28,6,rr,V,V,0}, /* cvtw.h */
+ {29,7,rr,V,V,0}, /* cvtb.w */
+ {30,7,rr,V,V,0}, /* cvth.w */
+ {28,13,rr,V,V,0}, /* cvtw.b.f */
+ {28,14,rr,V,V,0}, /* cvtw.h.f */
+ {29,15,rr,V,V,0}, /* cvtb.w.f */
+ {30,15,rr,V,V,0}, /* cvth.w.f */
+ {31,8,rr,V,V,0}, /* cvts.l */
+ {32,7,rr,V,V,0}, /* cvtd.w */
+ {33,3,rr,V,V,0}, /* cvtl.s */
+ {28,4,rr,V,V,0}, /* cvtw.d */
+ {31,16,rr,V,V,0}, /* cvts.l.f */
+ {32,15,rr,V,V,0}, /* cvtd.w.f */
+ {33,11,rr,V,V,0}, /* cvtl.s.f */
+ {28,12,rr,V,V,0}, /* cvtw.d.f */
+ {114,0,rr,S,S,0}, /* enal */
+ {8,7,rr,S,S,0}, /* shf.w */
+ {115,0,rr,S,S,0}, /* enag */
+ {0,0,0,0,0,0},
+ {28,4,rr,S,S,0}, /* cvtw.d */
+ {32,7,rr,S,S,0}, /* cvtd.w */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,3,rr,S,S,0}, /* frint.s */
+ {116,4,rr,S,S,0}, /* frint.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,3,rr,V,V,0}, /* frint.s */
+ {116,4,rr,V,V,0}, /* frint.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,11,rr,V,V,0}, /* frint.s.f */
+ {116,12,rr,V,V,0}, /* frint.d.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {81,3,rr,V,V,0}, /* sqrt.s */
+ {81,4,rr,V,V,0}, /* sqrt.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {81,11,rr,V,V,0}, /* sqrt.s.f */
+ {81,12,rr,V,V,0}, /* sqrt.d.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e0_format3[] = {
+ {32,11,rr,V,V,0}, /* cvtd.s.f */
+ {31,12,rr,V,V,0}, /* cvts.d.f */
+ {33,12,rr,V,V,0}, /* cvtl.d.f */
+ {32,16,rr,V,V,0}, /* cvtd.l.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {36,2,rr,V,V,0}, /* tzc.f */
+ {44,2,rr,V,V,0}, /* lop.f */
+ {117,2,rr,V,V,0}, /* xpnd.f */
+ {42,2,rr,V,V,0}, /* not.f */
+ {8,2,rr,S,V,0}, /* shf.f */
+ {35,17,rr,V,V,0}, /* plc.t.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {37,11,rr,V,V,0}, /* eq.s.f */
+ {37,12,rr,V,V,0}, /* eq.d.f */
+ {43,11,rr,V,V,0}, /* neg.s.f */
+ {43,12,rr,V,V,0}, /* neg.d.f */
+ {37,11,rr,S,V,0}, /* eq.s.f */
+ {37,12,rr,S,V,0}, /* eq.d.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {40,11,rr,V,V,0}, /* le.s.f */
+ {40,12,rr,V,V,0}, /* le.d.f */
+ {41,11,rr,V,V,0}, /* lt.s.f */
+ {41,12,rr,V,V,0}, /* lt.d.f */
+ {40,11,rr,S,V,0}, /* le.s.f */
+ {40,12,rr,S,V,0}, /* le.d.f */
+ {41,11,rr,S,V,0}, /* lt.s.f */
+ {41,12,rr,S,V,0}, /* lt.d.f */
+ {37,13,rr,V,V,0}, /* eq.b.f */
+ {37,14,rr,V,V,0}, /* eq.h.f */
+ {37,15,rr,V,V,0}, /* eq.w.f */
+ {37,16,rr,V,V,0}, /* eq.l.f */
+ {37,13,rr,S,V,0}, /* eq.b.f */
+ {37,14,rr,S,V,0}, /* eq.h.f */
+ {37,15,rr,S,V,0}, /* eq.w.f */
+ {37,16,rr,S,V,0}, /* eq.l.f */
+ {40,13,rr,V,V,0}, /* le.b.f */
+ {40,14,rr,V,V,0}, /* le.h.f */
+ {40,15,rr,V,V,0}, /* le.w.f */
+ {40,16,rr,V,V,0}, /* le.l.f */
+ {40,13,rr,S,V,0}, /* le.b.f */
+ {40,14,rr,S,V,0}, /* le.h.f */
+ {40,15,rr,S,V,0}, /* le.w.f */
+ {40,16,rr,S,V,0}, /* le.l.f */
+ {41,13,rr,V,V,0}, /* lt.b.f */
+ {41,14,rr,V,V,0}, /* lt.h.f */
+ {41,15,rr,V,V,0}, /* lt.w.f */
+ {41,16,rr,V,V,0}, /* lt.l.f */
+ {41,13,rr,S,V,0}, /* lt.b.f */
+ {41,14,rr,S,V,0}, /* lt.h.f */
+ {41,15,rr,S,V,0}, /* lt.w.f */
+ {41,16,rr,S,V,0}, /* lt.l.f */
+ {43,13,rr,V,V,0}, /* neg.b.f */
+ {43,14,rr,V,V,0}, /* neg.h.f */
+ {43,15,rr,V,V,0}, /* neg.w.f */
+ {43,16,rr,V,V,0}, /* neg.l.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e0_format4[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e0_format5[] = {
+ {51,13,rr,V,V,0}, /* ldvi.b.f */
+ {51,14,rr,V,V,0}, /* ldvi.h.f */
+ {51,15,rr,V,V,0}, /* ldvi.w.f */
+ {51,16,rr,V,V,0}, /* ldvi.l.f */
+ {28,11,rr,V,V,0}, /* cvtw.s.f */
+ {31,15,rr,V,V,0}, /* cvts.w.f */
+ {28,16,rr,V,V,0}, /* cvtw.l.f */
+ {33,15,rr,V,V,0}, /* cvtl.w.f */
+ {52,13,rxr,V,V,0}, /* stvi.b.f */
+ {52,14,rxr,V,V,0}, /* stvi.h.f */
+ {52,15,rxr,V,V,0}, /* stvi.w.f */
+ {52,16,rxr,V,V,0}, /* stvi.l.f */
+ {52,13,rxr,S,V,0}, /* stvi.b.f */
+ {52,14,rxr,S,V,0}, /* stvi.h.f */
+ {52,15,rxr,S,V,0}, /* stvi.w.f */
+ {52,16,rxr,S,V,0}, /* stvi.l.f */
+};
+struct formstr e0_format6[] = {
+ {0,0,rxl,S,CIR,0}, /* mov */
+ {0,0,lr,CIR,S,0}, /* mov */
+ {0,0,lr,TOC,S,0}, /* mov */
+ {0,0,lr,CPUID,S,0}, /* mov */
+ {0,0,rxl,S,TTR,0}, /* mov */
+ {0,0,lr,TTR,S,0}, /* mov */
+ {118,0,nops,0,0,0}, /* ctrsl */
+ {119,0,nops,0,0,0}, /* ctrsg */
+ {0,0,rxl,S,VMU,0}, /* mov */
+ {0,0,lr,VMU,S,0}, /* mov */
+ {0,0,rxl,S,VML,0}, /* mov */
+ {0,0,lr,VML,S,0}, /* mov */
+ {0,0,rxl,S,ICR,0}, /* mov */
+ {0,0,lr,ICR,S,0}, /* mov */
+ {0,0,rxl,S,TCPU,0}, /* mov */
+ {0,0,lr,TCPU,S,0}, /* mov */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {120,0,nops,0,0,0}, /* stop */
+ {0,0,0,0,0,0},
+ {0,0,rxl,S,TID,0}, /* mov */
+ {0,0,lr,TID,S,0}, /* mov */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e0_format7[] = {
+ {84,13,r,V,0,0}, /* sum.b.f */
+ {84,14,r,V,0,0}, /* sum.h.f */
+ {84,15,r,V,0,0}, /* sum.w.f */
+ {84,16,r,V,0,0}, /* sum.l.f */
+ {85,2,r,V,0,0}, /* all.f */
+ {86,2,r,V,0,0}, /* any.f */
+ {87,2,r,V,0,0}, /* parity.f */
+ {0,0,0,0,0,0},
+ {88,13,r,V,0,0}, /* max.b.f */
+ {88,14,r,V,0,0}, /* max.h.f */
+ {88,15,r,V,0,0}, /* max.w.f */
+ {88,16,r,V,0,0}, /* max.l.f */
+ {89,13,r,V,0,0}, /* min.b.f */
+ {89,14,r,V,0,0}, /* min.h.f */
+ {89,15,r,V,0,0}, /* min.w.f */
+ {89,16,r,V,0,0}, /* min.l.f */
+ {84,11,r,V,0,0}, /* sum.s.f */
+ {84,12,r,V,0,0}, /* sum.d.f */
+ {90,11,r,V,0,0}, /* prod.s.f */
+ {90,12,r,V,0,0}, /* prod.d.f */
+ {88,11,r,V,0,0}, /* max.s.f */
+ {88,12,r,V,0,0}, /* max.d.f */
+ {89,11,r,V,0,0}, /* min.s.f */
+ {89,12,r,V,0,0}, /* min.d.f */
+ {90,13,r,V,0,0}, /* prod.b.f */
+ {90,14,r,V,0,0}, /* prod.h.f */
+ {90,15,r,V,0,0}, /* prod.w.f */
+ {90,16,r,V,0,0}, /* prod.l.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e1_format0[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {10,18,rrr,S,V,V}, /* sub.s.t */
+ {10,19,rrr,S,V,V}, /* sub.d.t */
+ {4,18,rrr,S,V,V}, /* div.s.t */
+ {4,19,rrr,S,V,V}, /* div.d.t */
+ {3,18,rrr,V,V,V}, /* mul.s.t */
+ {3,19,rrr,V,V,V}, /* mul.d.t */
+ {4,18,rrr,V,V,V}, /* div.s.t */
+ {4,19,rrr,V,V,V}, /* div.d.t */
+ {3,18,rrr,V,S,V}, /* mul.s.t */
+ {3,19,rrr,V,S,V}, /* mul.d.t */
+ {4,18,rrr,V,S,V}, /* div.s.t */
+ {4,19,rrr,V,S,V}, /* div.d.t */
+ {5,1,rrr,V,V,V}, /* and.t */
+ {6,1,rrr,V,V,V}, /* or.t */
+ {7,1,rrr,V,V,V}, /* xor.t */
+ {8,1,rrr,V,V,V}, /* shf.t */
+ {5,1,rrr,V,S,V}, /* and.t */
+ {6,1,rrr,V,S,V}, /* or.t */
+ {7,1,rrr,V,S,V}, /* xor.t */
+ {8,1,rrr,V,S,V}, /* shf.t */
+ {9,18,rrr,V,V,V}, /* add.s.t */
+ {9,19,rrr,V,V,V}, /* add.d.t */
+ {10,18,rrr,V,V,V}, /* sub.s.t */
+ {10,19,rrr,V,V,V}, /* sub.d.t */
+ {9,18,rrr,V,S,V}, /* add.s.t */
+ {9,19,rrr,V,S,V}, /* add.d.t */
+ {10,18,rrr,V,S,V}, /* sub.s.t */
+ {10,19,rrr,V,S,V}, /* sub.d.t */
+ {9,20,rrr,V,V,V}, /* add.b.t */
+ {9,21,rrr,V,V,V}, /* add.h.t */
+ {9,22,rrr,V,V,V}, /* add.w.t */
+ {9,23,rrr,V,V,V}, /* add.l.t */
+ {9,20,rrr,V,S,V}, /* add.b.t */
+ {9,21,rrr,V,S,V}, /* add.h.t */
+ {9,22,rrr,V,S,V}, /* add.w.t */
+ {9,23,rrr,V,S,V}, /* add.l.t */
+ {10,20,rrr,V,V,V}, /* sub.b.t */
+ {10,21,rrr,V,V,V}, /* sub.h.t */
+ {10,22,rrr,V,V,V}, /* sub.w.t */
+ {10,23,rrr,V,V,V}, /* sub.l.t */
+ {10,20,rrr,V,S,V}, /* sub.b.t */
+ {10,21,rrr,V,S,V}, /* sub.h.t */
+ {10,22,rrr,V,S,V}, /* sub.w.t */
+ {10,23,rrr,V,S,V}, /* sub.l.t */
+ {3,20,rrr,V,V,V}, /* mul.b.t */
+ {3,21,rrr,V,V,V}, /* mul.h.t */
+ {3,22,rrr,V,V,V}, /* mul.w.t */
+ {3,23,rrr,V,V,V}, /* mul.l.t */
+ {3,20,rrr,V,S,V}, /* mul.b.t */
+ {3,21,rrr,V,S,V}, /* mul.h.t */
+ {3,22,rrr,V,S,V}, /* mul.w.t */
+ {3,23,rrr,V,S,V}, /* mul.l.t */
+ {4,20,rrr,V,V,V}, /* div.b.t */
+ {4,21,rrr,V,V,V}, /* div.h.t */
+ {4,22,rrr,V,V,V}, /* div.w.t */
+ {4,23,rrr,V,V,V}, /* div.l.t */
+ {4,20,rrr,V,S,V}, /* div.b.t */
+ {4,21,rrr,V,S,V}, /* div.h.t */
+ {4,22,rrr,V,S,V}, /* div.w.t */
+ {4,23,rrr,V,S,V}, /* div.l.t */
+};
+struct formstr e1_format1[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {26,20,a2r,S,0,0}, /* ste.b.t */
+ {26,21,a2r,S,0,0}, /* ste.h.t */
+ {26,22,a2r,S,0,0}, /* ste.w.t */
+ {26,23,a2r,S,0,0}, /* ste.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {18,20,a1r,V,0,0}, /* ld.b.t */
+ {18,21,a1r,V,0,0}, /* ld.h.t */
+ {18,22,a1r,V,0,0}, /* ld.w.t */
+ {18,23,a1r,V,0,0}, /* ld.l.t */
+ {21,20,a2r,V,0,0}, /* st.b.t */
+ {21,21,a2r,V,0,0}, /* st.h.t */
+ {21,22,a2r,V,0,0}, /* st.w.t */
+ {21,23,a2r,V,0,0}, /* st.l.t */
+};
+struct formstr e1_format2[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {28,20,rr,V,V,0}, /* cvtw.b.t */
+ {28,21,rr,V,V,0}, /* cvtw.h.t */
+ {29,22,rr,V,V,0}, /* cvtb.w.t */
+ {30,22,rr,V,V,0}, /* cvth.w.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {31,23,rr,V,V,0}, /* cvts.l.t */
+ {32,22,rr,V,V,0}, /* cvtd.w.t */
+ {33,18,rr,V,V,0}, /* cvtl.s.t */
+ {28,19,rr,V,V,0}, /* cvtw.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,18,rr,V,V,0}, /* frint.s.t */
+ {116,19,rr,V,V,0}, /* frint.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {81,18,rr,V,V,0}, /* sqrt.s.t */
+ {81,19,rr,V,V,0}, /* sqrt.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e1_format3[] = {
+ {32,18,rr,V,V,0}, /* cvtd.s.t */
+ {31,19,rr,V,V,0}, /* cvts.d.t */
+ {33,19,rr,V,V,0}, /* cvtl.d.t */
+ {32,23,rr,V,V,0}, /* cvtd.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {36,1,rr,V,V,0}, /* tzc.t */
+ {44,1,rr,V,V,0}, /* lop.t */
+ {117,1,rr,V,V,0}, /* xpnd.t */
+ {42,1,rr,V,V,0}, /* not.t */
+ {8,1,rr,S,V,0}, /* shf.t */
+ {35,24,rr,V,V,0}, /* plc.t.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {37,18,rr,V,V,0}, /* eq.s.t */
+ {37,19,rr,V,V,0}, /* eq.d.t */
+ {43,18,rr,V,V,0}, /* neg.s.t */
+ {43,19,rr,V,V,0}, /* neg.d.t */
+ {37,18,rr,S,V,0}, /* eq.s.t */
+ {37,19,rr,S,V,0}, /* eq.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {40,18,rr,V,V,0}, /* le.s.t */
+ {40,19,rr,V,V,0}, /* le.d.t */
+ {41,18,rr,V,V,0}, /* lt.s.t */
+ {41,19,rr,V,V,0}, /* lt.d.t */
+ {40,18,rr,S,V,0}, /* le.s.t */
+ {40,19,rr,S,V,0}, /* le.d.t */
+ {41,18,rr,S,V,0}, /* lt.s.t */
+ {41,19,rr,S,V,0}, /* lt.d.t */
+ {37,20,rr,V,V,0}, /* eq.b.t */
+ {37,21,rr,V,V,0}, /* eq.h.t */
+ {37,22,rr,V,V,0}, /* eq.w.t */
+ {37,23,rr,V,V,0}, /* eq.l.t */
+ {37,20,rr,S,V,0}, /* eq.b.t */
+ {37,21,rr,S,V,0}, /* eq.h.t */
+ {37,22,rr,S,V,0}, /* eq.w.t */
+ {37,23,rr,S,V,0}, /* eq.l.t */
+ {40,20,rr,V,V,0}, /* le.b.t */
+ {40,21,rr,V,V,0}, /* le.h.t */
+ {40,22,rr,V,V,0}, /* le.w.t */
+ {40,23,rr,V,V,0}, /* le.l.t */
+ {40,20,rr,S,V,0}, /* le.b.t */
+ {40,21,rr,S,V,0}, /* le.h.t */
+ {40,22,rr,S,V,0}, /* le.w.t */
+ {40,23,rr,S,V,0}, /* le.l.t */
+ {41,20,rr,V,V,0}, /* lt.b.t */
+ {41,21,rr,V,V,0}, /* lt.h.t */
+ {41,22,rr,V,V,0}, /* lt.w.t */
+ {41,23,rr,V,V,0}, /* lt.l.t */
+ {41,20,rr,S,V,0}, /* lt.b.t */
+ {41,21,rr,S,V,0}, /* lt.h.t */
+ {41,22,rr,S,V,0}, /* lt.w.t */
+ {41,23,rr,S,V,0}, /* lt.l.t */
+ {43,20,rr,V,V,0}, /* neg.b.t */
+ {43,21,rr,V,V,0}, /* neg.h.t */
+ {43,22,rr,V,V,0}, /* neg.w.t */
+ {43,23,rr,V,V,0}, /* neg.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e1_format4[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e1_format5[] = {
+ {51,20,rr,V,V,0}, /* ldvi.b.t */
+ {51,21,rr,V,V,0}, /* ldvi.h.t */
+ {51,22,rr,V,V,0}, /* ldvi.w.t */
+ {51,23,rr,V,V,0}, /* ldvi.l.t */
+ {28,18,rr,V,V,0}, /* cvtw.s.t */
+ {31,22,rr,V,V,0}, /* cvts.w.t */
+ {28,23,rr,V,V,0}, /* cvtw.l.t */
+ {33,22,rr,V,V,0}, /* cvtl.w.t */
+ {52,20,rxr,V,V,0}, /* stvi.b.t */
+ {52,21,rxr,V,V,0}, /* stvi.h.t */
+ {52,22,rxr,V,V,0}, /* stvi.w.t */
+ {52,23,rxr,V,V,0}, /* stvi.l.t */
+ {52,20,rxr,S,V,0}, /* stvi.b.t */
+ {52,21,rxr,S,V,0}, /* stvi.h.t */
+ {52,22,rxr,S,V,0}, /* stvi.w.t */
+ {52,23,rxr,S,V,0}, /* stvi.l.t */
+};
+struct formstr e1_format6[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+struct formstr e1_format7[] = {
+ {84,20,r,V,0,0}, /* sum.b.t */
+ {84,21,r,V,0,0}, /* sum.h.t */
+ {84,22,r,V,0,0}, /* sum.w.t */
+ {84,23,r,V,0,0}, /* sum.l.t */
+ {85,1,r,V,0,0}, /* all.t */
+ {86,1,r,V,0,0}, /* any.t */
+ {87,1,r,V,0,0}, /* parity.t */
+ {0,0,0,0,0,0},
+ {88,20,r,V,0,0}, /* max.b.t */
+ {88,21,r,V,0,0}, /* max.h.t */
+ {88,22,r,V,0,0}, /* max.w.t */
+ {88,23,r,V,0,0}, /* max.l.t */
+ {89,20,r,V,0,0}, /* min.b.t */
+ {89,21,r,V,0,0}, /* min.h.t */
+ {89,22,r,V,0,0}, /* min.w.t */
+ {89,23,r,V,0,0}, /* min.l.t */
+ {84,18,r,V,0,0}, /* sum.s.t */
+ {84,19,r,V,0,0}, /* sum.d.t */
+ {90,18,r,V,0,0}, /* prod.s.t */
+ {90,19,r,V,0,0}, /* prod.d.t */
+ {88,18,r,V,0,0}, /* max.s.t */
+ {88,19,r,V,0,0}, /* max.d.t */
+ {89,18,r,V,0,0}, /* min.s.t */
+ {89,19,r,V,0,0}, /* min.d.t */
+ {90,20,r,V,0,0}, /* prod.b.t */
+ {90,21,r,V,0,0}, /* prod.h.t */
+ {90,22,r,V,0,0}, /* prod.w.t */
+ {90,23,r,V,0,0}, /* prod.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+char *lop[] = {
+ "mov", /* 0 */
+ "merg", /* 1 */
+ "mask", /* 2 */
+ "mul", /* 3 */
+ "div", /* 4 */
+ "and", /* 5 */
+ "or", /* 6 */
+ "xor", /* 7 */
+ "shf", /* 8 */
+ "add", /* 9 */
+ "sub", /* 10 */
+ "exit", /* 11 */
+ "jmp", /* 12 */
+ "jmpi", /* 13 */
+ "jmpa", /* 14 */
+ "jmps", /* 15 */
+ "tac", /* 16 */
+ "ldea", /* 17 */
+ "ld", /* 18 */
+ "tas", /* 19 */
+ "pshea", /* 20 */
+ "st", /* 21 */
+ "call", /* 22 */
+ "calls", /* 23 */
+ "callq", /* 24 */
+ "pfork", /* 25 */
+ "ste", /* 26 */
+ "incr", /* 27 */
+ "cvtw", /* 28 */
+ "cvtb", /* 29 */
+ "cvth", /* 30 */
+ "cvts", /* 31 */
+ "cvtd", /* 32 */
+ "cvtl", /* 33 */
+ "ldpa", /* 34 */
+ "plc", /* 35 */
+ "tzc", /* 36 */
+ "eq", /* 37 */
+ "leu", /* 38 */
+ "ltu", /* 39 */
+ "le", /* 40 */
+ "lt", /* 41 */
+ "not", /* 42 */
+ "neg", /* 43 */
+ "lop", /* 44 */
+ "cprs", /* 45 */
+ "nop", /* 46 */
+ "br", /* 47 */
+ "bri", /* 48 */
+ "bra", /* 49 */
+ "brs", /* 50 */
+ "ldvi", /* 51 */
+ "stvi", /* 52 */
+ "ldsdr", /* 53 */
+ "ldkdr", /* 54 */
+ "ln", /* 55 */
+ "patu", /* 56 */
+ "pate", /* 57 */
+ "pich", /* 58 */
+ "plch", /* 59 */
+ "idle", /* 60 */
+ "rtnq", /* 61 */
+ "cfork", /* 62 */
+ "rtn", /* 63 */
+ "wfork", /* 64 */
+ "join", /* 65 */
+ "rtnc", /* 66 */
+ "exp", /* 67 */
+ "sin", /* 68 */
+ "cos", /* 69 */
+ "psh", /* 70 */
+ "pop", /* 71 */
+ "eni", /* 72 */
+ "dsi", /* 73 */
+ "bkpt", /* 74 */
+ "msync", /* 75 */
+ "mski", /* 76 */
+ "xmti", /* 77 */
+ "tstvv", /* 78 */
+ "diag", /* 79 */
+ "pbkpt", /* 80 */
+ "sqrt", /* 81 */
+ "casr", /* 82 */
+ "atan", /* 83 */
+ "sum", /* 84 */
+ "all", /* 85 */
+ "any", /* 86 */
+ "parity", /* 87 */
+ "max", /* 88 */
+ "min", /* 89 */
+ "prod", /* 90 */
+ "halt", /* 91 */
+ "sysc", /* 92 */
+ "trap", /* 93 */
+ "tst", /* 94 */
+ "lck", /* 95 */
+ "ulk", /* 96 */
+ "spawn", /* 97 */
+ "ldcmr", /* 98 */
+ "stcmr", /* 99 */
+ "popr", /* 100 */
+ "pshr", /* 101 */
+ "rcvr", /* 102 */
+ "matm", /* 103 */
+ "sndr", /* 104 */
+ "putr", /* 105 */
+ "getr", /* 106 */
+ "matr", /* 107 */
+ "mat", /* 108 */
+ "get", /* 109 */
+ "rcv", /* 110 */
+ "inc", /* 111 */
+ "put", /* 112 */
+ "snd", /* 113 */
+ "enal", /* 114 */
+ "enag", /* 115 */
+ "frint", /* 116 */
+ "xpnd", /* 117 */
+ "ctrsl", /* 118 */
+ "ctrsg", /* 119 */
+ "stop", /* 120 */
+};
+char *rop[] = {
+ "", /* 0 */
+ ".t", /* 1 */
+ ".f", /* 2 */
+ ".s", /* 3 */
+ ".d", /* 4 */
+ ".b", /* 5 */
+ ".h", /* 6 */
+ ".w", /* 7 */
+ ".l", /* 8 */
+ ".x", /* 9 */
+ ".u", /* 10 */
+ ".s.f", /* 11 */
+ ".d.f", /* 12 */
+ ".b.f", /* 13 */
+ ".h.f", /* 14 */
+ ".w.f", /* 15 */
+ ".l.f", /* 16 */
+ ".t.f", /* 17 */
+ ".s.t", /* 18 */
+ ".d.t", /* 19 */
+ ".b.t", /* 20 */
+ ".h.t", /* 21 */
+ ".w.t", /* 22 */
+ ".l.t", /* 23 */
+ ".t.t", /* 24 */
+};
--- /dev/null
+/* Print Convex instructions for GDB, the GNU debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+
+/* reg (fmt_field, inst_field) --
+ the {first,second,third} operand of instruction as fmt_field = [ijk]
+ gets the value of the field from the [ijk] position of the instruction */
+
+#define reg(a,b) ((char (*)[3])(op[fmt->a]))[inst.f0.b]
+
+/* lit (fmt_field) -- field [ijk] is a literal (PSW, VL, eg) */
+
+#define lit(i) op[fmt->i]
+
+/* aj[j] -- name for A register j */
+
+#define aj ((char (*)[3])(op[A]))
+\f
+union inst {
+ struct {
+ unsigned : 7;
+ unsigned i : 3;
+ unsigned j : 3;
+ unsigned k : 3;
+ unsigned : 16;
+ unsigned : 32;
+ } f0;
+ struct {
+ unsigned : 8;
+ unsigned indir : 1;
+ unsigned len : 1;
+ unsigned j : 3;
+ unsigned k : 3;
+ unsigned : 16;
+ unsigned : 32;
+ } f1;
+ unsigned char byte[8];
+ unsigned short half[4];
+ char signed_byte[8];
+ short signed_half[4];
+};
+
+struct opform {
+ int mask; /* opcode mask */
+ int shift; /* opcode align */
+ struct formstr *formstr[3]; /* ST, E0, E1 */
+};
+
+struct formstr {
+ unsigned lop:8, rop:5; /* opcode */
+ unsigned fmt:5; /* inst format */
+ unsigned i:5, j:5, k:2; /* operand formats */
+};
+
+#include "convex-opcode.h"
+
+unsigned char formdecode [] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+struct opform opdecode[] = {
+ 0x7e00, 9, format0, e0_format0, e1_format0,
+ 0x3f00, 8, format1, e0_format1, e1_format1,
+ 0x1fc0, 6, format2, e0_format2, e1_format2,
+ 0x0fc0, 6, format3, e0_format3, e1_format3,
+ 0x0700, 8, format4, e0_format4, e1_format4,
+ 0x03c0, 6, format5, e0_format5, e1_format5,
+ 0x01f8, 3, format6, e0_format6, e1_format6,
+ 0x00f8, 3, format7, e0_format7, e1_format7,
+ 0x0000, 0, formatx, formatx, formatx,
+ 0x0f80, 7, formatx, formatx, formatx,
+ 0x0f80, 7, formatx, formatx, formatx,
+};
+\f
+/* Print the instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ union inst inst;
+ struct formstr *fmt;
+ register int format, op1, pfx;
+ int l;
+
+ read_memory (memaddr, &inst, sizeof inst);
+
+ /* Remove and note prefix, if present */
+
+ pfx = inst.half[0];
+ if ((pfx & 0xfff0) == 0x7ef0)
+ {
+ pfx = ((pfx >> 3) & 1) + 1;
+ *(long long *) &inst = *(long long *) &inst.half[1];
+ }
+ else pfx = 0;
+
+ /* Split opcode into format.op1 and look up in appropriate table */
+
+ format = formdecode[inst.byte[0]];
+ op1 = (inst.half[0] & opdecode[format].mask) >> opdecode[format].shift;
+ if (format == 9)
+ {
+ if (pfx)
+ fmt = formatx;
+ else if (inst.f1.j == 0)
+ fmt = &format1a[op1];
+ else if (inst.f1.j == 1)
+ fmt = &format1b[op1];
+ else
+ fmt = formatx;
+ }
+ else
+ fmt = &opdecode[format].formstr[pfx][op1];
+
+ /* Print it */
+
+ if (fmt->fmt == xxx)
+ {
+ /* noninstruction */
+ fprintf (stream, "0x%04x", pfx ? pfx : inst.half[0]);
+ return 2;
+ }
+
+ if (pfx)
+ pfx = 2;
+
+ fprintf (stream, "%s%s%s", lop[fmt->lop], rop[fmt->rop],
+ &" "[strlen(lop[fmt->lop]) + strlen(rop[fmt->rop])]);
+
+ switch (fmt->fmt)
+ {
+ case rrr: /* three register */
+ fprintf (stream, "%s,%s,%s", reg(i,i), reg(j,j), reg(k,k));
+ return pfx + 2;
+
+ case rr: /* two register */
+ fprintf (stream, "%s,%s", reg(i,j), reg(j,k));
+ return pfx + 2;
+
+ case rxr: /* two register, reversed i and j fields */
+ fprintf (stream, "%s,%s", reg(i,k), reg(j,j));
+ return pfx + 2;
+
+ case r: /* one register */
+ fprintf (stream, "%s", reg(i,k));
+ return pfx + 2;
+
+ case nops: /* no operands */
+ return pfx + 2;
+
+ case nr: /* short immediate, one register */
+ fprintf (stream, "#%d,%s", inst.f0.j, reg(i,k));
+ return pfx + 2;
+
+ case pcrel: /* pc relative */
+ print_address (memaddr + 2 * inst.signed_byte[1], stream);
+ return pfx + 2;
+
+ case lr: /* literal, one register */
+ fprintf (stream, "%s,%s", lit(i), reg(j,k));
+ return pfx + 2;
+
+ case rxl: /* one register, literal */
+ fprintf (stream, "%s,%s", reg(i,k), lit(j));
+ return pfx + 2;
+
+ case rlr: /* register, literal, register */
+ fprintf (stream, "%s,%s,%s", reg(i,j), lit(j), reg(k,k));
+ return pfx + 2;
+
+ case rrl: /* register, register, literal */
+ fprintf (stream, "%s,%s,%s", reg(i,j), reg(j,k), lit(k));
+ return pfx + 2;
+
+ case iml: /* immediate, literal */
+ if (inst.f1.len)
+ {
+ fprintf (stream, "#%#x,%s",
+ (inst.signed_half[1] << 16) + inst.half[2], lit(i));
+ return pfx + 6;
+ }
+ else
+ {
+ fprintf (stream, "#%d,%s", inst.signed_half[1], lit(i));
+ return pfx + 4;
+ }
+
+ case imr: /* immediate, register */
+ if (inst.f1.len)
+ {
+ fprintf (stream, "#%#x,%s",
+ (inst.signed_half[1] << 16) + inst.half[2], reg(i,k));
+ return pfx + 6;
+ }
+ else
+ {
+ fprintf (stream, "#%d,%s", inst.signed_half[1], reg(i,k));
+ return pfx + 4;
+ }
+
+ case a1r: /* memory, register */
+ l = print_effa (inst, stream);
+ fprintf (stream, ",%s", reg(i,k));
+ return pfx + l;
+
+ case a1l: /* memory, literal */
+ l = print_effa (inst, stream);
+ fprintf (stream, ",%s", lit(i));
+ return pfx + l;
+
+ case a2r: /* register, memory */
+ fprintf (stream, "%s,", reg(i,k));
+ return pfx + print_effa (inst, stream);
+
+ case a2l: /* literal, memory */
+ fprintf (stream, "%s,", lit(i));
+ return pfx + print_effa (inst, stream);
+
+ case a3: /* memory */
+ return pfx + print_effa (inst, stream);
+
+ case a4: /* system call */
+ l = 29; goto a4a5;
+ case a5: /* trap */
+ l = 27;
+ a4a5:
+ if (inst.f1.len)
+ {
+ unsigned int m = (inst.signed_half[1] << 16) + inst.half[2];
+ fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
+ return pfx + 6;
+ }
+ else
+ {
+ unsigned int m = inst.signed_half[1];
+ fprintf (stream, "#%d,#%d", m >> l, m & (-1 >> (32-l)));
+ return pfx + 4;
+ }
+ }
+}
+
+
+/* print effective address @nnn(aj), return instruction length */
+
+int print_effa (inst, stream)
+ union inst inst;
+ FILE *stream;
+{
+ int n, l;
+
+ if (inst.f1.len)
+ {
+ n = (inst.signed_half[1] << 16) + inst.half[2];
+ l = 6;
+ }
+ else
+ {
+ n = inst.signed_half[1];
+ l = 4;
+ }
+
+ if (inst.f1.indir)
+ printf ("@");
+
+ if (!inst.f1.j)
+ {
+ print_address (n, stream);
+ return l;
+ }
+
+ fprintf (stream, (n & 0xf0000000) == 0x80000000 ? "%#x(%s)" : "%d(%s)",
+ n, aj[inst.f1.j]);
+
+ return l;
+}
--- /dev/null
+/* Convex stuff for GDB.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <signal.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/pcntl.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "gdbcmd.h"
+
+exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ int n;
+ struct stat st_exec;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end = 0;
+ text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+
+ n_exec = 0;
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+ if (myread (execchan, &filehdr, sizeof filehdr) < 0)
+ perror_with_name (filename);
+
+ if (! IS_SOFF_MAGIC (filehdr.h_magic))
+ error ("%s: not an executable file.", filename);
+
+ if (myread (execchan, &opthdr, filehdr.h_opthdr) <= 0)
+ perror_with_name (filename);
+
+ /* Read through the section headers.
+ For text, data, etc, record an entry in the exec file map.
+ Record text_start and text_end. */
+
+ lseek (execchan, (long) filehdr.h_scnptr, 0);
+
+ for (n = 0; n < filehdr.h_nscns; n++)
+ {
+ if (myread (execchan, &scnhdr, sizeof scnhdr) < 0)
+ perror_with_name (filename);
+
+ if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT
+ && (scnhdr.s_flags & S_TYPMASK) <= S_COMON)
+ {
+ exec_map[n_exec].mem_addr = scnhdr.s_vaddr;
+ exec_map[n_exec].mem_end = scnhdr.s_vaddr + scnhdr.s_size;
+ exec_map[n_exec].file_addr = scnhdr.s_scnptr;
+ exec_map[n_exec].type = scnhdr.s_flags & S_TYPMASK;
+ n_exec++;
+
+ if ((scnhdr.s_flags & S_TYPMASK) == S_TEXT)
+ {
+ text_start = scnhdr.s_vaddr;
+ text_end = scnhdr.s_vaddr + scnhdr.s_size;
+ }
+ }
+ }
+
+ fstat (execchan, &st_exec);
+ exec_mtime = st_exec.st_mtime;
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_filtered ("No exec file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
+
+/* Read data from SOFF exec or core file.
+ Return 0 on success, EIO if address out of bounds. */
+
+int
+xfer_core_file (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ register int n;
+ register int val;
+ int xferchan;
+ char **xferfile;
+ int fileptr;
+ int returnval = 0;
+
+ while (len > 0)
+ {
+ xferfile = 0;
+ xferchan = 0;
+
+ /* Determine which file the next bunch of addresses reside in,
+ and where in the file. Set the file's read/write pointer
+ to point at the proper place for the desired address
+ and set xferfile and xferchan for the correct file.
+ If desired address is nonexistent, leave them zero.
+ i is set to the number of bytes that can be handled
+ along with the next address. */
+
+ i = len;
+
+ for (n = 0; n < n_core; n++)
+ {
+ if (memaddr >= core_map[n].mem_addr && memaddr < core_map[n].mem_end
+ && (core_map[n].thread == -1
+ || core_map[n].thread == inferior_thread))
+ {
+ i = min (len, core_map[n].mem_end - memaddr);
+ fileptr = core_map[n].file_addr + memaddr - core_map[n].mem_addr;
+ if (core_map[n].file_addr)
+ {
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+ break;
+ }
+ else if (core_map[n].mem_addr >= memaddr
+ && core_map[n].mem_addr < memaddr + i)
+ i = core_map[n].mem_addr - memaddr;
+ }
+
+ if (!xferfile)
+ for (n = 0; n < n_exec; n++)
+ {
+ if (memaddr >= exec_map[n].mem_addr
+ && memaddr < exec_map[n].mem_end)
+ {
+ i = min (len, exec_map[n].mem_end - memaddr);
+ fileptr = exec_map[n].file_addr + memaddr
+ - exec_map[n].mem_addr;
+ if (exec_map[n].file_addr)
+ {
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ break;
+ }
+ else if (exec_map[n].mem_addr >= memaddr
+ && exec_map[n].mem_addr < memaddr + i)
+ i = exec_map[n].mem_addr - memaddr;
+ }
+
+ /* Now we know which file to use.
+ Set up its pointer and transfer the data. */
+ if (xferfile)
+ {
+ if (*xferfile == 0)
+ if (xferfile == &execfile)
+ error ("No program file to examine.");
+ else
+ error ("No core dump file or running program to examine.");
+ val = lseek (xferchan, fileptr, 0);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ val = myread (xferchan, myaddr, i);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ }
+ /* If this address is for nonexistent memory,
+ read zeros if reading, or do nothing if writing. */
+ else
+ {
+ bzero (myaddr, i);
+ returnval = EIO;
+ }
+
+ memaddr += i;
+ myaddr += i;
+ len -= i;
+ }
+ return returnval;
+}
+
+
+/* Here from info files command to print an address map. */
+
+print_maps ()
+{
+ struct pmap ptrs[200];
+ int n;
+
+ /* ID strings for core and executable file sections */
+
+ static char *idstr[] =
+ {
+ "0", "text", "data", "tdata", "bss", "tbss",
+ "common", "ttext", "ctx", "tctx", "10", "11", "12",
+ };
+
+ for (n = 0; n < n_core; n++)
+ {
+ core_map[n].which = 0;
+ ptrs[n] = core_map[n];
+ }
+ for (n = 0; n < n_exec; n++)
+ {
+ exec_map[n].which = 1;
+ ptrs[n_core+n] = exec_map[n];
+ }
+
+ qsort (ptrs, n_core + n_exec, sizeof *ptrs, ptr_cmp);
+
+ for (n = 0; n < n_core + n_exec; n++)
+ {
+ struct pmap *p = &ptrs[n];
+ if (n > 0)
+ {
+ if (p->mem_addr < ptrs[n-1].mem_end)
+ p->mem_addr = ptrs[n-1].mem_end;
+ if (p->mem_addr >= p->mem_end)
+ continue;
+ }
+ printf_filtered ("%08x .. %08x %-6s %s\n",
+ p->mem_addr, p->mem_end, idstr[p->type],
+ p->which ? execfile : corefile);
+ }
+}
+
+/* Compare routine to put file sections in order.
+ Sort into increasing order on address, and put core file sections
+ before exec file sections if both files contain the same addresses. */
+
+static ptr_cmp (a, b)
+ struct pmap *a, *b;
+{
+ if (a->mem_addr != b->mem_addr) return a->mem_addr - b->mem_addr;
+ return a->which - b->which;
+}
+\f
+/* Trapped internal variables are used to handle special registers.
+ A trapped i.v. calls a hook here every time it is dereferenced,
+ to provide a new value for the variable, and it calls a hook here
+ when a new value is assigned, to do something with the value.
+
+ The vector registers are $vl, $vs, $vm, $vN, $VN (N in 0..7).
+ The communication registers are $cN, $CN (N in 0..63).
+ They not handled as regular registers because it's expensive to
+ read them, and their size varies, and they have too many names. */
+
+
+/* Return 1 if NAME is a trapped internal variable, else 0. */
+
+int
+is_trapped_internalvar (name)
+ char *name;
+{
+ if ((name[0] == 'c' || name[0] == 'C')
+ && name[1] >= '0' && name[1] <= '9'
+ && (name[2] == '\0'
+ || (name[2] >= '0' && name[2] <= '9'
+ && name[3] == '\0' && name[1] != '0'))
+ && atoi (&name[1]) < 64) return 1;
+
+ if ((name[0] == 'v' || name[0] == 'V')
+ && (((name[1] & -8) == '0' && name[2] == '\0')
+ || !strcmp (name, "vl")
+ || !strcmp (name, "vs")
+ || !strcmp (name, "vm")))
+ return 1;
+ else return 0;
+}
+
+/* Return the value of trapped internal variable VAR */
+
+value
+value_of_trapped_internalvar (var)
+ struct internalvar *var;
+{
+ char *name = var->name;
+ value val;
+ struct type *type;
+ long len = *read_vector_register (VL_REGNUM);
+ if (len <= 0 || len > 128) len = 128;
+
+ if (!strcmp (name, "vl"))
+ {
+ val = value_from_long (builtin_type_int,
+ (LONGEST) *read_vector_register_1 (VL_REGNUM));
+ }
+ else if (!strcmp (name, "vs"))
+ {
+ val = value_from_long (builtin_type_int,
+ (LONGEST) *read_vector_register_1 (VS_REGNUM));
+ }
+ else if (!strcmp (name, "vm"))
+ {
+ long vm[4];
+ long i, *p;
+ bcopy (read_vector_register_1 (VM_REGNUM), vm, sizeof vm);
+ type = vector_type (builtin_type_int, len);
+ val = allocate_value (type);
+ p = (long *) VALUE_CONTENTS (val);
+ for (i = 0; i < len; i++)
+ *p++ = !! (vm[3 - (i >> 5)] & (1 << (i & 037)));
+ }
+ else if (name[0] == 'V')
+ {
+ type = vector_type (builtin_type_long_long, len);
+ val = allocate_value (type);
+ bcopy (read_vector_register_1 (name[1] - '0'),
+ VALUE_CONTENTS (val), TYPE_LENGTH (type));
+ }
+ else if (name[0] == 'v')
+ {
+ long *p1, *p2;
+ type = vector_type (builtin_type_long, len);
+ val = allocate_value (type);
+ p1 = read_vector_register_1 (name[1] - '0');
+ p2 = (long *) VALUE_CONTENTS (val);
+ while (--len >= 0) {p1++; *p2++ = *p1++;}
+ }
+
+ else if (name[0] == 'c')
+ val = value_from_long (builtin_type_int,
+ read_comm_register (atoi (&name[1])));
+ else if (name[0] == 'C')
+ val = value_from_long (builtin_type_long_long,
+ read_comm_register (atoi (&name[1])));
+
+ VALUE_LVAL (val) = lval_internalvar;
+ VALUE_INTERNALVAR (val) = var;
+ return val;
+}
+
+/* Construct the type for a vector register's value --
+ array[LENGTH] of ELEMENT_TYPE. */
+
+static struct type *
+vector_type (element_type, length)
+ struct type *element_type;
+ long length;
+{
+ struct type *type = (struct type *) xmalloc (sizeof (struct type));
+ bzero (type, sizeof type);
+ TYPE_CODE (type) = TYPE_CODE_ARRAY;
+ TYPE_TARGET_TYPE (type) = element_type;
+ TYPE_LENGTH (type) = length * TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+ return type;
+}
+
+/* Handle a new value assigned to a trapped internal variable */
+
+void
+set_trapped_internalvar (var, val, bitpos, bitsize, offset)
+ struct internalvar *var;
+ value val;
+ int bitpos, bitsize, offset;
+{
+ char *name = var->name;
+ long long newval = value_as_long (val);
+
+ if (!strcmp (name, "vl"))
+ write_vector_register (VL_REGNUM, 0, newval);
+ else if (!strcmp (name, "vs"))
+ write_vector_register (VS_REGNUM, 0, newval);
+ else if (name[0] == 'c' || name[0] == 'C')
+ write_comm_register (atoi (&name[1]), newval);
+ else if (!strcmp (name, "vm"))
+ error ("can't assign to $vm");
+ else
+ {
+ offset /= bitsize / 8;
+ write_vector_register (name[1] - '0', offset, newval);
+ }
+}
+
+/* Print an integer value when no format was specified. gdb normally
+ prints these values in decimal, but the the leading 0x80000000 of
+ pointers produces intolerable 10-digit negative numbers.
+ If it looks like an address, print it in hex instead. */
+
+decout (stream, type, val)
+ FILE *stream;
+ struct type *type;
+ LONGEST val;
+{
+ long lv = val;
+
+ switch (output_radix)
+ {
+ case 0:
+ if ((lv == val || (unsigned) lv == val)
+ && ((lv & 0xf0000000) == 0x80000000
+ || ((lv & 0xf0000000) == 0xf0000000 && lv < STACK_END_ADDR)))
+ {
+ fprintf_filtered (stream, "%#x", lv);
+ return;
+ }
+
+ case 10:
+ fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val);
+ return;
+
+ case 8:
+ if (TYPE_LENGTH (type) <= sizeof lv)
+ fprintf_filtered (stream, "%#o", lv);
+ else
+ fprintf_filtered (stream, "%#llo", val);
+ return;
+
+ case 16:
+ if (TYPE_LENGTH (type) <= sizeof lv)
+ fprintf_filtered (stream, "%#x", lv);
+ else
+ fprintf_filtered (stream, "%#llx", val);
+ return;
+ }
+}
+
+/* Change the default output radix to 10 or 16, or set it to 0 (heuristic).
+ This command is mostly obsolete now that the print command allows
+ formats to apply to aggregates, but is still handy occasionally. */
+
+static void
+set_base_command (arg)
+ char *arg;
+{
+ int new_radix;
+
+ if (!arg)
+ output_radix = 0;
+ else
+ {
+ new_radix = atoi (arg);
+ if (new_radix != 10 && new_radix != 16 && new_radix != 8)
+ error ("base must be 8, 10 or 16, or null");
+ else output_radix = new_radix;
+ }
+}
+
+/* Turn pipelining on or off in the inferior. */
+
+static void
+set_pipelining_command (arg)
+ char *arg;
+{
+ if (!arg)
+ {
+ sequential = !sequential;
+ printf_filtered ("%s\n", sequential ? "off" : "on");
+ }
+ else if (!strcmp (arg, "on"))
+ sequential = 0;
+ else if (!strcmp (arg, "off"))
+ sequential = 1;
+ else error ("valid args are `on', to allow instructions to overlap, or\n\
+`off', to prevent it and thereby pinpoint exceptions.");
+}
+
+/* Enable, disable, or force parallel execution in the inferior. */
+
+static void
+set_parallel_command (arg)
+ char *arg;
+{
+ struct rlimit rl;
+ int prevparallel = parallel;
+
+ if (!strncmp (arg, "fixed", strlen (arg)))
+ parallel = 2;
+ else if (!strcmp (arg, "on"))
+ parallel = 1;
+ else if (!strcmp (arg, "off"))
+ parallel = 0;
+ else error ("valid args are `on', to allow multiple threads, or\n\
+`fixed', to force multiple threads, or\n\
+`off', to run with one thread only.");
+
+ if ((prevparallel == 0) != (parallel == 0) && inferior_pid)
+ printf_filtered ("will take effect at next run.\n");
+
+ getrlimit (RLIMIT_CONCUR, &rl);
+ rl.rlim_cur = parallel ? rl.rlim_max : 1;
+ setrlimit (RLIMIT_CONCUR, &rl);
+
+ if (inferior_pid)
+ set_fixed_scheduling (inferior_pid, parallel == 2);
+}
+
+/* Add a new name for an existing command. */
+
+static void
+alias_command (arg)
+ char *arg;
+{
+ static char *aliaserr = "usage is `alias NEW OLD', no args allowed";
+ char *newname = arg;
+ struct cmd_list_element *new, *old;
+
+ if (!arg)
+ error_no_arg ("newname oldname");
+
+ new = lookup_cmd (&arg, cmdlist, "", -1);
+ if (new && !strncmp (newname, new->name, strlen (new->name)))
+ {
+ newname = new->name;
+ if (!(*arg == '-'
+ || (*arg >= 'a' && *arg <= 'z')
+ || (*arg >= 'A' && *arg <= 'Z')
+ || (*arg >= '0' && *arg <= '9')))
+ error (aliaserr);
+ }
+ else
+ {
+ arg = newname;
+ while (*arg == '-'
+ || (*arg >= 'a' && *arg <= 'z')
+ || (*arg >= 'A' && *arg <= 'Z')
+ || (*arg >= '0' && *arg <= '9'))
+ arg++;
+ if (*arg != ' ' && *arg != '\t')
+ error (aliaserr);
+ *arg = '\0';
+ arg++;
+ }
+
+ old = lookup_cmd (&arg, cmdlist, "", 0);
+
+ if (*arg != '\0')
+ error (aliaserr);
+
+ if (new && !strncmp (newname, new->name, strlen (new->name)))
+ {
+ char *tem;
+ if (new->class == (int) class_user || new->class == (int) class_alias)
+ tem = "Redefine command \"%s\"? ";
+ else
+ tem = "Really redefine built-in command \"%s\"? ";
+ if (!query (tem, new->name))
+ error ("Command \"%s\" not redefined.", new->name);
+ }
+
+ add_com (newname, class_alias, old->function, old->doc);
+}
+
+
+
+/* Print the current thread number, and any threads with signals in the
+ queue. */
+
+thread_info ()
+{
+ struct threadpid *p;
+
+ if (have_inferior_p ())
+ {
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+ }
+
+ printf_filtered ("Current thread %d stopped with signal %d.%d (%s).\n",
+ inferior_thread, stop_signal, stop_sigcode,
+ subsig_name (stop_signal, stop_sigcode));
+
+ for (p = signal_stack; p->pid; p--)
+ printf_filtered ("Thread %d stopped with signal %d.%d (%s).\n",
+ p->thread, p->signo, p->subsig,
+ subsig_name (p->signo, p->subsig));
+
+ if (iscrlbit (comm_registers.crctl.lbits.cc, 64+13))
+ printf_filtered ("New thread start pc %#x\n",
+ (long) (comm_registers.crreg.pcpsw >> 32));
+}
+
+/* Return string describing a signal.subcode number */
+
+static char *
+subsig_name (signo, subcode)
+ int signo, subcode;
+{
+ static char *subsig4[] = {
+ "error exit", "privileged instruction", "unknown",
+ "unknown", "undefined opcode",
+ 0};
+ static char *subsig5[] = {0,
+ "breakpoint", "single step", "fork trap", "exec trap", "pfork trap",
+ "join trap", "idle trap", "last thread", "wfork trap",
+ "process breakpoint", "trap instruction",
+ 0};
+ static char *subsig8[] = {0,
+ "int overflow", "int divide check", "float overflow",
+ "float divide check", "float underflow", "reserved operand",
+ "sqrt error", "exp error", "ln error", "sin error", "cos error",
+ 0};
+ static char *subsig10[] = {0,
+ "invalid inward ring address", "invalid outward ring call",
+ "invalid inward ring return", "invalid syscall gate",
+ "invalid rtn frame length", "invalid comm reg address",
+ "invalid trap gate",
+ 0};
+ static char *subsig11[] = {0,
+ "read access denied", "write access denied", "execute access denied",
+ "segment descriptor fault", "page table fault", "data reference fault",
+ "i/o access denied", "levt pte invalid",
+ 0};
+
+ static char **subsig_list[] =
+ {0, 0, 0, 0, subsig4, subsig5, 0, 0, subsig8, 0, subsig10, subsig11, 0};
+
+ int i;
+ char *p = signo < NSIG ? sys_siglist[signo] : "unknown";
+
+ if (signo >= (sizeof subsig_list / sizeof *subsig_list)
+ || !subsig_list[signo])
+ return p;
+ for (i = 1; subsig_list[signo][i]; i++)
+ if (i == subcode)
+ return subsig_list[signo][subcode];
+ return p;
+}
+
+
+/* Print a compact display of thread status, essentially x/i $pc
+ for all active threads. */
+
+static void
+threadstat ()
+{
+ int t;
+
+ for (t = 0; t < n_threads; t++)
+ if (thread_state[t] == PI_TALIVE)
+ {
+ printf_filtered ("%d%c %08x%c %d.%d ", t,
+ (t == inferior_thread ? '*' : ' '), thread_pc[t],
+ (thread_is_in_kernel[t] ? '#' : ' '),
+ thread_signal[t], thread_sigcode[t]);
+ print_insn (thread_pc[t], stdout);
+ printf_filtered ("\n");
+ }
+}
+
+/* Change the current thread to ARG. */
+
+set_thread_command (arg)
+ char *arg;
+{
+ int thread;
+
+ if (!arg)
+ {
+ threadstat ();
+ return;
+ }
+
+ thread = parse_and_eval_address (arg);
+
+ if (thread < 0 || thread > n_threads || thread_state[thread] != PI_TALIVE)
+ error ("no such thread.");
+
+ select_thread (thread);
+
+ stop_pc = read_pc ();
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_sel_frame (1);
+}
+
+/* Here on CONT command; gdb's dispatch address is changed to come here.
+ Set global variable ALL_CONTINUE to tell resume() that it should
+ start up all threads, and that a thread switch will not blow gdb's
+ mind. */
+
+static void
+convex_cont_command (proc_count_exp, from_tty)
+ char *proc_count_exp;
+ int from_tty;
+{
+ all_continue = 1;
+ cont_command (proc_count_exp, from_tty);
+}
+
+/* Here on 1CONT command. Resume only the current thread. */
+
+one_cont_command (proc_count_exp, from_tty)
+ char *proc_count_exp;
+ int from_tty;
+{
+ cont_command (proc_count_exp, from_tty);
+}
+
+/* Print the contents and lock bits of all communication registers,
+ or just register ARG if ARG is a communication register,
+ or the 3-word resource structure in memory at address ARG. */
+
+comm_registers_info (arg)
+ char *arg;
+{
+ int i, regnum;
+
+ if (arg)
+ {
+ if (sscanf (arg, "0x%x", ®num) == 1
+ || sscanf (arg, "%d", ®num) == 1)
+ {
+ if (regnum > 0)
+ regnum &= ~0x8000;
+ }
+ else if (sscanf (arg, "$c%d", ®num) == 1)
+ ;
+ else if (sscanf (arg, "$C%d", ®num) == 1)
+ ;
+ else
+ regnum = parse_and_eval_address (arg);
+
+ if (regnum >= 64)
+ error ("%s: invalid register name.", arg);
+
+ /* if we got a (user) address, examine the resource struct there */
+
+ if (regnum < 0)
+ {
+ static int buf[3];
+ read_memory (regnum, buf, sizeof buf);
+ printf_filtered ("%08x %08x%08x%s\n", regnum, buf[1], buf[2],
+ buf[0] & 0xff ? " locked" : "");
+ return;
+ }
+ }
+
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+
+ for (i = 0; i < 64; i++)
+ if (!arg || i == regnum)
+ printf_filtered ("%2d 0x8%03x %016llx%s\n", i, i,
+ comm_registers.crreg.r4[i],
+ (iscrlbit (comm_registers.crctl.lbits.cc, i)
+ ? " locked" : ""));
+}
+
+/* Print the psw */
+
+static void
+psw_info (arg)
+ char *arg;
+{
+ struct pswbit
+ {
+ int bit;
+ int pos;
+ char *text;
+ };
+
+ static struct pswbit pswbit[] =
+ {
+ { 0x80000000, -1, "A carry" },
+ { 0x40000000, -1, "A integer overflow" },
+ { 0x20000000, -1, "A zero divide" },
+ { 0x10000000, -1, "Integer overflow enable" },
+ { 0x08000000, -1, "Trace" },
+ { 0x06000000, 25, "Frame length" },
+ { 0x01000000, -1, "Sequential" },
+ { 0x00800000, -1, "S carry" },
+ { 0x00400000, -1, "S integer overflow" },
+ { 0x00200000, -1, "S zero divide" },
+ { 0x00100000, -1, "Zero divide enable" },
+ { 0x00080000, -1, "Floating underflow" },
+ { 0x00040000, -1, "Floating overflow" },
+ { 0x00020000, -1, "Floating reserved operand" },
+ { 0x00010000, -1, "Floating zero divide" },
+ { 0x00008000, -1, "Floating error enable" },
+ { 0x00004000, -1, "Floating underflow enable" },
+ { 0x00002000, -1, "IEEE" },
+ { 0x00001000, -1, "Sequential stores" },
+ { 0x00000800, -1, "Intrinsic error" },
+ { 0x00000400, -1, "Intrinsic error enable" },
+ { 0x00000200, -1, "Trace thread creates" },
+ { 0x00000100, -1, "Thread init trap" },
+ { 0x000000e0, 5, "Reserved" },
+ { 0x0000001f, 0, "Intrinsic error code" },
+ {0, 0, 0},
+ };
+
+ long psw;
+ struct pswbit *p;
+
+ if (arg)
+ psw = parse_and_eval_address (arg);
+ else
+ psw = read_register (PS_REGNUM);
+
+ for (p = pswbit; p->bit; p++)
+ {
+ if (p->pos < 0)
+ printf_filtered ("%08x %s %s\n", p->bit,
+ (psw & p->bit) ? "yes" : "no ", p->text);
+ else
+ printf_filtered ("%08x %3d %s\n", p->bit,
+ (psw & p->bit) >> p->pos, p->text);
+ }
+}
+\f
+_initialize_convex_dep ()
+{
+ add_com ("alias", class_support, alias_command,
+ "Add a new name for an existing command.");
+
+ add_cmd ("base", class_vars, set_base_command,
+ "Change the integer output radix to 8, 10 or 16\n\
+or use just `set base' with no args to return to the ad-hoc default,\n\
+which is 16 for integers that look like addresses, 10 otherwise.",
+ &setlist);
+
+ add_cmd ("pipeline", class_run, set_pipelining_command,
+ "Enable or disable overlapped execution of instructions.\n\
+With `set pipe off', exceptions are reported with\n\
+$pc pointing at the instruction after the faulting one.\n\
+The default is `set pipe on', which runs faster.",
+ &setlist);
+
+ add_cmd ("parallel", class_run, set_parallel_command,
+ "Enable or disable multi-threaded execution of parallel code.\n\
+`set parallel off' means run the program on a single CPU.\n\
+`set parallel fixed' means run the program with all CPUs assigned to it.\n\
+`set parallel on' means run the program on any CPUs that are available.",
+ &setlist);
+
+ add_com ("1cont", class_run, one_cont_command,
+ "Continue the program, activating only the current thread.\n\
+Args are the same as the `cont' command.");
+
+ add_com ("thread", class_run, set_thread_command,
+ "Change the current thread, the one under scrutiny and control.\n\
+With no arg, show the active threads, the current one marked with *.");
+
+ add_info ("threads", thread_info,
+ "List status of active threads.");
+
+ add_info ("comm-registers", comm_registers_info,
+ "List communication registers and their contents.\n\
+A communication register name as argument means describe only that register.\n\
+An address as argument means describe the resource structure at that address.\n\
+`Locked' means that the register has been sent to but not yet received from.");
+
+ add_info ("psw", psw_info,
+ "Display $ps, the processor status word, bit by bit.\n\
+An argument means display that value's interpretation as a psw.");
+
+ add_cmd ("convex", no_class, 0, "Convex-specific commands.\n\
+32-bit registers $pc $ps $sp $ap $fp $a1-5 $s0-7 $v0-7 $vl $vs $vm $c0-63\n\
+64-bit registers $S0-7 $V0-7 $C0-63\n\
+\n\
+info threads display info on stopped threads waiting to signal\n\
+thread display list of active threads\n\
+thread N select thread N (its registers, stack, memory, etc.)\n\
+step, next, etc step selected thread only\n\
+1cont continue selected thread only\n\
+cont continue all threads\n\
+info comm-registers display contents of comm register(s) or a resource struct\n\
+info psw display processor status word $ps\n\
+set base N change integer radix used by `print' without a format\n\
+set pipeline off exceptions are precise, $pc points after the faulting insn\n\
+set pipeline on normal mode, $pc is somewhere ahead of faulting insn\n\
+set parallel off program runs on a single CPU\n\
+set parallel fixed all CPUs are assigned to the program\n\
+set parallel on normal mode, parallel execution on random available CPUs\n\
+",
+ &cmdlist);
+
+}
--- /dev/null
+/* Convex stuff for GDB.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "command.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include <signal.h>
+#include <fcntl.h>
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/pcntl.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <convex/vmparam.h>
+#include <convex/filehdr.h>
+#include <convex/opthdr.h>
+#include <convex/scnhdr.h>
+#include <convex/core.h>
+
+/* Per-thread data, read from the inferior at each stop and written
+ back at each resume. */
+
+/* Number of active threads.
+ Tables are valid for thread numbers less than this. */
+
+static int n_threads;
+
+#define MAXTHREADS 8
+
+/* Thread state. The remaining data is valid only if this is PI_TALIVE. */
+
+static int thread_state[MAXTHREADS];
+
+/* Stop pc, signal, signal subcode */
+
+static int thread_pc[MAXTHREADS];
+static int thread_signal[MAXTHREADS];
+static int thread_sigcode[MAXTHREADS];
+
+/* Thread registers.
+ If thread is selected, the regs are in registers[] instead. */
+
+static char thread_regs[MAXTHREADS][REGISTER_BYTES];
+
+/* 1 if the top frame on the thread's stack was a context frame,
+ meaning that the kernel is up to something and we should not
+ touch the thread at all except to resume it. */
+
+static char thread_is_in_kernel[MAXTHREADS];
+
+/* The currently selected thread's number. */
+
+static int inferior_thread;
+
+/* Inferior process's file handle and a process control block
+ to feed args to ioctl with. */
+
+static int inferior_fd;
+static struct pcntl ps;
+
+/* SOFF file headers for exec or core file. */
+
+static FILEHDR filehdr;
+static OPTHDR opthdr;
+static SCNHDR scnhdr;
+
+/* Address maps constructed from section headers of exec and core files.
+ Defines process address -> file address translation. */
+
+struct pmap
+{
+ long mem_addr; /* process start address */
+ long mem_end; /* process end+1 address */
+ long file_addr; /* file start address */
+ long thread; /* -1 shared; 0,1,... thread-local */
+ long type; /* S_TEXT S_DATA S_BSS S_TBSS etc */
+ long which; /* used to sort map for info files */
+};
+
+static int n_exec, n_core;
+static struct pmap exec_map[100];
+static struct pmap core_map[100];
+
+/* Offsets in the core file of core_context and core_tcontext blocks. */
+
+static int context_offset;
+static int tcontext_offset[MAXTHREADS];
+
+/* Core file control blocks. */
+
+static struct core_context_v70 c;
+static struct core_tcontext_v70 tc;
+static struct user u;
+static thread_t th;
+static proc_t pr;
+
+/* The registers of the currently selected thread. */
+
+extern char registers[REGISTER_BYTES];
+
+/* Vector and communication registers from core dump or from inferior.
+ These are read on demand, ie, not normally valid. */
+
+static struct vecst vector_registers;
+static struct creg_ctx comm_registers;
+
+/* Flag, set on a vanilla CONT command and cleared when the inferior
+ is continued. */
+
+static int all_continue;
+
+/* Flag, set when the inferior is continued by a vanilla CONT command,
+ cleared if it is continued for any other purpose. */
+
+static int thread_switch_ok;
+
+/* Stack of signals recieved from threads but not yet delivered to gdb. */
+
+struct threadpid
+{
+ int pid;
+ int thread;
+ int signo;
+ int subsig;
+ int pc;
+};
+
+static struct threadpid signal_stack_bot[100];
+static struct threadpid *signal_stack = signal_stack_bot;
+
+/* How to detect empty stack -- bottom frame is all zero. */
+
+#define signal_stack_is_empty() (signal_stack->pid == 0)
+
+/* Mode controlled by SET PIPE command, controls the psw SEQ bit
+ which forces each instruction to complete before the next one starts. */
+
+static int sequential = 0;
+
+/* Mode controlled by the SET PARALLEL command. Values are:
+ 0 concurrency limit 1 thread, dynamic scheduling
+ 1 no concurrency limit, dynamic scheduling
+ 2 no concurrency limit, fixed scheduling */
+
+static int parallel = 1;
+
+/* Mode controlled by SET BASE command, output radix for unformatted
+ integer typeout, as in argument lists, aggregates, and so on.
+ Zero means guess whether it's an address (hex) or not (decimal). */
+
+static int output_radix = 0;
+
+/* Signal subcode at last thread stop. */
+
+static int stop_sigcode;
+
+/* Hack, see wait() below. */
+
+static int exec_trap_timer;
+
+#include "gdbcmd.h"
+
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+extern int attach_flag;
+
+
+
+static struct type *vector_type ();
+static long *read_vector_register ();
+static long *read_vector_register_1 ();
+static void write_vector_register ();
+static REGISTER_TYPE read_comm_register ();
+static void write_comm_register ();
+static void convex_cont_command ();
+static void thread_continue ();
+static void select_thread ();
+static void scan_stack ();
+static void set_fixed_scheduling ();
+static char *subsig_name ();
+static void psw_info ();
+static sig_noop ();
+static ptr_cmp ();
+
+extern char *sys_siglist[];
+\f
+/* Execute ptrace. Convex V7 replaced ptrace with pattach.
+ Allow ptrace (0) as a no-op. */
+
+int
+call_ptrace (request, pid, procaddr, buf)
+ int request, pid, procaddr, buf;
+{
+ if (request == 0)
+ return;
+ error ("no ptrace");
+}
+
+/* Replacement for system execle routine.
+ Convert it to an equivalent exect, which pattach insists on. */
+
+execle (name, argv)
+ char *name, *argv;
+{
+ char ***envp = (char ***) &argv;
+ while (*envp++) ;
+
+ signal (SIGTRAP, sig_noop);
+ exect (name, &argv, *envp);
+}
+
+/* Stupid handler for stupid trace trap that otherwise causes
+ startup to stupidly hang. */
+
+static sig_noop ()
+{}
+
+/* Read registers from inferior into registers[] array.
+ For convex, they are already there, read in when the inferior stops. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+}
+
+/* Store our register values back into the inferior.
+ For Convex, do this only once, right before resuming inferior. */
+
+store_inferior_registers (regno)
+ int regno;
+{
+}
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR.
+ On failure (cannot read from inferior, usually because address is out
+ of bounds) returns the value of errno. */
+
+int
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ errno = 0;
+ while (len > 0)
+ {
+ /* little-known undocumented max request size */
+ int i = (len < 12288) ? len : 12288;
+
+ lseek (inferior_fd, memaddr, 0);
+ read (inferior_fd, myaddr, i);
+
+ memaddr += i;
+ myaddr += i;
+ len -= i;
+ }
+ if (errno)
+ bzero (myaddr, len);
+ return errno;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ Returns errno on failure (cannot write the inferior) */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ errno = 0;
+ lseek (inferior_fd, memaddr, 0);
+ write (inferior_fd, myaddr, len);
+ return errno;
+}
+
+/* Here from create_inferior when the inferior process has been created
+ and started up. We must do a pattach to grab it for debugging.
+
+ Also, intercept the CONT command by altering its dispatch address. */
+
+create_inferior_hook (pid)
+ int pid;
+{
+ static char cont[] = "cont";
+ static char cont1[] = "c";
+ char *linep = cont;
+ char *linep1 = cont1;
+ char **line = &linep;
+ char **line1 = &linep1;
+ struct cmd_list_element *c;
+
+ c = lookup_cmd (line, cmdlist, "", 0);
+ c->function = convex_cont_command;
+ c = lookup_cmd (line1, cmdlist, "", 0);
+ c->function = convex_cont_command;
+
+ inferior_fd = pattach (pid, O_EXCL);
+ if (inferior_fd < 0)
+ perror_with_name ("pattach");
+ inferior_thread = 0;
+ set_fixed_scheduling (pid, parallel == 2);
+}
+
+/* Attach process PID for debugging. */
+
+attach (pid)
+ int pid;
+{
+ int fd = pattach (pid, O_EXCL);
+ if (fd < 0)
+ perror_with_name ("pattach");
+ attach_flag = 1;
+ /* wait for strange kernel reverberations to go away */
+ sleep (1);
+
+ setpgrp (pid, pid);
+
+ inferior_fd = fd;
+ inferior_thread = 0;
+ return pid;
+}
+
+/* Stop debugging the process whose number is PID
+ and continue it with signal number SIGNAL.
+ SIGNAL = 0 means just continue it. */
+
+void
+detach (signal)
+ int signal;
+{
+ signal_stack = signal_stack_bot;
+ thread_continue (-1, 0, signal);
+ ioctl (inferior_fd, PIXDETACH, &ps);
+ close (inferior_fd);
+ inferior_fd = 0;
+ attach_flag = 0;
+}
+
+/* Kill off the inferior process. */
+
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ioctl (inferior_fd, PIXTERMINATE, 0);
+ wait (0);
+ target_mourn_inferior ();
+}
+
+/* This is used when GDB is exiting. It gives less chance of error.*/
+
+kill_inferior_fast ()
+{
+ if (inferior_pid == 0)
+ return;
+ ioctl (inferior_fd, PIXTERMINATE, 0);
+ wait (0);
+}
+
+/* Read vector register REG, and return a pointer to the value. */
+
+static long *
+read_vector_register (reg)
+ int reg;
+{
+ if (have_inferior_p ())
+ {
+ errno = 0;
+ ps.pi_buffer = (char *) &vector_registers;
+ ps.pi_nbytes = sizeof vector_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDVREGS, &ps);
+ if (errno)
+ bzero (&vector_registers, sizeof vector_registers);
+ }
+ else if (corechan >= 0)
+ {
+ lseek (corechan, tcontext_offset[inferior_thread], 0);
+ if (myread (corechan, &tc, sizeof tc) < 0)
+ perror_with_name (corefile);
+ lseek (corechan, tc.core_thread_p, 0);
+ if (myread (corechan, &th, sizeof th) < 0)
+ perror_with_name (corefile);
+ lseek (corechan, tc.core_vregs_p, 0);
+ if (myread (corechan, &vector_registers, 16*128) < 0)
+ perror_with_name (corefile);
+ vector_registers.vm[0] = th.t_vect_ctx.vc_vm[0];
+ vector_registers.vm[1] = th.t_vect_ctx.vc_vm[1];
+ vector_registers.vls = th.t_vect_ctx.vc_vls;
+ }
+
+ return read_vector_register_1 (reg);
+}
+
+/* Return a pointer to vector register REG, which must already have been
+ fetched from the inferior or core file. */
+
+static long *
+read_vector_register_1 (reg)
+ int reg;
+{
+ switch (reg)
+ {
+ case VM_REGNUM:
+ return (long *) vector_registers.vm;
+ case VS_REGNUM:
+ return (long *) &vector_registers.vls;
+ case VL_REGNUM:
+ return 1 + (long *) &vector_registers.vls;
+ default:
+ return (long *) &vector_registers.vr[reg];
+ }
+}
+
+/* Write vector register REG, element ELEMENT, new value VAL.
+ NB: must use read-modify-write on the entire vector state,
+ since pattach does not do offsetted writes correctly. */
+
+static void
+write_vector_register (reg, element, val)
+ int reg, element;
+ REGISTER_TYPE val;
+{
+ if (have_inferior_p ())
+ {
+ errno = 0;
+ ps.pi_thread = inferior_thread;
+ ps.pi_offset = 0;
+ ps.pi_buffer = (char *) &vector_registers;
+ ps.pi_nbytes = sizeof vector_registers;
+
+ ioctl (inferior_fd, PIXRDVREGS, &ps);
+
+ switch (reg)
+ {
+ case VL_REGNUM:
+ vector_registers.vls =
+ (vector_registers.vls & 0xffffffff00000000LL)
+ + (unsigned long) val;
+ break;
+
+ case VS_REGNUM:
+ vector_registers.vls =
+ (val << 32) + (unsigned long) vector_registers.vls;
+ break;
+
+ default:
+ vector_registers.vr[reg].el[element] = val;
+ break;
+ }
+
+ ioctl (inferior_fd, PIXWRVREGS, &ps);
+
+ if (errno)
+ perror_with_name ("writing vector register");
+ }
+}
+
+/* Return the contents of communication register NUM. */
+
+static REGISTER_TYPE
+read_comm_register (num)
+ int num;
+{
+ if (have_inferior_p ())
+ {
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+ }
+ return comm_registers.crreg.r4[num];
+}
+
+/* Store a new value VAL into communication register NUM.
+ NB: Must use read-modify-write on the whole comm register set
+ since pattach does not do offsetted writes correctly. */
+
+static void
+write_comm_register (num, val)
+ int num;
+ REGISTER_TYPE val;
+{
+ if (have_inferior_p ())
+ {
+ ps.pi_buffer = (char *) &comm_registers;
+ ps.pi_nbytes = sizeof comm_registers;
+ ps.pi_offset = 0;
+ ps.pi_thread = inferior_thread;
+ ioctl (inferior_fd, PIXRDCREGS, &ps);
+ comm_registers.crreg.r4[num] = val;
+ ioctl (inferior_fd, PIXWRCREGS, &ps);
+ }
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+resume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ if (step || signal)
+ thread_continue (inferior_thread, step, signal);
+ else
+ thread_continue (-1, 0, 0);
+}
+
+/* Maybe resume some threads.
+ THREAD is which thread to resume, or -1 to resume them all.
+ STEP and SIGNAL are as in resume.
+
+ Global variable ALL_CONTINUE is set when we are here to do a
+ `cont' command; otherwise we may be doing `finish' or a call or
+ something else that will not tolerate an automatic thread switch.
+
+ If there are stopped threads waiting to deliver signals, and
+ ALL_CONTINUE, do not actually resume anything. gdb will do a wait
+ and see one of the stopped threads in the queue. */
+
+static void
+thread_continue (thread, step, signal)
+ int thread, step, signal;
+{
+ int n;
+
+ /* If we are to continue all threads, but not for the CONTINUE command,
+ pay no attention and continue only the selected thread. */
+
+ if (thread < 0 && ! all_continue)
+ thread = inferior_thread;
+
+ /* If we are not stepping, we have now executed the continue part
+ of a CONTINUE command. */
+
+ if (! step)
+ all_continue = 0;
+
+ /* Allow wait() to switch threads if this is an all-out continue. */
+
+ thread_switch_ok = thread < 0;
+
+ /* If there are threads queued up, don't resume. */
+
+ if (thread_switch_ok && ! signal_stack_is_empty ())
+ return;
+
+ /* OK, do it. */
+
+ for (n = 0; n < n_threads; n++)
+ if (thread_state[n] == PI_TALIVE)
+ {
+ select_thread (n);
+
+ if ((thread < 0 || n == thread) && ! thread_is_in_kernel[n])
+ {
+ /* Blam the trace bits in the stack's saved psws to match
+ the desired step mode. This is required so that
+ single-stepping a return doesn't restore a psw with a
+ clear trace bit and fly away, and conversely,
+ proceeding through a return in a routine that was
+ stepped into doesn't cause a phantom break by restoring
+ a psw with the trace bit set. */
+ scan_stack (PSW_T_BIT, step);
+ scan_stack (PSW_S_BIT, sequential);
+ }
+
+ ps.pi_buffer = registers;
+ ps.pi_nbytes = REGISTER_BYTES;
+ ps.pi_offset = 0;
+ ps.pi_thread = n;
+ if (! thread_is_in_kernel[n])
+ if (ioctl (inferior_fd, PIXWRREGS, &ps))
+ perror_with_name ("PIXWRREGS");
+
+ if (thread < 0 || n == thread)
+ {
+ ps.pi_pc = 1;
+ ps.pi_signo = signal;
+ if (ioctl (inferior_fd, step ? PIXSTEP : PIXCONTINUE, &ps) < 0)
+ perror_with_name ("PIXCONTINUE");
+ }
+ }
+
+ if (ioctl (inferior_fd, PIXRUN, &ps) < 0)
+ perror_with_name ("PIXRUN");
+}
+
+/* Replacement for system wait routine.
+
+ The system wait returns with one or more threads stopped by
+ signals. Put stopped threads on a stack and return them one by
+ one, so that it appears that wait returns one thread at a time.
+
+ Global variable THREAD_SWITCH_OK is set when gdb can tolerate wait
+ returning a new thread. If it is false, then only one thread is
+ running; we will do a real wait, the thread will do something, and
+ we will return that. */
+
+pid_t
+wait (w)
+ union wait *w;
+{
+ int pid;
+
+ if (!w)
+ return wait3 (0, 0, 0);
+
+ /* Do a real wait if we were told to, or if there are no queued threads. */
+
+ if (! thread_switch_ok || signal_stack_is_empty ())
+ {
+ int thread;
+
+ pid = wait3 (w, 0, 0);
+
+ if (!WIFSTOPPED (*w) || pid != inferior_pid)
+ return pid;
+
+ /* The inferior has done something and stopped. Read in all the
+ threads' registers, and queue up any signals that happened. */
+
+ if (ioctl (inferior_fd, PIXGETTHCOUNT, &ps) < 0)
+ perror_with_name ("PIXGETTHCOUNT");
+
+ n_threads = ps.pi_othdcnt;
+ for (thread = 0; thread < n_threads; thread++)
+ {
+ ps.pi_thread = thread;
+ if (ioctl (inferior_fd, PIXGETSUBCODE, &ps) < 0)
+ perror_with_name ("PIXGETSUBCODE");
+ thread_state[thread] = ps.pi_otstate;
+
+ if (ps.pi_otstate == PI_TALIVE)
+ {
+ select_thread (thread);
+ ps.pi_buffer = registers;
+ ps.pi_nbytes = REGISTER_BYTES;
+ ps.pi_offset = 0;
+ ps.pi_thread = thread;
+ if (ioctl (inferior_fd, PIXRDREGS, &ps) < 0)
+ perror_with_name ("PIXRDREGS");
+
+ registers_fetched ();
+
+ thread_pc[thread] = read_pc ();
+ thread_signal[thread] = ps.pi_osigno;
+ thread_sigcode[thread] = ps.pi_osigcode;
+
+ /* If the thread's stack has a context frame
+ on top, something fucked is going on. I do not
+ know what, but do I know this: the only thing you
+ can do with such a thread is continue it. */
+
+ thread_is_in_kernel[thread] =
+ ((read_register (PS_REGNUM) >> 25) & 3) == 0;
+
+ /* Signals push an extended frame and then fault
+ with a ridiculous pc. Pop the frame. */
+
+ if (thread_pc[thread] > STACK_END_ADDR)
+ {
+ POP_FRAME;
+ if (is_break_pc (thread_pc[thread]))
+ thread_pc[thread] = read_pc () - 2;
+ else
+ thread_pc[thread] = read_pc ();
+ write_register (PC_REGNUM, thread_pc[thread]);
+ }
+
+ if (ps.pi_osigno || ps.pi_osigcode)
+ {
+ signal_stack++;
+ signal_stack->pid = pid;
+ signal_stack->thread = thread;
+ signal_stack->signo = thread_signal[thread];
+ signal_stack->subsig = thread_sigcode[thread];
+ signal_stack->pc = thread_pc[thread];
+ }
+
+ /* The following hackery is caused by a unix 7.1 feature:
+ the inferior's fixed scheduling mode is cleared when
+ it execs the shell (since the shell is not a parallel
+ program). So, note the 5.4 trap we get when
+ the shell does its exec, then catch the 5.0 trap
+ that occurs when the debuggee starts, and set fixed
+ scheduling mode properly. */
+
+ if (ps.pi_osigno == 5 && ps.pi_osigcode == 4)
+ exec_trap_timer = 1;
+ else
+ exec_trap_timer--;
+
+ if (ps.pi_osigno == 5 && exec_trap_timer == 0)
+ set_fixed_scheduling (pid, parallel == 2);
+ }
+ }
+
+ if (signal_stack_is_empty ())
+ error ("no active threads?!");
+ }
+
+ /* Select the thread that stopped, and return *w saying why. */
+
+ select_thread (signal_stack->thread);
+
+ stop_signal = signal_stack->signo;
+ stop_sigcode = signal_stack->subsig;
+
+ WSETSTOP (*w, signal_stack->signo);
+ w->w_thread = signal_stack->thread;
+ return (signal_stack--)->pid;
+}
+
+/* Select thread THREAD -- its registers, stack, per-thread memory.
+ This is the only routine that may assign to inferior_thread
+ or thread_regs[]. */
+
+static void
+select_thread (thread)
+ int thread;
+{
+ if (thread == inferior_thread)
+ return;
+
+ bcopy (registers, thread_regs[inferior_thread], REGISTER_BYTES);
+ ps.pi_thread = inferior_thread = thread;
+ if (have_inferior_p ())
+ ioctl (inferior_fd, PISETRWTID, &ps);
+ bcopy (thread_regs[thread], registers, REGISTER_BYTES);
+}
+
+/* Routine to set or clear a psw bit in the psw and also all psws
+ saved on the stack. Quits when we get to a frame in which the
+ saved psw is correct. */
+
+static void
+scan_stack (bit, val)
+ long bit, val;
+{
+ long ps = read_register (PS_REGNUM);
+ long fp;
+ if (val ? !(ps & bit) : (ps & bit))
+ {
+ ps ^= bit;
+ write_register (PS_REGNUM, ps);
+
+ fp = read_register (FP_REGNUM);
+ while (fp & 0x80000000)
+ {
+ ps = read_memory_integer (fp + 4, 4);
+ if (val ? (ps & bit) : !(ps & bit))
+ break;
+ ps ^= bit;
+ write_memory (fp + 4, &ps, 4);
+ fp = read_memory_integer (fp + 8, 4);
+ }
+ }
+}
+
+/* Set fixed scheduling (alliant mode) of process PID to ARG (0 or 1). */
+
+static void
+set_fixed_scheduling (pid, arg)
+ int arg;
+{
+ struct pattributes pattr;
+ getpattr (pid, &pattr);
+ pattr.pattr_pfixed = arg;
+ setpattr (pid, &pattr);
+}
+\f
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int n;
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+ n_core = 0;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+
+ if (myread (corechan, &filehdr, sizeof filehdr) < 0)
+ perror_with_name (filename);
+
+ if (!IS_CORE_SOFF_MAGIC (filehdr.h_magic))
+ error ("%s: not a core file.\n", filename);
+
+ if (myread (corechan, &opthdr, filehdr.h_opthdr) < 0)
+ perror_with_name (filename);
+
+ /* Read through the section headers.
+ For text, data, etc, record an entry in the core file map.
+ For context and tcontext, record the file address of
+ the context blocks. */
+
+ lseek (corechan, (long) filehdr.h_scnptr, 0);
+
+ n_threads = 0;
+ for (n = 0; n < filehdr.h_nscns; n++)
+ {
+ if (myread (corechan, &scnhdr, sizeof scnhdr) < 0)
+ perror_with_name (filename);
+ if ((scnhdr.s_flags & S_TYPMASK) >= S_TEXT
+ && (scnhdr.s_flags & S_TYPMASK) <= S_COMON)
+ {
+ core_map[n_core].mem_addr = scnhdr.s_vaddr;
+ core_map[n_core].mem_end = scnhdr.s_vaddr + scnhdr.s_size;
+ core_map[n_core].file_addr = scnhdr.s_scnptr;
+ core_map[n_core].type = scnhdr.s_flags & S_TYPMASK;
+ if (core_map[n_core].type != S_TBSS
+ && core_map[n_core].type != S_TDATA
+ && core_map[n_core].type != S_TTEXT)
+ core_map[n_core].thread = -1;
+ else if (n_core == 0
+ || core_map[n_core-1].mem_addr != scnhdr.s_vaddr)
+ core_map[n_core].thread = 0;
+ else
+ core_map[n_core].thread = core_map[n_core-1].thread + 1;
+ n_core++;
+ }
+ else if ((scnhdr.s_flags & S_TYPMASK) == S_CONTEXT)
+ context_offset = scnhdr.s_scnptr;
+ else if ((scnhdr.s_flags & S_TYPMASK) == S_TCONTEXT)
+ tcontext_offset[n_threads++] = scnhdr.s_scnptr;
+ }
+
+ /* Read the context block, struct user, struct proc,
+ and the comm regs. */
+
+ lseek (corechan, context_offset, 0);
+ if (myread (corechan, &c, sizeof c) < 0)
+ perror_with_name (filename);
+ lseek (corechan, c.core_user_p, 0);
+ if (myread (corechan, &u, sizeof u) < 0)
+ perror_with_name (filename);
+ lseek (corechan, c.core_proc_p, 0);
+ if (myread (corechan, &pr, sizeof pr) < 0)
+ perror_with_name (filename);
+ comm_registers = pr.p_creg;
+
+ /* Core file apparently is really there. Make it really exist
+ for xfer_core_file so we can do read_memory on it. */
+
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ corefile = concat (current_directory, "/", filename);
+
+ printf_filtered ("Program %s ", u.u_comm);
+
+ /* Read the thread registers and fill in the thread_xxx[] data. */
+
+ for (n = 0; n < n_threads; n++)
+ {
+ select_thread (n);
+
+ lseek (corechan, tcontext_offset[n], 0);
+ if (myread (corechan, &tc, sizeof tc) < 0)
+ perror_with_name (corefile);
+ lseek (corechan, tc.core_thread_p, 0);
+ if (myread (corechan, &th, sizeof th) < 0)
+ perror_with_name (corefile);
+
+ lseek (corechan, tc.core_syscall_context_p, 0);
+ if (myread (corechan, registers, REGISTER_BYTES) < 0)
+ perror_with_name (corefile);
+
+ thread_signal[n] = th.t_cursig;
+ thread_sigcode[n] = th.t_code;
+ thread_state[n] = th.t_state;
+ thread_pc[n] = read_pc ();
+
+ if (thread_pc[n] > STACK_END_ADDR)
+ {
+ POP_FRAME;
+ if (is_break_pc (thread_pc[n]))
+ thread_pc[n] = read_pc () - 2;
+ else
+ thread_pc[n] = read_pc ();
+ write_register (PC_REGNUM, thread_pc[n]);
+ }
+
+ printf_filtered ("thread %d received signal %d, %s\n",
+ n, thread_signal[n],
+ thread_signal[n] < NSIG
+ ? sys_siglist[thread_signal[n]]
+ : "(undocumented)");
+ }
+
+ /* Select an interesting thread -- also-rans died with SIGKILL,
+ so find one that didn't. */
+
+ for (n = 0; n < n_threads; n++)
+ if (thread_signal[n] != 0 && thread_signal[n] != SIGKILL)
+ {
+ select_thread (n);
+ stop_signal = thread_signal[n];
+ stop_sigcode = thread_sigcode[n];
+ break;
+ }
+
+ core_aouthdr.a_magic = 0;
+
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+
+ print_sel_frame (1);
+ }
+ else if (from_tty)
+ printf_filtered ("No core file now.\n");
+}
--- /dev/null
+/* Work with core dump and executable files, for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+
+extern int xfer_memory ();
+extern void child_attach (), child_create_inferior ();
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+extern char *sys_siglist[];
+
+extern char registers[];
+
+/* Hook for `exec_file_command' command to call. */
+
+void (*exec_file_display_hook) () = NULL;
+
+struct section_table *core_sections, *core_sections_end;
+
+/* Binary file diddling handle for the core file. */
+
+bfd *core_bfd = NULL;
+
+/* Forward decl */
+extern struct target_ops core_ops;
+
+\f
+/* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+void
+core_close (quitting)
+ int quitting;
+{
+ if (core_bfd) {
+ free (bfd_get_filename (core_bfd));
+ bfd_close (core_bfd);
+ core_bfd = NULL;
+ }
+}
+
+/* This routine opens and sets up the core file bfd */
+
+void
+core_open (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ char *p;
+ int siggy;
+ struct cleanup *old_chain;
+ char *temp;
+ bfd *temp_bfd;
+ int ontop;
+
+ if (!filename)
+ {
+ error (core_bfd?
+ "No core file specified. (Use `detach' to stop debugging a core file.)"
+ : "No core file specified.");
+ }
+
+ filename = tilde_expand (filename);
+ if (filename[0] != '/') {
+ temp = concat (current_directory, "/", filename);
+ free (filename);
+ filename = temp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+ temp_bfd = bfd_openr (filename, NULL);
+ if (temp_bfd == NULL)
+ {
+ perror_with_name (filename);
+ }
+
+ if (!bfd_check_format (temp_bfd, bfd_core))
+ {
+ bfd_close (temp_bfd);
+ error ("\"%s\" does not appear to be a core dump", filename);
+ }
+
+ /* Looks semi-reasonable. Toss the old core file and work on the new. */
+
+ discard_cleanups (old_chain); /* Don't free filename any more */
+ unpush_target (&core_ops);
+ core_bfd = temp_bfd;
+ old_chain = make_cleanup (core_close, core_bfd);
+
+ validate_files ();
+
+ /* Find the data section */
+ if (build_section_table (core_bfd, &core_sections, &core_sections_end))
+ error ("Can't find sections in `%s': %s", bfd_get_filename(core_bfd),
+ bfd_errmsg (bfd_error));
+
+ ontop = !push_target (&core_ops);
+
+ p = bfd_core_file_failing_command (core_bfd);
+ if (p)
+ printf ("Core file invoked as `%s'.\n", p);
+
+ siggy = bfd_core_file_failing_signal (core_bfd);
+ if (siggy > 0)
+ printf ("Program terminated with signal %d, %s.\n", siggy,
+ siggy < NSIG ? sys_siglist[siggy] : "(undocumented)");
+
+ if (ontop) {
+ /* Fetch all registers from core file */
+ target_fetch_registers (-1);
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ /* FIXME, handle shared library reading here. */
+ print_sel_frame (0); /* Print the top frame and source line */
+ } else {
+ printf (
+"Warning: you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''\n", current_target->to_longname);
+ }
+
+ discard_cleanups (old_chain);
+}
+
+void
+core_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+ if (args)
+ error ("Too many arguments");
+ pop_target ();
+ if (from_tty)
+ printf ("No core file now.\n");
+}
+
+/* Backward compatability with old way of specifying core files. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ if (!filename)
+ core_detach (filename, from_tty);
+ else
+ core_open (filename, from_tty);
+}
+
+\f
+/* Call this to specify the hook for exec_file_command to call back.
+ This is called from the x-window display code. */
+
+void
+specify_exec_file_hook (hook)
+ void (*hook) ();
+{
+ exec_file_display_hook = hook;
+}
+
+/* The exec file must be closed before running an inferior.
+ If it is needed again after the inferior dies, it must
+ be reopened. */
+
+void
+close_exec_file ()
+{
+#ifdef FIXME
+ if (exec_bfd)
+ bfd_tempclose (exec_bfd);
+#endif
+}
+
+void
+reopen_exec_file ()
+{
+#ifdef FIXME
+ if (exec_bfd)
+ bfd_reopen (exec_bfd);
+#endif
+}
+\f
+/* If we have both a core file and an exec file,
+ print a warning if they don't go together.
+ This should really check that the core file came
+ from that exec file, but I don't know how to do it. */
+
+void
+validate_files ()
+{
+ if (exec_bfd && core_bfd)
+ {
+ if (core_file_matches_executable_p (core_bfd, exec_bfd))
+ printf ("Warning: core file does not match specified executable file.\n");
+ else if (bfd_get_mtime(exec_bfd) > bfd_get_mtime(core_bfd))
+ printf ("Warning: exec file is newer than core file.\n");
+ }
+}
+
+/* Return the name of the executable file as a string.
+ ERR nonzero means get error if there is none specified;
+ otherwise return 0 in that case. */
+
+char *
+get_exec_file (err)
+ int err;
+{
+ if (exec_bfd) return bfd_get_filename(exec_bfd);
+ if (!err) return NULL;
+
+ error ("No executable file specified.\n\
+Use the \"file\" or \"exec-file\" command.");
+ return NULL;
+}
+
+static void
+core_files_info ()
+{
+ struct section_table *p;
+
+ printf ("\tCore file `%s'.\n", bfd_get_filename(core_bfd));
+
+ for (p = core_sections; p < core_sections_end; p++)
+ printf("\tcore file from 0x%08x to 0x%08x is %s\n",
+ p->addr, p->endaddr,
+ bfd_section_name (core_bfd, p->sec_ptr));
+}
+\f
+void
+memory_error (status, memaddr)
+ int status;
+ CORE_ADDR memaddr;
+{
+
+ if (status == EIO)
+ {
+ /* Actually, address between memaddr and memaddr + len
+ was out of bounds. */
+ error ("Cannot access memory: address 0x%x out of bounds.", memaddr);
+ }
+ else
+ {
+ if (status >= sys_nerr || status < 0)
+ error ("Error accessing memory address 0x%x: unknown error (%d).",
+ memaddr, status);
+ else
+ error ("Error accessing memory address 0x%x: %s.",
+ memaddr, sys_errlist[status]);
+ }
+}
+
+/* Same as target_read_memory, but report an error if can't read. */
+void
+read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int status;
+ status = target_read_memory (memaddr, myaddr, len);
+ if (status != 0)
+ memory_error (status, memaddr);
+}
+
+/* Same as target_write_memory, but report an error if can't write. */
+void
+write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int status;
+
+ status = target_write_memory (memaddr, myaddr, len);
+ if (status != 0)
+ memory_error (status, memaddr);
+}
+
+/* Read an integer from debugged memory, given address and number of bytes. */
+
+long
+read_memory_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char cbuf;
+ short sbuf;
+ int ibuf;
+ long lbuf;
+
+ if (len == sizeof (char))
+ {
+ read_memory (memaddr, &cbuf, len);
+ return cbuf;
+ }
+ if (len == sizeof (short))
+ {
+ read_memory (memaddr, (char *)&sbuf, len);
+ SWAP_TARGET_AND_HOST (&sbuf, sizeof (short));
+ return sbuf;
+ }
+ if (len == sizeof (int))
+ {
+ read_memory (memaddr, (char *)&ibuf, len);
+ SWAP_TARGET_AND_HOST (&ibuf, sizeof (int));
+ return ibuf;
+ }
+ if (len == sizeof (lbuf))
+ {
+ read_memory (memaddr, (char *)&lbuf, len);
+ SWAP_TARGET_AND_HOST (&lbuf, sizeof (lbuf));
+ return lbuf;
+ }
+ error ("Cannot handle integers of %d bytes.", len);
+ return -1; /* for lint */
+}
+\f
+/* Read or write the core file.
+
+ Args are address within core file, address within gdb address-space,
+ length, and a flag indicating whether to read or write.
+
+ Result is a length:
+
+ 0: We cannot handle this address and length.
+ > 0: We have handled N bytes starting at this address.
+ (If N == length, we did it all.) We might be able
+ to handle more bytes beyond this length, but no
+ promises.
+ < 0: We cannot handle this address, but if somebody
+ else handles (-N) bytes, we can start from there.
+
+ The actual work is done by xfer_memory in exec.c, which we share
+ in common with exec_xfer_memory(). */
+
+static int
+core_xfer_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+ return xfer_memory (memaddr, myaddr, len, write,
+ core_bfd, core_sections, core_sections_end);
+}
+\f
+/* Get the registers out of a core file. This is the machine-
+ independent part. Fetch_core_registers is the machine-dependent
+ part, typically implemented in the xm-file for each architecture. */
+
+static int
+get_core_registers (regno)
+ int regno;
+{
+ sec_ptr reg_sec;
+ unsigned size;
+ char *the_regs;
+
+ reg_sec = bfd_get_section_by_name (core_bfd, ".reg");
+ size = bfd_section_size (core_bfd, reg_sec);
+ the_regs = alloca (size);
+ if (bfd_get_section_contents (core_bfd, reg_sec, the_regs,
+ (unsigned)0, size))
+ {
+ fetch_core_registers (the_regs, size, 0);
+ }
+ else
+ {
+ fprintf (stderr, "Couldn't fetch registers from core file: %s\n",
+ bfd_errmsg (bfd_error));
+ }
+
+ /* Now do it again for the float registers, if they exist. */
+ reg_sec = bfd_get_section_by_name (core_bfd, ".reg2");
+ if (reg_sec) {
+ size = bfd_section_size (core_bfd, reg_sec);
+ the_regs = alloca (size);
+ if (bfd_get_section_contents (core_bfd, reg_sec, the_regs,
+ (unsigned)0, size))
+ {
+ fetch_core_registers (the_regs, size, 2);
+ }
+ else
+ {
+ fprintf (stderr, "Couldn't fetch register set 2 from core file: %s\n",
+ bfd_errmsg (bfd_error));
+ }
+ }
+ registers_fetched();
+ return 0; /* FIXME, what result goes here? */
+}
+\f
+struct target_ops core_ops = {
+ "core", "Local core dump file",
+ core_open, core_close,
+ child_attach, core_detach, 0, 0, /* resume, wait */
+ get_core_registers,
+ 0, 0, 0, 0, /* store_regs, prepare_to_store, conv_to, conv_from */
+ core_xfer_memory, core_files_info,
+ 0, 0, /* core_insert_breakpoint, core_remove_breakpoint, */
+ 0, 0, 0, 0, 0, /* terminal stuff */
+ 0, 0, 0, 0, 0, /* kill, load, add_syms, call fn, lookup sym */
+ child_create_inferior, 0, /* mourn_inferior */
+ core_stratum, 0, /* next */
+ 0, 1, 1, 1, 0, /* all mem, mem, stack, regs, exec */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_core()
+{
+
+ add_com ("core-file", class_files, core_file_command,
+ "Use FILE as core dump for examining memory and registers.\n\
+No arg means have no core file. This command has been superseded by the\n\
+`target core' and `detach' commands.");
+ add_target (&core_ops);
+}
--- /dev/null
+/* Extract registers from a "standard" core file, for GDB.
+ Copyright (C) 1988-1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* core.c is supposed to be the more machine-independent aspects of this;
+ this file is more machine-specific. */
+
+#include "defs.h"
+#include "param.h"
+#include "gdbcore.h"
+
+/* Some of these are needed on various systems, perhaps, to expand
+ REGISTER_U_ADDR appropriately? */
+/* #include <sys/core.h> */
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/user.h>
+
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them. */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+{
+ register int regno;
+ register unsigned int addr;
+ int bad_reg = -1;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ addr = register_addr (regno, core_reg_size);
+ if (addr >= core_reg_size) {
+ if (bad_reg < 0)
+ bad_reg = regno;
+ } else {
+ supply_register (regno, core_reg_sect + addr);
+ }
+ }
+ if (bad_reg > 0)
+ {
+ error ("Register %s not found in core file.", reg_names[bad_reg]);
+ }
+}
+
+
+#ifdef REGISTER_U_ADDR
+
+/* Return the address in the core dump or inferior of register REGNO.
+ BLOCKEND is the address of the end of the user structure. */
+
+unsigned int
+register_addr (regno, blockend)
+ int regno;
+ int blockend;
+{
+ int addr;
+
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+#endif /* REGISTER_U_ADDR */
--- /dev/null
+/* Demangler for GNU C++
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ written by James Clark (jjc@jclark.uucp)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is for g++ 1.36.1 (November 6 version). It will probably
+ require changes for any other version.
+
+ Modified for g++ 1.36.2 (November 18 version). */
+
+/* This file exports one function
+
+ char *cplus_demangle (const char *name, int mode)
+
+ If NAME is a mangled function name produced by GNU C++, then
+ a pointer to a malloced string giving a C++ representation
+ of the name will be returned; otherwise NULL will be returned.
+ It is the caller's responsibility to free the string which
+ is returned.
+
+ If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
+ Otherwise they are not.
+ If MODE >= 0, parameters are emitted; otherwise not.
+
+ For example,
+
+ cplus_demangle ("foo__1Ai", 0) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", 1) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", -1) => "A::foo"
+
+ cplus_demangle ("foo__1Afe", 0) => "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", 1) => "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", -1) => "A::foo"
+
+ This file imports xmalloc and xrealloc, which are like malloc and
+ realloc except that they generate a fatal error if there is no
+ available memory. */
+
+/* define this if names don't start with _ */
+/* #define nounderscore 1 */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef USG
+#include <memory.h>
+#include <string.h>
+#else
+#include <strings.h>
+#define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
+#define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
+#define strchr index
+#define strrchr rindex
+#endif
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifdef __STDC__
+extern char *cplus_demangle (const char *type, int mode);
+#else
+extern char *cplus_demangle ();
+#endif
+
+#ifdef __STDC__
+extern char *xmalloc (int);
+extern char *xrealloc (char *, int);
+extern void free (char *);
+#else
+extern char *xmalloc ();
+extern char *xrealloc ();
+extern void free ();
+#endif
+
+static char **typevec = 0;
+static int ntypes = 0;
+static int typevec_size = 0;
+
+static struct {
+ const char *in;
+ const char *out;
+} optable[] = {
+ "new", " new",
+ "delete", " delete",
+ "ne", "!=",
+ "eq", "==",
+ "ge", ">=",
+ "gt", ">",
+ "le", "<=",
+ "lt", "<",
+ "plus", "+",
+ "minus", "-",
+ "mult", "*",
+ "convert", "+", /* unary + */
+ "negate", "-", /* unary - */
+ "trunc_mod", "%",
+ "trunc_div", "/",
+ "truth_andif", "&&",
+ "truth_orif", "||",
+ "truth_not", "!",
+ "postincrement", "++",
+ "postdecrement", "--",
+ "bit_ior", "|",
+ "bit_xor", "^",
+ "bit_and", "&",
+ "bit_not", "~",
+ "call", "()",
+ "cond", "?:",
+ "alshift", "<<",
+ "arshift", ">>",
+ "component", "->",
+ "indirect", "*",
+ "method_call", "->()",
+ "addr", "&", /* unary & */
+ "array", "[]",
+ "nop", "", /* for operator= */
+};
+
+/* Beware: these aren't '\0' terminated. */
+
+typedef struct {
+ char *b; /* pointer to start of string */
+ char *p; /* pointer after last character */
+ char *e; /* pointer after end of allocated space */
+} string;
+
+#ifdef __STDC__
+static void string_need (string *s, int n);
+static void string_delete (string *s);
+static void string_init (string *s);
+static void string_clear (string *s);
+static int string_empty (string *s);
+static void string_append (string *p, const char *s);
+static void string_appends (string *p, string *s);
+static void string_appendn (string *p, const char *s, int n);
+static void string_prepend (string *p, const char *s);
+#if 0
+static void string_prepends (string *p, string *s);
+#endif
+static void string_prependn (string *p, const char *s, int n);
+static int get_count (const char **type, int *count);
+static int do_args (const char **type, string *decl, int arg_mode);
+static int do_type (const char **type, string *result, int arg_mode);
+static int do_arg (const char **type, string *result, int arg_mode);
+static void munge_function_name (string *name, int arg_mode);
+static void remember_type (const char *type, int len);
+#else
+static void string_need ();
+static void string_delete ();
+static void string_init ();
+static void string_clear ();
+static int string_empty ();
+static void string_append ();
+static void string_appends ();
+static void string_appendn ();
+static void string_prepend ();
+#if 0
+static void string_prepends ();
+#endif
+static void string_prependn ();
+static int get_count ();
+static int do_args ();
+static int do_type ();
+static int do_arg ();
+static int do_args ();
+static void munge_function_name ();
+static void remember_type ();
+#endif
+
+char *
+cplus_demangle (type, arg_mode)
+ const char *type;
+ int arg_mode;
+{
+ string decl;
+ int n;
+ int success = 0;
+ int constructor = 0;
+ int const_flag = 0;
+ int i;
+ const char *p;
+#ifndef LONGERNAMES
+ const char *premangle;
+#endif
+
+# define print_ansi_qualifiers (arg_mode > 0)
+# define print_arg_types (arg_mode >= 0)
+
+ if (type == NULL || *type == '\0')
+ return NULL;
+#ifndef nounderscore
+ if (*type++ != '_')
+ return NULL;
+#endif
+ p = type;
+ while (*p != '\0' && !(*p == '_' && p[1] == '_'))
+ p++;
+ if (*p == '\0')
+ {
+ /* destructor */
+ if (type[0] == '_' && type[1] == '$' && type[2] == '_')
+ {
+ int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
+ char *tem = (char *) xmalloc (n);
+ strcpy (tem, type + 3);
+ strcat (tem, "::~");
+ strcat (tem, type + 3);
+ strcat (tem, "()");
+ return tem;
+ }
+ /* static data member */
+ if (*type != '_' && (p = strchr (type, '$')) != NULL)
+ {
+ int n = strlen (type) + 2;
+ char *tem = (char *) xmalloc (n);
+ memcpy (tem, type, p - type);
+ strcpy (tem + (p - type), "::");
+ strcpy (tem + (p - type) + 2, p + 1);
+ return tem;
+ }
+ /* virtual table "_vt$" */
+ if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
+ {
+ int n = strlen (type + 4) + 14 + 1;
+ char *tem = (char *) xmalloc (n);
+ strcpy (tem, type + 4);
+ strcat (tem, " virtual table");
+ return tem;
+ }
+ return NULL;
+ }
+
+ string_init (&decl);
+
+ if (p == type)
+ {
+ if (!isdigit (p[2]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ constructor = 1;
+ }
+ else
+ {
+ string_appendn (&decl, type, p - type);
+ munge_function_name (&decl, arg_mode);
+ }
+ p += 2;
+
+#ifndef LONGERNAMES
+ premangle = p;
+#endif
+ switch (*p)
+ {
+ case 'C':
+ /* a const member function */
+ if (!isdigit (p[1]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ p += 1;
+ const_flag = 1;
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (strlen (p) < n)
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ if (constructor)
+ {
+ string_appendn (&decl, p, n);
+ string_append (&decl, "::");
+ string_appendn (&decl, p, n);
+ }
+ else
+ {
+ string_prepend (&decl, "::");
+ string_prependn (&decl, p, n);
+ }
+ p += n;
+#ifndef LONGERNAMES
+ remember_type (premangle, p - premangle);
+#endif
+ success = do_args (&p, &decl, arg_mode);
+ if (const_flag && print_arg_types)
+ string_append (&decl, " const");
+ break;
+ case 'F':
+ p += 1;
+ success = do_args (&p, &decl, arg_mode);
+ break;
+ }
+
+ for (i = 0; i < ntypes; i++)
+ if (typevec[i] != NULL)
+ free (typevec[i]);
+ ntypes = 0;
+ if (typevec != NULL)
+ {
+ free ((char *)typevec);
+ typevec = NULL;
+ typevec_size = 0;
+ }
+
+ if (success)
+ {
+ string_appendn (&decl, "", 1);
+ return decl.b;
+ }
+ else
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+}
+
+static int
+get_count (type, count)
+ const char **type;
+ int *count;
+{
+ if (!isdigit (**type))
+ return 0;
+ *count = **type - '0';
+ *type += 1;
+ /* see flush_repeats in cplus-method.c */
+ if (isdigit (**type))
+ {
+ const char *p = *type;
+ int n = *count;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (*p == '_')
+ {
+ *type = p + 1;
+ *count = n;
+ }
+ }
+ return 1;
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (type, result, arg_mode)
+ const char **type;
+ string *result;
+ int arg_mode;
+{
+ int n;
+ int done;
+ int non_empty = 0;
+ int success;
+ string decl;
+ const char *remembered_type;
+
+ string_init (&decl);
+ string_init (result);
+
+ done = 0;
+ success = 1;
+ while (success && !done)
+ {
+ int member;
+ switch (**type)
+ {
+ case 'P':
+ *type += 1;
+ string_prepend (&decl, "*");
+ break;
+
+ case 'R':
+ *type += 1;
+ string_prepend (&decl, "&");
+ break;
+
+ case 'T':
+ *type += 1;
+ if (!get_count (type, &n) || n >= ntypes)
+ success = 0;
+ else
+ {
+ remembered_type = typevec[n];
+ type = &remembered_type;
+ }
+ break;
+
+ case 'F':
+ *type += 1;
+ if (!string_empty (&decl) && decl.b[0] == '*')
+ {
+ string_prepend (&decl, "(");
+ string_append (&decl, ")");
+ }
+ if (!do_args (type, &decl, arg_mode) || **type != '_')
+ success = 0;
+ else
+ *type += 1;
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ int constp = 0;
+ int volatilep = 0;
+
+ member = **type == 'M';
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_append (&decl, ")");
+ string_prepend (&decl, "::");
+ string_prependn (&decl, *type, n);
+ string_prepend (&decl, "(");
+ *type += n;
+ if (member)
+ {
+ if (**type == 'C')
+ {
+ *type += 1;
+ constp = 1;
+ }
+ if (**type == 'V')
+ {
+ *type += 1;
+ volatilep = 1;
+ }
+ if (*(*type)++ != 'F')
+ {
+ success = 0;
+ break;
+ }
+ }
+ if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
+ {
+ success = 0;
+ break;
+ }
+ *type += 1;
+ if (! print_ansi_qualifiers)
+ break;
+ if (constp)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "const");
+ }
+ if (volatilep)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "volatile");
+ }
+ break;
+ }
+
+ case 'C':
+ if ((*type)[1] == 'P')
+ {
+ *type += 1;
+ if (print_ansi_qualifiers)
+ {
+ if (!string_empty (&decl))
+ string_prepend (&decl, " ");
+ string_prepend (&decl, "const");
+ }
+ break;
+ }
+
+ /* fall through */
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ done = 0;
+ non_empty = 0;
+ while (success && !done)
+ {
+ switch (**type)
+ {
+ case 'C':
+ *type += 1;
+ if (print_ansi_qualifiers)
+ {
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "const");
+ }
+ break;
+ case 'U':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "unsigned");
+ break;
+ case 'V':
+ *type += 1;
+ if (print_ansi_qualifiers)
+ {
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "volatile");
+ }
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ if (success)
+ switch (**type)
+ {
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "void");
+ break;
+ case 'x':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long long");
+ break;
+ case 'l':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long");
+ break;
+ case 'i':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "int");
+ break;
+ case 's':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "short");
+ break;
+ case 'c':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "char");
+ break;
+ case 'r':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long double");
+ break;
+ case 'd':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "double");
+ break;
+ case 'f':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "float");
+ break;
+ case 'G':
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ if (non_empty)
+ string_append (result, " ");
+ string_appendn (result, *type, n);
+ *type += n;
+ break;
+ default:
+ success = 0;
+ break;
+ }
+
+ if (success)
+ {
+ if (!string_empty (&decl))
+ {
+ string_append (result, " ");
+ string_appends (result, &decl);
+ }
+ string_delete (&decl);
+ return 1;
+ }
+ else
+ {
+ string_delete (&decl);
+ string_delete (result);
+ return 0;
+ }
+}
+
+/* `result' will be initialised in do_type; it will be freed on failure */
+
+static int
+do_arg (type, result, arg_mode)
+ const char **type;
+ string *result;
+ int arg_mode;
+{
+ const char *start = *type;
+
+ if (!do_type (type, result, arg_mode))
+ return 0;
+ remember_type (start, *type - start);
+ return 1;
+}
+
+static void
+remember_type (start, len)
+ const char *start;
+ int len;
+{
+ char *tem;
+
+ if (ntypes >= typevec_size)
+ {
+ if (typevec_size == 0)
+ {
+ typevec_size = 3;
+ typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
+ }
+ else
+ {
+ typevec_size *= 2;
+ typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
+ }
+ }
+ tem = (char *) xmalloc (len + 1);
+ memcpy (tem, start, len);
+ tem[len] = '\0';
+ typevec[ntypes++] = tem;
+}
+
+/* `decl' must be already initialised, usually non-empty;
+ it won't be freed on failure */
+
+static int
+do_args (type, decl, arg_mode)
+ const char **type;
+ string *decl;
+ int arg_mode;
+{
+ string arg;
+ int need_comma = 0;
+
+ if (print_arg_types)
+ string_append (decl, "(");
+
+ while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
+ {
+ if (**type == 'N')
+ {
+ int r;
+ int t;
+ *type += 1;
+ if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
+ return 0;
+ while (--r >= 0)
+ {
+ const char *tem = typevec[t];
+ if (need_comma && print_arg_types)
+ string_append (decl, ", ");
+ if (!do_arg (&tem, &arg, arg_mode))
+ return 0;
+ if (print_arg_types)
+ string_appends (decl, &arg);
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+ else
+ {
+ if (need_comma & print_arg_types)
+ string_append (decl, ", ");
+ if (!do_arg (type, &arg, arg_mode))
+ return 0;
+ if (print_arg_types)
+ string_appends (decl, &arg);
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+
+ if (**type == 'v')
+ *type += 1;
+ else if (**type == 'e')
+ {
+ *type += 1;
+ if (print_arg_types)
+ {
+ if (need_comma)
+ string_append (decl, ",");
+ string_append (decl, "...");
+ }
+ }
+
+ if (print_arg_types)
+ string_append (decl, ")");
+ return 1;
+}
+
+static void
+munge_function_name (name, arg_mode)
+ string *name;
+ int arg_mode;
+{
+ if (!string_empty (name) && name->p - name->b >= 3
+ && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
+ {
+ int i;
+ /* see if it's an assignment expression */
+ if (name->p - name->b >= 10 /* op$assign_ */
+ && memcmp (name->b + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 10;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 10, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ string_append (name, "=");
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 3;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 3, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ return;
+ }
+ }
+ }
+ return;
+ }
+ else if (!string_empty (name) && name->p - name->b >= 5
+ && memcmp (name->b, "type$", 5) == 0)
+ {
+ /* type conversion operator */
+ string type;
+ const char *tem = name->b + 5;
+ if (do_type (&tem, &type, arg_mode))
+ {
+ string_clear (name);
+ string_append (name, "operator ");
+ string_appends (name, &type);
+ string_delete (&type);
+ return;
+ }
+ }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+ string *s;
+ int n;
+{
+ if (s->b == NULL)
+ {
+ if (n < 32)
+ n = 32;
+ s->p = s->b = (char *) xmalloc (n);
+ s->e = s->b + n;
+ }
+ else if (s->e - s->p < n)
+ {
+ int tem = s->p - s->b;
+ n += tem;
+ n *= 2;
+ s->b = (char *) xrealloc (s->b, n);
+ s->p = s->b + tem;
+ s->e = s->b + n;
+ }
+}
+
+static void
+string_delete (s)
+ string *s;
+{
+ if (s->b != NULL)
+ {
+ free (s->b);
+ s->b = s->e = s->p = NULL;
+ }
+}
+
+static void
+string_init (s)
+ string *s;
+{
+ s->b = s->p = s->e = NULL;
+}
+
+static void
+string_clear (s)
+ string *s;
+{
+ s->p = s->b;
+}
+
+static int
+string_empty (s)
+ string *s;
+{
+ return s->b == s->p;
+}
+
+static void
+string_append (p, s)
+ string *p;
+ const char *s;
+{
+ int n;
+ if (s == NULL || *s == '\0')
+ return;
+ n = strlen (s);
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_appends (p, s)
+ string *p, *s;
+{
+ int n;
+ if (s->b == s->p)
+ return;
+ n = s->p - s->b;
+ string_need (p, n);
+ memcpy (p->p, s->b, n);
+ p->p += n;
+}
+
+static void
+string_appendn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ if (n == 0)
+ return;
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_prepend (p, s)
+ string *p;
+ const char *s;
+{
+ if (s == NULL || *s == '\0')
+ return;
+ string_prependn (p, s, strlen (s));
+}
+
+#if 0
+static void
+string_prepends (p, s)
+ string *p, *s;
+{
+ if (s->b == s->p)
+ return;
+ string_prependn (p, s->b, s->p - s->b);
+}
+#endif
+
+static void
+string_prependn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ char *q;
+
+ if (n == 0)
+ return;
+ string_need (p, n);
+ for (q = p->p - 1; q >= p->b; q--)
+ q[n] = q[0];
+ memcpy (p->b, s, n);
+ p->p += n;
+}
--- /dev/null
+#!/bin/sh
+#
+# Here we check to see if we are compiling in a directory that contains
+# symlinks to the source files instead of the actual files. If this is so,
+# we setup the TAGS entries to point to the actual source directory.
+#
+filelist=""
+if test "`find main.c -type l -print `" != "" ; then
+ prefix=`ls -l main.c | awk '{print $11}' | sed 's;main.c$;;'`
+else
+ prefix=""
+fi
+
+# Replace .o at end of filename with .c
+for i in $@ ; do
+ file=`echo $i-x- | sed -e 's/\.o-x-/\.c-x-/' | sed -e 's/-x-//'`
+ filelist="$filelist $prefix$file"
+done
+
+etags $filelist
--- /dev/null
+altos-xdep.o : altos-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+am29k-pinsn.o : am29k-pinsn.c defs.h target.h am29k-opcode.h
+am29k-tdep.o : am29k-tdep.c defs.h gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h \
+ param.h tm.h config.status param-no-tm.h xm.h config.status value.h symtab.h inferior.h breakpoint.h
+arm-pinsn.o : arm-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ arm-opcode.h
+arm-tdep.o : arm-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h arm-opcode.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+arm-xdep.o : arm-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h arm-opcode.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+blockframe.o : blockframe.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ frame.h gdbcore.h $(INCLUDE_DIR)/bfd.h value.h target.h
+breakpoint.o : breakpoint.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ frame.h breakpoint.h value.h expression.h gdbcore.h $(INCLUDE_DIR)/bfd.h \
+ gdbcmd.h command.h inferior.h target.h
+coffread.o : coffread.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ breakpoint.h value.h $(INCLUDE_DIR)/bfd.h $(BFD_DIR)/libcoff.h symfile.h
+command.o : command.c defs.h command.h symtab.h value.h
+convex-pinsn.o : convex-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ symtab.h convex-opcode.h
+convex-tdep.o : convex-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ command.h symtab.h value.h frame.h inferior.h breakpoint.h \
+ $(INCLUDE_DIR)/wait.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h
+convex-xdep.o : convex-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ command.h symtab.h value.h frame.h inferior.h breakpoint.h \
+ $(INCLUDE_DIR)/wait.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h
+core.o : core.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h inferior.h \
+ breakpoint.h value.h symtab.h command.h $(INCLUDE_DIR)/bfd.h target.h \
+ gdbcore.h
+coredep.o : coredep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+cplus-dem.o : cplus-dem.c
+dbxread.o : dbxread.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ $(INCLUDE_DIR)/a.out.gnu.h $(INCLUDE_DIR)/target.h $(INCLUDE_DIR)/reloc.h \
+ $(INCLUDE_DIR)/stab.gnu.h $(INCLUDE_DIR)/stab.def symtab.h breakpoint.h value.h \
+ command.h target.h gdbcore.h $(INCLUDE_DIR)/bfd.h $(BFD_DIR)/liba.out.h \
+ symfile.h
+environ.o : environ.c environ.h
+eval.o : eval.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h value.h \
+ expression.h target.h
+exec.o : exec.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h inferior.h \
+ breakpoint.h value.h symtab.h target.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+expprint.o : expprint.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ expression.h value.h
+findvar.o : findvar.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ frame.h value.h gdbcore.h $(INCLUDE_DIR)/bfd.h inferior.h breakpoint.h \
+ target.h
+gould-pinsn.o : gould-pinsn.c gdbcore.h $(INCLUDE_DIR)/bfd.h defs.h param.h \
+ tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h np1-opcode.h
+gould-xdep.o : gould-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+hp300hpux-xdep.o : hp300hpux-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ frame.h inferior.h breakpoint.h value.h symtab.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+i386-pinsn.o : i386-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ frame.h inferior.h breakpoint.h value.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+i386-tdep.o : i386-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+i386-xdep.o : i386-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+i960-pinsn.o : i960-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h
+i960-tdep.o : i960-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ value.h frame.h signame.h ieee-float.h
+ieee-float.o : ieee-float.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ ieee-float.h
+infcmd.o : infcmd.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h \
+ inferior.h breakpoint.h value.h environ.h gdbcmd.h command.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h target.h
+inflow.o : inflow.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h command.h signals.h terminal.h \
+ target.h
+infptrace.o : infptrace.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h target.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+infrun.o : infrun.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h \
+ inferior.h breakpoint.h value.h $(INCLUDE_DIR)/wait.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h signame.h command.h terminal.h target.h
+inftarg.o : inftarg.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h target.h $(INCLUDE_DIR)/wait.h \
+ gdbcore.h $(INCLUDE_DIR)/bfd.h ieee-float.h
+m68k-pinsn.o : m68k-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ m68k-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+m68k-tdep.o : m68k-tdep.c defs.h ieee-float.h
+main.o : main.c defs.h gdbcmd.h command.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ symtab.h inferior.h breakpoint.h value.h frame.h signals.h target.h
+mem-break.o : mem-break.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status
+mips-pinsn.o : mips-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ mips-opcode.h
+mips-tdep.o : mips-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcmd.h command.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+mips-xdep.o : mips-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+mipsread.o : mipsread.c param.h tm.h config.status param-no-tm.h xm.h config.status obstack.h defs.h \
+ symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h symfile.h $(INCLUDE_DIR)/intel-coff.h
+news-xdep.o : news-xdep.c
+Onindy.o : ${srcdir}/nindy-share/Onindy.c ${srcdir}/nindy-share/ttycntl.h \
+ ${srcdir}/nindy-share/block_io.h $(INCLUDE_DIR)/wait.h ${srcdir}/nindy-share/env.h \
+ /usr/include/string.h
+nindy.o : ${srcdir}/nindy-share/nindy.c ${srcdir}/nindy-share/ttycntl.h ${srcdir}/nindy-share/block_io.h \
+ $(INCLUDE_DIR)/wait.h ${srcdir}/nindy-share/env.h /usr/include/string.h
+ttybreak.o : ${srcdir}/nindy-share/ttybreak.c ${srcdir}/nindy-share/ttycntl.h
+ttyflush.o : ${srcdir}/nindy-share/ttyflush.c ${srcdir}/nindy-share/ttycntl.h
+nindy-tdep.o : nindy-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ frame.h
+ns32k-pinsn.o : ns32k-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ symtab.h ns32k-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+printcmd.o : printcmd.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ symtab.h value.h expression.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h \
+ command.h target.h
+pyr-pinsn.o : pyr-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ pyr-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+pyr-tdep.o : pyr-tdep.c
+pyr-xdep.o : pyr-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+remote-eb.o : remote-eb.c defs.h tm-29k.h param-no-tm.h xm.h config.status inferior.h \
+ breakpoint.h value.h symtab.h frame.h param.h $(INCLUDE_DIR)/wait.h \
+ terminal.h target.h
+remote-nindy.o : remote-nindy.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ frame.h inferior.h breakpoint.h value.h symtab.h target.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h command.h ieee-float.h $(INCLUDE_DIR)/wait.h \
+ ${srcdir}/nindy-share/ttycntl.h ${srcdir}/nindy-share/demux.h ${srcdir}/nindy-share/env.h \
+ ${srcdir}/nindy-share/stop.h
+remote-vx.o : remote-vx.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h $(INCLUDE_DIR)/wait.h target.h \
+ gdbcore.h $(INCLUDE_DIR)/bfd.h command.h symfile.h ${srcdir}/vx-share/xdr_ptrace.h \
+ ${srcdir}/vx-share/xdr_regs.h ${srcdir}/vx-share/reg.h ${srcdir}/vx-share/xdr_ld.h \
+ ${srcdir}/vx-share/xdr_rdb.h ${srcdir}/vx-share/dbgRpcLib.h
+remote.o : remote.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h target.h $(INCLUDE_DIR)/wait.h \
+ terminal.h
+signame.o : signame.c signame.h
+solib.o : solib.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h command.h
+source.o : source.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ command.h frame.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+sparc-pinsn.o : sparc-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ symtab.h sparc-opcode.h gdbcore.h $(INCLUDE_DIR)/bfd.h /usr/include/string.h \
+ target.h
+sparc-tdep.o : sparc-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h obstack.h signame.h target.h \
+ ieee-float.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+sparc-xdep.o : sparc-xdep.c defs.h tm-sparc.h param-no-tm.h xm.h config.status inferior.h \
+ breakpoint.h value.h symtab.h frame.h param.h target.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+stack.o : stack.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h frame.h \
+ gdbcmd.h command.h value.h gdbcore.h $(INCLUDE_DIR)/bfd.h target.h \
+ breakpoint.h
+sun3-xdep.o : sun3-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status inferior.h \
+ breakpoint.h value.h symtab.h frame.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+sun386-xdep.o : sun386-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ frame.h inferior.h breakpoint.h value.h symtab.h signame.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+symfile.o : symfile.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h target.h value.h symfile.h gdbcmd.h \
+ command.h breakpoint.h
+symmetry-tdep.o : symmetry-tdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ frame.h inferior.h breakpoint.h value.h symtab.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+symmetry-xdep.o : symmetry-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ frame.h inferior.h breakpoint.h value.h symtab.h gdbcore.h \
+ $(INCLUDE_DIR)/bfd.h
+symmisc.o : symmisc.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ breakpoint.h value.h command.h
+symtab.o : symtab.c defs.h symtab.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h target.h value.h symfile.h gdbcmd.h \
+ command.h
+target.o : target.c defs.h target.h gdbcmd.h command.h symtab.h inferior.h \
+ breakpoint.h value.h frame.h param.h tm.h config.status param-no-tm.h xm.h config.status \
+ $(INCLUDE_DIR)/bfd.h symfile.h
+tdesc.o : tdesc.c
+umax-xdep.o : umax-xdep.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status frame.h \
+ inferior.h breakpoint.h value.h symtab.h gdbcore.h $(INCLUDE_DIR)/bfd.h
+utils.o : utils.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status signals.h gdbcmd.h \
+ command.h terminal.h $(INCLUDE_DIR)/bfd.h target.h
+valarith.o : valarith.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status value.h \
+ symtab.h expression.h target.h
+valops.o : valops.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h value.h \
+ frame.h inferior.h breakpoint.h gdbcore.h $(INCLUDE_DIR)/bfd.h target.h
+valprint.o : valprint.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ value.h gdbcore.h $(INCLUDE_DIR)/bfd.h gdbcmd.h command.h target.h obstack.h
+values.o : values.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h value.h \
+ gdbcore.h $(INCLUDE_DIR)/bfd.h frame.h command.h
+vax-pinsn.o : vax-pinsn.c defs.h param.h tm.h config.status param-no-tm.h xm.h config.status symtab.h \
+ vax-opcode.h
+xdr_ld.o : ${srcdir}/vx-share/xdr_ld.c ${srcdir}/vx-share/vxWorks.h ${srcdir}/vx-share/vxTypes.h \
+ /usr/include/rpc/rpc.h ${srcdir}/vx-share/xdr_ld.h
+xdr_ptrace.o : ${srcdir}/vx-share/xdr_ptrace.c
+xdr_rdb.o : ${srcdir}/vx-share/xdr_rdb.c ${srcdir}/vx-share/vxWorks.h ${srcdir}/vx-share/vxTypes.h \
+ ${srcdir}/vx-share/xdr_rdb.h
+xdr_regs.o : ${srcdir}/vx-share/xdr_regs.c
--- /dev/null
+
+/* A Bison parser, made from ../expread.y */
+
+#define INT 258
+#define CHAR 259
+#define UINT 260
+#define FLOAT 261
+#define STRING 262
+#define NAME 263
+#define BLOCKNAME 264
+#define TYPENAME 265
+#define NAME_OR_INT 266
+#define NAME_OR_UINT 267
+#define STRUCT 268
+#define UNION 269
+#define ENUM 270
+#define SIZEOF 271
+#define UNSIGNED 272
+#define COLONCOLON 273
+#define ERROR 274
+#define SIGNED 275
+#define LONG 276
+#define SHORT 277
+#define INT_KEYWORD 278
+#define LAST 279
+#define REGNAME 280
+#define VARIABLE 281
+#define ASSIGN_MODIFY 282
+#define THIS 283
+#define ABOVE_COMMA 284
+#define OR 285
+#define AND 286
+#define EQUAL 287
+#define NOTEQUAL 288
+#define LEQ 289
+#define GEQ 290
+#define LSH 291
+#define RSH 292
+#define UNARY 293
+#define INCREMENT 294
+#define DECREMENT 295
+#define ARROW 296
+
+#line 29 "../expread.y"
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "expression.h"
+#include "value.h"
+#include "command.h"
+
+static struct expression *expout;
+static int expout_size;
+static int expout_ptr;
+
+static int yylex ();
+static void yyerror ();
+static void write_exp_elt ();
+static void write_exp_elt_opcode ();
+static void write_exp_elt_sym ();
+static void write_exp_elt_longcst ();
+static void write_exp_elt_dblcst ();
+static void write_exp_elt_type ();
+static void write_exp_elt_intern ();
+static void write_exp_string ();
+static void start_arglist ();
+static int end_arglist ();
+static void free_funcalls ();
+static char *copy_name ();
+static int parse_number ();
+
+/* If this is nonzero, this block is used as the lexical context
+ for symbol names. */
+
+static struct block *expression_context_block;
+
+/* The innermost context required by the stack and register variables
+ we've encountered so far. */
+struct block *innermost_block;
+
+/* The block in which the most recently discovered symbol was found. */
+struct block *block_found;
+
+/* Number of arguments seen so far in innermost function call. */
+static int arglist_len;
+
+/* Data structure for saving values of arglist_len
+ for function calls whose arguments contain other function calls. */
+
+struct funcall
+ {
+ struct funcall *next;
+ int arglist_len;
+ };
+
+struct funcall *funcall_chain;
+
+/* This kind of datum is used to represent the name
+ of a symbol token. */
+
+struct stoken
+ {
+ char *ptr;
+ int length;
+ };
+
+struct ttype
+ {
+ struct stoken stoken;
+ struct type *type;
+ };
+
+struct symtoken
+ {
+ struct stoken stoken;
+ struct symbol *sym;
+ int is_a_field_of_this;
+ };
+
+/* For parsing of complicated types.
+ An array should be preceded in the list by the size of the array. */
+enum type_pieces
+ {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function};
+static enum type_pieces *type_stack;
+static int type_stack_depth, type_stack_size;
+
+static void push_type ();
+static enum type_pieces pop_type ();
+
+/* Allow debugging of parsing. */
+#define YYDEBUG 1
+
+#line 125 "../expread.y"
+typedef union
+ {
+ LONGEST lval;
+ unsigned LONGEST ulval;
+ double dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ } YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __STDC__
+#define const
+#endif
+
+
+
+#define YYFINAL 189
+#define YYFLAG -32768
+#define YYNTBASE 66
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 296 ? yytranslate[x] : 84)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 59, 2, 2, 2, 51, 37, 2, 58,
+ 62, 49, 47, 29, 48, 56, 50, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 65, 2, 40,
+ 31, 41, 32, 46, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 57, 2, 61, 36, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 63, 35, 64, 60, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 30, 33, 34, 38, 39, 42, 43,
+ 44, 45, 52, 53, 54, 55
+};
+
+static const short yyrline[] = { 0,
+ 218, 222, 223, 228, 231, 234, 238, 242, 246, 250,
+ 254, 258, 262, 266, 272, 276, 282, 286, 290, 294,
+ 300, 303, 307, 311, 317, 323, 329, 333, 337, 341,
+ 345, 349, 353, 357, 361, 365, 369, 373, 377, 381,
+ 385, 389, 393, 397, 401, 405, 409, 413, 419, 429,
+ 442, 454, 467, 474, 481, 484, 490, 496, 502, 509,
+ 516, 523, 540, 550, 562, 575, 621, 695, 696, 731,
+ 733, 735, 738, 740, 745, 751, 753, 757, 759, 763,
+ 767, 768, 770, 772, 775, 782, 784, 786, 788, 790,
+ 792, 794, 796, 798, 801, 804, 807, 809, 811, 813,
+ 817, 818, 824, 830, 839, 844, 851, 852, 853, 854,
+ 855, 858, 859, 860, 861
+};
+
+static const char * const yytname[] = { 0,
+"error","$illegal.","INT","CHAR","UINT","FLOAT","STRING","NAME","BLOCKNAME","TYPENAME",
+"NAME_OR_INT","NAME_OR_UINT","STRUCT","UNION","ENUM","SIZEOF","UNSIGNED","COLONCOLON","ERROR","SIGNED",
+"LONG","SHORT","INT_KEYWORD","LAST","REGNAME","VARIABLE","ASSIGN_MODIFY","THIS","','","ABOVE_COMMA",
+"'='","'?'","OR","AND","'|'","'^'","'&'","EQUAL","NOTEQUAL","'<'",
+"'>'","LEQ","GEQ","LSH","RSH","'@'","'+'","'-'","'*'","'/'",
+"'%'","UNARY","INCREMENT","DECREMENT","ARROW","'.'","'['","'('","'!'","'~'",
+"']'","')'","'{'","'}'","':'","start"
+};
+
+static const short yyr1[] = { 0,
+ 66, 67, 67, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 69, 68,
+ 70, 70, 70, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 71, 71, 72, 72, 72, 72, 73, 73, 74,
+ 74, 74, 75, 75, 75, 75, 75, 76, 76, 77,
+ 78, 78, 78, 78, 78, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
+ 80, 80, 80, 80, 81, 81, 82, 82, 82, 82,
+ 82, 83, 83, 83, 83
+};
+
+static const short yyr2[] = { 0,
+ 1, 1, 3, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 3, 4, 3, 4, 4, 0, 5,
+ 0, 1, 3, 4, 4, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 5, 3, 3, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 4, 1,
+ 1, 1, 3, 3, 3, 2, 1, 1, 2, 1,
+ 2, 1, 3, 2, 1, 2, 1, 2, 3, 2,
+ 1, 3, 6, 8, 9, 1, 1, 1, 1, 2,
+ 3, 2, 3, 2, 2, 2, 2, 1, 2, 1,
+ 1, 1, 1, 1, 1, 3, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+};
+
+static const short yydefact[] = { 0,
+ 49, 53, 51, 54, 60, 112, 113, 86, 50, 52,
+ 0, 0, 0, 0, 98, 0, 100, 88, 89, 87,
+ 56, 57, 58, 61, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 2, 0, 55, 0, 67, 107,
+ 108, 109, 110, 111, 94, 95, 96, 0, 13, 101,
+ 103, 104, 102, 97, 66, 103, 104, 99, 90, 92,
+ 5, 6, 4, 9, 10, 0, 81, 0, 68, 7,
+ 8, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 11, 12, 0, 0,
+ 0, 19, 0, 0, 0, 91, 93, 26, 0, 0,
+ 0, 70, 0, 0, 69, 72, 75, 77, 0, 0,
+ 3, 48, 47, 0, 45, 44, 43, 42, 41, 35,
+ 36, 39, 40, 37, 38, 33, 34, 27, 31, 32,
+ 28, 29, 30, 0, 14, 0, 16, 0, 21, 64,
+ 65, 59, 0, 25, 82, 71, 0, 78, 80, 0,
+ 0, 74, 76, 24, 0, 15, 17, 18, 22, 0,
+ 0, 79, 73, 46, 0, 20, 0, 23, 83, 0,
+ 84, 105, 0, 0, 85, 106, 0, 0, 0
+};
+
+static const short yydefgoto[] = { 187,
+ 66, 35, 149, 170, 36, 37, 67, 115, 116, 117,
+ 118, 68, 38, 54, 183, 151, 39
+};
+
+static const short yypact[] = { 159,
+-32768,-32768,-32768,-32768,-32768,-32768, -13,-32768,-32768,-32768,
+ 21, 21, 21, 220, 121, 21, 124, -15, 3,-32768,
+-32768,-32768,-32768,-32768, 159, 159, 159, 159, 159, 159,
+ 159, 159, 272, 80, 306, 32,-32768, 99,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768, 159, 508,-32768,
+ 100, 101,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ 508, 508, 508, 508, 508, -4,-32768, -52, 79, 508,
+ 508, -55, 92, 159, 159, 159, 159, 159, 159, 159,
+ 159, 159, 159, 159, 159, 159, 159, 159, 159, 159,
+ 159, 159, 159, 159, 159, 159,-32768,-32768, 90, 104,
+ 159,-32768, 21, 21, -35,-32768,-32768,-32768, 272, 159,
+ 110, 157, 25, 209,-32768, 30,-32768,-32768, 159, 84,
+ 306, 306, 306, 271, 358, 382, 405, 427, 448, 467,
+ 467, 144, 144, 144, 144, 480, 480, 492, 502, 502,
+ 508, 508, 508, 159,-32768, 159,-32768, 66, 159, 111,
+-32768, 31, 122, 508,-32768,-32768, 94,-32768,-32768, 95,
+ 98,-32768,-32768, 508, 159, 508, 508,-32768, 306, 63,
+ 107,-32768,-32768, 333, 159,-32768, 116, 306, 128, 239,
+-32768, 145, 64, 272,-32768, 145, 204, 205,-32768
+};
+
+static const short yypgoto[] = {-32768,
+ 2, -14,-32768,-32768,-32768,-32768,-32768, -8,-32768, 93,
+ 105, -32, -26, 193,-32768, 8,-32768
+};
+
+
+#define YYLAST 566
+
+
+static const short yytable[] = { 49,
+ 72, 34, 109, 69, -62, 109, 73, 59, 119, 110,
+ 61, 62, 63, 64, 65, 105, 70, 71, 45, 46,
+ 47, 69, 109, 55, 74, 60, 152, 157, 40, 41,
+ 42, 43, 44, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 103,
+ 17, 18, 19, 20, 21, 22, 23, 108, 24, 121,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 153, 28, 29, 158, 113, 161, 30, 31,
+ 32, 175, 184, 33, 74, 154, 111, 40, 41, 42,
+ 43, 44, 148, 156, 164, 160, 145, 147, 74, 120,
+ 150, 40, 41, 42, 43, 44, 104, 40, 41, 42,
+ 43, 44, 106, 107, 176, 185, 168, 112, -63, 166,
+ 50, 167, 155, 50, 169, 113, 114, 154, 144, 171,
+ 112, 51, 52, 53, 56, 57, 53, 182, 113, 114,
+ 174, 186, 146, 73, 172, 177, 173, 73, 155, 159,
+ 178, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 179, 17, 18,
+ 19, 20, 21, 22, 23, 180, 24, 89, 90, 91,
+ 92, 93, 94, 95, 96, 25, 97, 98, 99, 100,
+ 101, 102, 109, 188, 189, 112, 26, 27, 162, 58,
+ 0, 28, 29, 113, 114, 0, 30, 31, 32, 0,
+ 163, 33, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 0, 17,
+ 18, 19, 20, 21, 22, 23, 0, 24, 8, 0,
+ 0, 11, 12, 13, 0, 15, 25, 112, 17, 18,
+ 19, 20, 0, 0, 0, 113, 114, 26, 27, 0,
+ 159, 0, 28, 29, 0, 0, 0, 48, 31, 32,
+ 0, 8, 33, 0, 11, 12, 13, 0, 15, 0,
+ 0, 17, 18, 19, 20, 0, 0, 75, 0, 0,
+ 181, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 0, 97, 98, 99, 100, 101, 102, 0,
+ 0, 0, 75, 0, 0, 165, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 0, 97, 98,
+ 99, 100, 101, 102, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 0, 97, 98, 99, 100, 101,
+ 102, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 0,
+ 97, 98, 99, 100, 101, 102, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 0, 97, 98, 99, 100, 101, 102,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 0, 97, 98, 99,
+ 100, 101, 102, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 0, 97,
+ 98, 99, 100, 101, 102, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95, 96, 0,
+ 97, 98, 99, 100, 101, 102, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 0, 97,
+ 98, 99, 100, 101, 102, 91, 92, 93, 94, 95,
+ 96, 0, 97, 98, 99, 100, 101, 102, 92, 93,
+ 94, 95, 96, 0, 97, 98, 99, 100, 101, 102,
+ 94, 95, 96, 0, 97, 98, 99, 100, 101, 102,
+ 97, 98, 99, 100, 101, 102
+};
+
+static const short yycheck[] = { 14,
+ 33, 0, 58, 30, 18, 58, 33, 23, 64, 62,
+ 25, 26, 27, 28, 29, 48, 31, 32, 11, 12,
+ 13, 48, 58, 16, 29, 23, 62, 3, 8, 9,
+ 10, 11, 12, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 18,
+ 20, 21, 22, 23, 24, 25, 26, 62, 28, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 109, 53, 54, 61, 57, 58, 58, 59,
+ 60, 29, 29, 63, 29, 110, 18, 8, 9, 10,
+ 11, 12, 101, 112, 119, 114, 99, 100, 29, 18,
+ 103, 8, 9, 10, 11, 12, 18, 8, 9, 10,
+ 11, 12, 23, 23, 62, 62, 61, 49, 18, 144,
+ 10, 146, 49, 10, 149, 57, 58, 152, 49, 18,
+ 49, 21, 22, 23, 21, 22, 23, 180, 57, 58,
+ 165, 184, 49, 180, 61, 49, 62, 184, 49, 62,
+ 175, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 62, 20, 21,
+ 22, 23, 24, 25, 26, 58, 28, 44, 45, 46,
+ 47, 48, 49, 50, 51, 37, 53, 54, 55, 56,
+ 57, 58, 58, 0, 0, 49, 48, 49, 116, 17,
+ -1, 53, 54, 57, 58, -1, 58, 59, 60, -1,
+ 116, 63, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, -1, 20,
+ 21, 22, 23, 24, 25, 26, -1, 28, 10, -1,
+ -1, 13, 14, 15, -1, 17, 37, 49, 20, 21,
+ 22, 23, -1, -1, -1, 57, 58, 48, 49, -1,
+ 62, -1, 53, 54, -1, -1, -1, 58, 59, 60,
+ -1, 10, 63, -1, 13, 14, 15, -1, 17, -1,
+ -1, 20, 21, 22, 23, -1, -1, 27, -1, -1,
+ 62, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, -1, 53, 54, 55, 56, 57, 58, -1,
+ -1, -1, 27, -1, -1, 65, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, -1, 53, 54,
+ 55, 56, 57, 58, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, -1, 53, 54, 55, 56, 57,
+ 58, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, -1,
+ 53, 54, 55, 56, 57, 58, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, -1, 53, 54, 55, 56, 57, 58,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, -1, 53, 54, 55,
+ 56, 57, 58, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, -1, 53,
+ 54, 55, 56, 57, 58, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, -1,
+ 53, 54, 55, 56, 57, 58, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, -1, 53,
+ 54, 55, 56, 57, 58, 46, 47, 48, 49, 50,
+ 51, -1, 53, 54, 55, 56, 57, 58, 47, 48,
+ 49, 50, 51, -1, 53, 54, 55, 56, 57, 58,
+ 49, 50, 51, -1, 53, 54, 55, 56, 57, 58,
+ 53, 54, 55, 56, 57, 58
+};
+#define YYPURE 1
+
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "bison.simple"
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984 Bob Corbett and Richard Stallman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
+#include <alloca.h>
+#endif
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYFAIL goto yyerrlab;
+#define YYACCEPT return(0)
+#define YYABORT return(1)
+#define YYERROR goto yyerrlab
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYIMPURE
+#define YYLEX yylex()
+#endif
+
+#ifndef YYPURE
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYIMPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+
+int yynerrs; /* number of parse errors so far */
+#endif /* YYIMPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYMAXDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 200
+#endif
+
+/* YYMAXLIMIT is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#ifndef YYMAXLIMIT
+#define YYMAXLIMIT 10000
+#endif
+
+
+#line 90 "bison.simple"
+int
+yyparse()
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYMAXDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYMAXDEPTH]; /* the semantic value stack */
+ YYLTYPE yylsa[YYMAXDEPTH]; /* the location stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+ YYLTYPE *yyls = yylsa;
+
+ int yymaxdepth = YYMAXDEPTH;
+
+#ifndef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ YYLTYPE yylloc;
+ int yynerrs;
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+ yylsp = yyls;
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yymaxdepth - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ YYLTYPE *yyls1 = yyls;
+ short *yyss1 = yyss;
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yymaxdepth);
+
+ yyss = yyss1; yyvs = yyvs1; yyls = yyls1;
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yymaxdepth >= YYMAXLIMIT)
+ yyerror("parser stack overflow");
+ yymaxdepth *= 2;
+ if (yymaxdepth > YYMAXLIMIT)
+ yymaxdepth = YYMAXLIMIT;
+ yyss = (short *) alloca (yymaxdepth * sizeof (*yyssp));
+ bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+ yyvs = (YYSTYPE *) alloca (yymaxdepth * sizeof (*yyvsp));
+ bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) alloca (yymaxdepth * sizeof (*yylsp));
+ bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yymaxdepth);
+#endif
+
+ if (yyssp >= yyss + yymaxdepth - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+yyresume:
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Next token is %d (%s)\n", yychar, yytname[yychar1]);
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ if (yylen == 1)
+ fprintf (stderr, "Reducing 1 value via line %d, ",
+ yyrline[yyn]);
+ else
+ fprintf (stderr, "Reducing %d values via line %d, ",
+ yylen, yyrline[yyn]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 3:
+#line 224 "../expread.y"
+{ write_exp_elt_opcode (BINOP_COMMA); ;
+ break;}
+case 4:
+#line 229 "../expread.y"
+{ write_exp_elt_opcode (UNOP_IND); ;
+ break;}
+case 5:
+#line 232 "../expread.y"
+{ write_exp_elt_opcode (UNOP_ADDR); ;
+ break;}
+case 6:
+#line 235 "../expread.y"
+{ write_exp_elt_opcode (UNOP_NEG); ;
+ break;}
+case 7:
+#line 239 "../expread.y"
+{ write_exp_elt_opcode (UNOP_ZEROP); ;
+ break;}
+case 8:
+#line 243 "../expread.y"
+{ write_exp_elt_opcode (UNOP_LOGNOT); ;
+ break;}
+case 9:
+#line 247 "../expread.y"
+{ write_exp_elt_opcode (UNOP_PREINCREMENT); ;
+ break;}
+case 10:
+#line 251 "../expread.y"
+{ write_exp_elt_opcode (UNOP_PREDECREMENT); ;
+ break;}
+case 11:
+#line 255 "../expread.y"
+{ write_exp_elt_opcode (UNOP_POSTINCREMENT); ;
+ break;}
+case 12:
+#line 259 "../expread.y"
+{ write_exp_elt_opcode (UNOP_POSTDECREMENT); ;
+ break;}
+case 13:
+#line 263 "../expread.y"
+{ write_exp_elt_opcode (UNOP_SIZEOF); ;
+ break;}
+case 14:
+#line 267 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (STRUCTOP_PTR); ;
+ break;}
+case 15:
+#line 273 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_MPTR); ;
+ break;}
+case 16:
+#line 277 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); ;
+ break;}
+case 17:
+#line 283 "../expread.y"
+{ write_exp_elt_opcode (STRUCTOP_MEMBER); ;
+ break;}
+case 18:
+#line 287 "../expread.y"
+{ write_exp_elt_opcode (BINOP_SUBSCRIPT); ;
+ break;}
+case 19:
+#line 293 "../expread.y"
+{ start_arglist (); ;
+ break;}
+case 20:
+#line 295 "../expread.y"
+{ write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); ;
+ break;}
+case 22:
+#line 304 "../expread.y"
+{ arglist_len = 1; ;
+ break;}
+case 23:
+#line 308 "../expread.y"
+{ arglist_len++; ;
+ break;}
+case 24:
+#line 312 "../expread.y"
+{ write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_elt_type (yyvsp[-2].tval);
+ write_exp_elt_opcode (UNOP_MEMVAL); ;
+ break;}
+case 25:
+#line 318 "../expread.y"
+{ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (yyvsp[-2].tval);
+ write_exp_elt_opcode (UNOP_CAST); ;
+ break;}
+case 26:
+#line 324 "../expread.y"
+{ ;
+ break;}
+case 27:
+#line 330 "../expread.y"
+{ write_exp_elt_opcode (BINOP_REPEAT); ;
+ break;}
+case 28:
+#line 334 "../expread.y"
+{ write_exp_elt_opcode (BINOP_MUL); ;
+ break;}
+case 29:
+#line 338 "../expread.y"
+{ write_exp_elt_opcode (BINOP_DIV); ;
+ break;}
+case 30:
+#line 342 "../expread.y"
+{ write_exp_elt_opcode (BINOP_REM); ;
+ break;}
+case 31:
+#line 346 "../expread.y"
+{ write_exp_elt_opcode (BINOP_ADD); ;
+ break;}
+case 32:
+#line 350 "../expread.y"
+{ write_exp_elt_opcode (BINOP_SUB); ;
+ break;}
+case 33:
+#line 354 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LSH); ;
+ break;}
+case 34:
+#line 358 "../expread.y"
+{ write_exp_elt_opcode (BINOP_RSH); ;
+ break;}
+case 35:
+#line 362 "../expread.y"
+{ write_exp_elt_opcode (BINOP_EQUAL); ;
+ break;}
+case 36:
+#line 366 "../expread.y"
+{ write_exp_elt_opcode (BINOP_NOTEQUAL); ;
+ break;}
+case 37:
+#line 370 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LEQ); ;
+ break;}
+case 38:
+#line 374 "../expread.y"
+{ write_exp_elt_opcode (BINOP_GEQ); ;
+ break;}
+case 39:
+#line 378 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LESS); ;
+ break;}
+case 40:
+#line 382 "../expread.y"
+{ write_exp_elt_opcode (BINOP_GTR); ;
+ break;}
+case 41:
+#line 386 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LOGAND); ;
+ break;}
+case 42:
+#line 390 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LOGXOR); ;
+ break;}
+case 43:
+#line 394 "../expread.y"
+{ write_exp_elt_opcode (BINOP_LOGIOR); ;
+ break;}
+case 44:
+#line 398 "../expread.y"
+{ write_exp_elt_opcode (BINOP_AND); ;
+ break;}
+case 45:
+#line 402 "../expread.y"
+{ write_exp_elt_opcode (BINOP_OR); ;
+ break;}
+case 46:
+#line 406 "../expread.y"
+{ write_exp_elt_opcode (TERNOP_COND); ;
+ break;}
+case 47:
+#line 410 "../expread.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN); ;
+ break;}
+case 48:
+#line 414 "../expread.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode (yyvsp[-1].opcode);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); ;
+ break;}
+case 49:
+#line 420 "../expread.y"
+{ write_exp_elt_opcode (OP_LONG);
+ if (yyvsp[0].lval == (int) yyvsp[0].lval || yyvsp[0].lval == (unsigned int) yyvsp[0].lval)
+ write_exp_elt_type (builtin_type_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 50:
+#line 430 "../expread.y"
+{ YYSTYPE val;
+ parse_number (yyvsp[0].ssym.stoken.ptr, yyvsp[0].ssym.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ if (val.lval == (int) val.lval ||
+ val.lval == (unsigned int) val.lval)
+ write_exp_elt_type (builtin_type_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+ write_exp_elt_longcst (val.lval);
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 51:
+#line 443 "../expread.y"
+{
+ write_exp_elt_opcode (OP_LONG);
+ if (yyvsp[0].ulval == (unsigned int) yyvsp[0].ulval)
+ write_exp_elt_type (builtin_type_unsigned_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].ulval);
+ write_exp_elt_opcode (OP_LONG);
+ ;
+ break;}
+case 52:
+#line 455 "../expread.y"
+{ YYSTYPE val;
+ parse_number (yyvsp[0].ssym.stoken.ptr, yyvsp[0].ssym.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ if (val.ulval == (unsigned int) val.ulval)
+ write_exp_elt_type (builtin_type_unsigned_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+ write_exp_elt_longcst ((LONGEST)val.ulval);
+ write_exp_elt_opcode (OP_LONG);
+ ;
+ break;}
+case 53:
+#line 468 "../expread.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 54:
+#line 475 "../expread.y"
+{ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_double);
+ write_exp_elt_dblcst (yyvsp[0].dval);
+ write_exp_elt_opcode (OP_DOUBLE); ;
+ break;}
+case 56:
+#line 485 "../expread.y"
+{ write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+ write_exp_elt_opcode (OP_LAST); ;
+ break;}
+case 57:
+#line 491 "../expread.y"
+{ write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+ write_exp_elt_opcode (OP_REGISTER); ;
+ break;}
+case 58:
+#line 497 "../expread.y"
+{ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern (yyvsp[0].ivar);
+ write_exp_elt_opcode (OP_INTERNALVAR); ;
+ break;}
+case 59:
+#line 503 "../expread.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (yyvsp[-1].tval));
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 60:
+#line 510 "../expread.y"
+{ write_exp_elt_opcode (OP_STRING);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (OP_STRING); ;
+ break;}
+case 61:
+#line 517 "../expread.y"
+{ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS); ;
+ break;}
+case 62:
+#line 524 "../expread.y"
+{
+ if (yyvsp[0].ssym.sym != 0)
+ yyval.bval = SYMBOL_BLOCK_VALUE (yyvsp[0].ssym.sym);
+ else
+ {
+ struct symtab *tem =
+ lookup_symtab (copy_name (yyvsp[0].ssym.stoken));
+ if (tem)
+ yyval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1);
+ else
+ error ("No file or function \"%s\".",
+ copy_name (yyvsp[0].ssym.stoken));
+ }
+ ;
+ break;}
+case 63:
+#line 541 "../expread.y"
+{ struct symbol *tem
+ = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+ VAR_NAMESPACE, 0, NULL);
+ if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+ error ("No function \"%s\" in specified context.",
+ copy_name (yyvsp[0].sval));
+ yyval.bval = SYMBOL_BLOCK_VALUE (tem); ;
+ break;}
+case 64:
+#line 551 "../expread.y"
+{ struct symbol *sym;
+ sym = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+ VAR_NAMESPACE, 0, NULL);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name (yyvsp[0].sval));
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); ;
+ break;}
+case 65:
+#line 563 "../expread.y"
+{
+ struct type *type = yyvsp[-2].tval;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (OP_SCOPE);
+ ;
+ break;}
+case 66:
+#line 576 "../expread.y"
+{
+ char *name = copy_name (yyvsp[0].sval);
+ struct symbol *sym;
+ int i;
+
+ sym =
+ lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym)
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, name))
+ break;
+
+ if (i < misc_function_count)
+ {
+ enum misc_function_type mft =
+ misc_function_vector[i].type;
+
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (mft == mf_data || mft == mf_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (mft == mf_text)
+ write_exp_elt_type (lookup_function_type (builtin_type_int));
+ else
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ }
+ else
+ if (symtab_list == 0
+ && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.", name);
+ ;
+ break;}
+case 67:
+#line 622 "../expread.y"
+{ struct symbol *sym = yyvsp[0].ssym.sym;
+
+ if (sym)
+ {
+ switch (sym->class)
+ {
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else if (yyvsp[0].ssym.is_a_field_of_this)
+ {
+ /* C++: it hangs off of `this'. Must
+ not inadvertently convert from a method call
+ to data ref. */
+ if (innermost_block == 0 ||
+ contained_in (block_found, innermost_block))
+ innermost_block = block_found;
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string (yyvsp[0].ssym.stoken);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ }
+ else
+ {
+ register int i;
+ register char *arg = copy_name (yyvsp[0].ssym.stoken);
+
+ /* FIXME, this search is linear! At least
+ optimize the strcmp with a 1-char cmp... */
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, arg))
+ break;
+
+ if (i < misc_function_count)
+ {
+ enum misc_function_type mft =
+ misc_function_vector[i].type;
+
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (mft == mf_data || mft == mf_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (mft == mf_text)
+ write_exp_elt_type (lookup_function_type (builtin_type_int));
+ else
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ }
+ else if (symtab_list == 0
+ && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name (yyvsp[0].ssym.stoken));
+ }
+ ;
+ break;}
+case 69:
+#line 697 "../expread.y"
+{
+ /* This is where the interesting stuff happens. */
+ int done = 0;
+ int array_size;
+ struct type *follow_type = yyvsp[-1].tval;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = (int) pop_type ();
+ if (array_size != -1)
+ follow_type = create_array_type (follow_type,
+ array_size);
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ yyval.tval = follow_type;
+ ;
+ break;}
+case 70:
+#line 732 "../expread.y"
+{ push_type (tp_pointer); yyval.voidval = 0; ;
+ break;}
+case 71:
+#line 734 "../expread.y"
+{ push_type (tp_pointer); yyval.voidval = yyvsp[0].voidval; ;
+ break;}
+case 73:
+#line 739 "../expread.y"
+{ yyval.voidval = yyvsp[-1].voidval; ;
+ break;}
+case 74:
+#line 741 "../expread.y"
+{
+ push_type ((enum type_pieces) yyvsp[0].lval);
+ push_type (tp_array);
+ ;
+ break;}
+case 75:
+#line 746 "../expread.y"
+{
+ push_type ((enum type_pieces) yyvsp[0].lval);
+ push_type (tp_array);
+ yyval.voidval = 0;
+ ;
+ break;}
+case 76:
+#line 752 "../expread.y"
+{ push_type (tp_function); ;
+ break;}
+case 77:
+#line 754 "../expread.y"
+{ push_type (tp_function); ;
+ break;}
+case 78:
+#line 758 "../expread.y"
+{ yyval.lval = -1; ;
+ break;}
+case 79:
+#line 760 "../expread.y"
+{ yyval.lval = yyvsp[-1].lval; ;
+ break;}
+case 80:
+#line 764 "../expread.y"
+{ yyval.voidval = 0; ;
+ break;}
+case 82:
+#line 769 "../expread.y"
+{ yyval.tval = lookup_member_type (builtin_type_int, yyvsp[-2].tval); ;
+ break;}
+case 83:
+#line 771 "../expread.y"
+{ yyval.tval = lookup_member_type (yyvsp[-5].tval, yyvsp[-3].tval); ;
+ break;}
+case 84:
+#line 773 "../expread.y"
+{ yyval.tval = lookup_member_type
+ (lookup_function_type (yyvsp[-7].tval), yyvsp[-5].tval); ;
+ break;}
+case 85:
+#line 776 "../expread.y"
+{ yyval.tval = lookup_member_type
+ (lookup_function_type (yyvsp[-8].tval), yyvsp[-6].tval);
+ free (yyvsp[-1].tvec); ;
+ break;}
+case 86:
+#line 783 "../expread.y"
+{ yyval.tval = yyvsp[0].tsym.type; ;
+ break;}
+case 87:
+#line 785 "../expread.y"
+{ yyval.tval = builtin_type_int; ;
+ break;}
+case 88:
+#line 787 "../expread.y"
+{ yyval.tval = builtin_type_long; ;
+ break;}
+case 89:
+#line 789 "../expread.y"
+{ yyval.tval = builtin_type_short; ;
+ break;}
+case 90:
+#line 791 "../expread.y"
+{ yyval.tval = builtin_type_long; ;
+ break;}
+case 91:
+#line 793 "../expread.y"
+{ yyval.tval = builtin_type_unsigned_long; ;
+ break;}
+case 92:
+#line 795 "../expread.y"
+{ yyval.tval = builtin_type_short; ;
+ break;}
+case 93:
+#line 797 "../expread.y"
+{ yyval.tval = builtin_type_unsigned_short; ;
+ break;}
+case 94:
+#line 799 "../expread.y"
+{ yyval.tval = lookup_struct (copy_name (yyvsp[0].sval),
+ expression_context_block); ;
+ break;}
+case 95:
+#line 802 "../expread.y"
+{ yyval.tval = lookup_union (copy_name (yyvsp[0].sval),
+ expression_context_block); ;
+ break;}
+case 96:
+#line 805 "../expread.y"
+{ yyval.tval = lookup_enum (copy_name (yyvsp[0].sval),
+ expression_context_block); ;
+ break;}
+case 97:
+#line 808 "../expread.y"
+{ yyval.tval = lookup_unsigned_typename (TYPE_NAME(yyvsp[0].tsym.type)); ;
+ break;}
+case 98:
+#line 810 "../expread.y"
+{ yyval.tval = builtin_type_unsigned_int; ;
+ break;}
+case 99:
+#line 812 "../expread.y"
+{ yyval.tval = yyvsp[0].tsym.type; ;
+ break;}
+case 100:
+#line 814 "../expread.y"
+{ yyval.tval = builtin_type_int; ;
+ break;}
+case 102:
+#line 819 "../expread.y"
+{
+ yyval.tsym.stoken.ptr = "int";
+ yyval.tsym.stoken.length = 3;
+ yyval.tsym.type = builtin_type_int;
+ ;
+ break;}
+case 103:
+#line 825 "../expread.y"
+{
+ yyval.tsym.stoken.ptr = "long";
+ yyval.tsym.stoken.length = 4;
+ yyval.tsym.type = builtin_type_long;
+ ;
+ break;}
+case 104:
+#line 831 "../expread.y"
+{
+ yyval.tsym.stoken.ptr = "short";
+ yyval.tsym.stoken.length = 5;
+ yyval.tsym.type = builtin_type_short;
+ ;
+ break;}
+case 105:
+#line 840 "../expread.y"
+{ yyval.tvec = (struct type **)xmalloc (sizeof (struct type *) * 2);
+ yyval.tvec[0] = (struct type *)0;
+ yyval.tvec[1] = yyvsp[0].tval;
+ ;
+ break;}
+case 106:
+#line 845 "../expread.y"
+{ int len = sizeof (struct type *) * ++(yyvsp[-2].ivec[0]);
+ yyval.tvec = (struct type **)xrealloc (yyvsp[-2].tvec, len);
+ yyval.tvec[yyval.ivec[0]] = yyvsp[0].tval;
+ ;
+ break;}
+case 107:
+#line 851 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+case 108:
+#line 852 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+case 109:
+#line 853 "../expread.y"
+{ yyval.sval = yyvsp[0].tsym.stoken; ;
+ break;}
+case 110:
+#line 854 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+case 111:
+#line 855 "../expread.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 327 "bison.simple"
+\f
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+ yyerror("parse error");
+ }
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+}
+#line 864 "../expread.y"
+
+\f
+/* Begin counting arguments for a function call,
+ saving the data about any containing call. */
+
+static void
+start_arglist ()
+{
+ register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+
+ new->next = funcall_chain;
+ new->arglist_len = arglist_len;
+ arglist_len = 0;
+ funcall_chain = new;
+}
+
+/* Return the number of arguments in a function call just terminated,
+ and restore the data for the containing function call. */
+
+static int
+end_arglist ()
+{
+ register int val = arglist_len;
+ register struct funcall *call = funcall_chain;
+ funcall_chain = call->next;
+ arglist_len = call->arglist_len;
+ free (call);
+ return val;
+}
+
+/* Free everything in the funcall chain.
+ Used when there is an error inside parsing. */
+
+static void
+free_funcalls ()
+{
+ register struct funcall *call, *next;
+
+ for (call = funcall_chain; call; call = next)
+ {
+ next = call->next;
+ free (call);
+ }
+}
+\f
+/* This page contains the functions for adding data to the struct expression
+ being constructed. */
+
+/* Add one element to the end of the expression. */
+
+/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
+ a register through here */
+
+static void
+write_exp_elt (expelt)
+ union exp_element expelt;
+{
+ if (expout_ptr >= expout_size)
+ {
+ expout_size *= 2;
+ expout = (struct expression *) xrealloc (expout,
+ sizeof (struct expression)
+ + expout_size * sizeof (union exp_element));
+ }
+ expout->elts[expout_ptr++] = expelt;
+}
+
+static void
+write_exp_elt_opcode (expelt)
+ enum exp_opcode expelt;
+{
+ union exp_element tmp;
+
+ tmp.opcode = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_sym (expelt)
+ struct symbol *expelt;
+{
+ union exp_element tmp;
+
+ tmp.symbol = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_longcst (expelt)
+ LONGEST expelt;
+{
+ union exp_element tmp;
+
+ tmp.longconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_dblcst (expelt)
+ double expelt;
+{
+ union exp_element tmp;
+
+ tmp.doubleconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_type (expelt)
+ struct type *expelt;
+{
+ union exp_element tmp;
+
+ tmp.type = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_intern (expelt)
+ struct internalvar *expelt;
+{
+ union exp_element tmp;
+
+ tmp.internalvar = expelt;
+
+ write_exp_elt (tmp);
+}
+
+/* Add a string constant to the end of the expression.
+ Follow it by its length in bytes, as a separate exp_element. */
+
+static void
+write_exp_string (str)
+ struct stoken str;
+{
+ register int len = str.length;
+ register int lenelt
+ = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+
+ expout_ptr += lenelt;
+
+ if (expout_ptr >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + 10);
+ expout = (struct expression *)
+ xrealloc (expout, (sizeof (struct expression)
+ + (expout_size * sizeof (union exp_element))));
+ }
+ bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
+ ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+ write_exp_elt_longcst ((LONGEST) len);
+}
+\f
+/* During parsing of a C expression, the pointer to the next character
+ is in this variable. */
+
+static char *lexptr;
+
+/* Tokens that refer to names do so with explicit pointer and length,
+ so they can share the storage that lexptr is parsing.
+
+ When it is necessary to pass a name to a function that expects
+ a null-terminated string, the substring is copied out
+ into a block of storage that namecopy points to.
+
+ namecopy is allocated once, guaranteed big enough, for each parsing. */
+
+static char *namecopy;
+
+/* Current depth in parentheses within the expression. */
+
+static int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses). */
+
+static int comma_terminates;
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ register LONGEST n = 0;
+ register int i;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+
+ extern double atof ();
+
+ if (parsed_float)
+ {
+ /* It's a float since it contains a point or an exponent. */
+ putithere->dval = atof (p);
+ return FLOAT;
+ }
+
+ /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+ if (p[0] == '0')
+ switch (p[1])
+ {
+ case 'x':
+ case 'X':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ case 'd':
+ case 'D':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 10;
+ len -= 2;
+ }
+ break;
+
+ default:
+ base = 8;
+ break;
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ n += i = c - '0';
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ n += i = c - 'a' + 10;
+ else if (len == 0 && c == 'l')
+ ;
+ else if (len == 0 && c == 'u')
+ unsigned_p = 1;
+ else
+ return ERROR; /* Char not a digit */
+ }
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+ }
+
+ if (unsigned_p)
+ {
+ putithere->ulval = n;
+ return UINT;
+ }
+ else
+ {
+ putithere->lval = n;
+ return INT;
+ }
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static struct token tokentab3[] =
+ {
+ {">>=", ASSIGN_MODIFY, BINOP_RSH},
+ {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+ };
+
+static struct token tokentab2[] =
+ {
+ {"+=", ASSIGN_MODIFY, BINOP_ADD},
+ {"-=", ASSIGN_MODIFY, BINOP_SUB},
+ {"*=", ASSIGN_MODIFY, BINOP_MUL},
+ {"/=", ASSIGN_MODIFY, BINOP_DIV},
+ {"%=", ASSIGN_MODIFY, BINOP_REM},
+ {"|=", ASSIGN_MODIFY, BINOP_LOGIOR},
+ {"&=", ASSIGN_MODIFY, BINOP_LOGAND},
+ {"^=", ASSIGN_MODIFY, BINOP_LOGXOR},
+ {"++", INCREMENT, BINOP_END},
+ {"--", DECREMENT, BINOP_END},
+ {"->", ARROW, BINOP_END},
+ {"&&", AND, BINOP_END},
+ {"||", OR, BINOP_END},
+ {"::", COLONCOLON, BINOP_END},
+ {"<<", LSH, BINOP_END},
+ {">>", RSH, BINOP_END},
+ {"==", EQUAL, BINOP_END},
+ {"!=", NOTEQUAL, BINOP_END},
+ {"<=", LEQ, BINOP_END},
+ {">=", GEQ, BINOP_END}
+ };
+
+/* assign machine-independent names to certain registers
+ * (unless overridden by the REGISTER_NAMES table)
+ */
+struct std_regs {
+ char *name;
+ int regnum;
+} std_regs[] = {
+#ifdef PC_REGNUM
+ { "pc", PC_REGNUM },
+#endif
+#ifdef FP_REGNUM
+ { "fp", FP_REGNUM },
+#endif
+#ifdef SP_REGNUM
+ { "sp", SP_REGNUM },
+#endif
+#ifdef PS_REGNUM
+ { "ps", PS_REGNUM },
+#endif
+};
+
+#define NUM_STD_REGS (sizeof std_regs / sizeof std_regs[0])
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ register int c;
+ register int namelen;
+ register unsigned i;
+ register char *tokstart;
+
+ retry:
+
+ tokstart = lexptr;
+ /* See if it is a special token of length 3. */
+ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+ if (!strncmp (tokstart, tokentab3[i].operator, 3))
+ {
+ lexptr += 3;
+ yylval.opcode = tokentab3[i].opcode;
+ return tokentab3[i].token;
+ }
+
+ /* See if it is a special token of length 2. */
+ for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+ if (!strncmp (tokstart, tokentab2[i].operator, 2))
+ {
+ lexptr += 2;
+ yylval.opcode = tokentab2[i].opcode;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ lexptr++;
+ c = *lexptr++;
+ if (c == '\\')
+ c = parse_escape (&lexptr);
+ yylval.lval = c;
+ c = *lexptr++;
+ if (c != '\'')
+ error ("Invalid character constant.");
+ return CHAR;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] < '0' || lexptr[1] > '9')
+ goto symbol; /* Nope, must be a symbol. */
+ /* FALL THRU into number case. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!hex && !got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ /* We will take any letters or digits. parse_number will
+ complain if past the radix, or if L or U are not final. */
+ else if ((*p < '0' || *p > '9')
+ && ((*p < 'a' || *p > 'z')
+ && (*p < 'A' || *p > 'Z')))
+ break;
+ }
+ toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ bcopy (tokstart, err_copy, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ symbol:
+ lexptr++;
+ return c;
+
+ case '"':
+ for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++)
+ if (c == '\\')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ c = tokstart[++namelen];
+ }
+ }
+ yylval.sval.ptr = tokstart + 1;
+ yylval.sval.length = namelen - 1;
+ lexptr += namelen + 1;
+ return STRING;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen])
+ ;
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ lexptr += namelen;
+
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that).
+ Make token type LAST, and put the number (the digits) in yylval. */
+
+ if (*tokstart == '$')
+ {
+ register int negate = 0;
+ c = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (namelen >= 2 && tokstart[1] == '$')
+ {
+ negate = 1;
+ c = 2;
+ }
+ if (c == namelen)
+ {
+ /* Just dollars (one or two) */
+ yylval.lval = - negate;
+ return LAST;
+ }
+ /* Is the rest of the token digits? */
+ for (; c < namelen; c++)
+ if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
+ break;
+ if (c == namelen)
+ {
+ yylval.lval = atoi (tokstart + 1 + negate);
+ if (negate)
+ yylval.lval = - yylval.lval;
+ return LAST;
+ }
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+
+ if (*tokstart == '$') {
+ for (c = 0; c < NUM_REGS; c++)
+ if (namelen - 1 == strlen (reg_names[c])
+ && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+ {
+ yylval.lval = c;
+ return REGNAME;
+ }
+ for (c = 0; c < NUM_STD_REGS; c++)
+ if (namelen - 1 == strlen (std_regs[c].name)
+ && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+ {
+ yylval.lval = std_regs[c].regnum;
+ return REGNAME;
+ }
+ }
+ /* Catch specific keywords. Should be done with a data structure. */
+ switch (namelen)
+ {
+ case 8:
+ if (!strncmp (tokstart, "unsigned", 8))
+ return UNSIGNED;
+ break;
+ case 6:
+ if (!strncmp (tokstart, "struct", 6))
+ return STRUCT;
+ if (!strncmp (tokstart, "signed", 6))
+ return SIGNED;
+ if (!strncmp (tokstart, "sizeof", 6))
+ return SIZEOF;
+ break;
+ case 5:
+ if (!strncmp (tokstart, "union", 5))
+ return UNION;
+ if (!strncmp (tokstart, "short", 5))
+ return SHORT;
+ break;
+ case 4:
+ if (!strncmp (tokstart, "enum", 4))
+ return ENUM;
+ if (!strncmp (tokstart, "long", 4))
+ return LONG;
+ if (!strncmp (tokstart, "this", 4))
+ {
+ static const char this_name[] =
+ { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
+
+ if (lookup_symbol (this_name, expression_context_block,
+ VAR_NAMESPACE, 0, NULL))
+ return THIS;
+ }
+ break;
+ case 3:
+ if (!strncmp (tokstart, "int", 3))
+ return INT_KEYWORD;
+ break;
+ default:
+ break;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ if (*tokstart == '$')
+ {
+ yylval.ivar = lookup_internalvar (copy_name (yylval.sval) + 1);
+ return VARIABLE;
+ }
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions or symtabs. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+ int is_a_field_of_this = 0;
+ int hextype;
+
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, &is_a_field_of_this, NULL);
+ if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
+ lookup_partial_symtab (tmp))
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return BLOCKNAME;
+ }
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym &&
+ ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
+ (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ if (hextype == UINT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_UINT;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+static void
+yyerror (msg)
+ char *msg;
+{
+ error ("Invalid syntax in expression.");
+}
+
+/* Return a null-terminated temporary copy of the name
+ of a string token. */
+
+static char *
+copy_name (token)
+ struct stoken token;
+{
+ bcopy (token.ptr, namecopy, token.length);
+ namecopy[token.length] = 0;
+ return namecopy;
+}
+\f
+/* Reverse an expression from suffix form (in which it is constructed)
+ to prefix form (in which we can conveniently print or execute it). */
+
+static void prefixify_subexp ();
+
+static void
+prefixify_expression (expr)
+ register struct expression *expr;
+{
+ register int len = sizeof (struct expression) +
+ expr->nelts * sizeof (union exp_element);
+ register struct expression *temp;
+ register int inpos = expr->nelts, outpos = 0;
+
+ temp = (struct expression *) alloca (len);
+
+ /* Copy the original expression into temp. */
+ bcopy (expr, temp, len);
+
+ prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the subexpression of EXPR
+ whose last exp_element is at index ENDPOS - 1 in EXPR. */
+
+static int
+length_of_subexp (expr, endpos)
+ register struct expression *expr;
+ register int endpos;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+
+ if (endpos < 0)
+ error ("?error in length_of_subexp");
+
+ i = (int) expr->elts[endpos - 1].opcode;
+
+ switch (i)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((expr->elts[endpos - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ oplen = 4;
+ break;
+
+ case OP_VAR_VALUE:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + expr->elts[endpos - 2].longconst;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ case OP_STRING:
+ oplen = 3 + ((expr->elts[endpos - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + (i < (int) BINOP_END);
+ }
+
+ while (args > 0)
+ {
+ oplen += length_of_subexp (expr, endpos - oplen);
+ args--;
+ }
+
+ return oplen;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+ into OUTEXPR, starting at index OUTBEG.
+ In the process, convert it from suffix to prefix form. */
+
+static void
+prefixify_subexp (inexpr, outexpr, inend, outbeg)
+ register struct expression *inexpr;
+ struct expression *outexpr;
+ register int inend;
+ int outbeg;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+ int *arglens;
+ enum exp_opcode opcode;
+
+ /* Compute how long the last operation is (in OPLEN),
+ and also how many preceding subexpressions serve as
+ arguments for it (in ARGS). */
+
+ opcode = inexpr->elts[inend - 1].opcode;
+ switch (opcode)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((inexpr->elts[inend - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ oplen = 4;
+ break;
+
+ case OP_VAR_VALUE:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + inexpr->elts[inend - 2].longconst;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ case OP_STRING:
+ oplen = 3 + ((inexpr->elts[inend - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + ((int) opcode < (int) BINOP_END);
+ }
+
+ /* Copy the final operator itself, from the end of the input
+ to the beginning of the output. */
+ inend -= oplen;
+ bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg],
+ oplen * sizeof (union exp_element));
+ outbeg += oplen;
+
+ /* Find the lengths of the arg subexpressions. */
+ arglens = (int *) alloca (args * sizeof (int));
+ for (i = args - 1; i >= 0; i--)
+ {
+ oplen = length_of_subexp (inexpr, inend);
+ arglens[i] = oplen;
+ inend -= oplen;
+ }
+
+ /* Now copy each subexpression, preserving the order of
+ the subexpressions, but prefixifying each one.
+ In this loop, inend starts at the beginning of
+ the expression this level is working on
+ and marches forward over the arguments.
+ outbeg does similarly in the output. */
+ for (i = 0; i < args; i++)
+ {
+ oplen = arglens[i];
+ inend += oplen;
+ prefixify_subexp (inexpr, outexpr, inend, outbeg);
+ outbeg += oplen;
+ }
+}
+\f
+/* This page contains the two entry points to this file. */
+
+/* Read a C expression from the string *STRINGPTR points to,
+ parse it, and return a pointer to a struct expression that we malloc.
+ Use block BLOCK as the lexical context for variable names;
+ if BLOCK is zero, use the block of the selected stack frame.
+ Meanwhile, advance *STRINGPTR to point after the expression,
+ at the first nonwhite character that is not part of the expression
+ (possibly a null character).
+
+ If COMMA is nonzero, stop if a comma is reached. */
+
+struct expression *
+parse_c_1 (stringptr, block, comma)
+ char **stringptr;
+ struct block *block;
+ int comma;
+{
+ struct cleanup *old_chain;
+
+ lexptr = *stringptr;
+
+ paren_depth = 0;
+ type_stack_depth = 0;
+
+ comma_terminates = comma;
+
+ if (lexptr == 0 || *lexptr == 0)
+ error_no_arg ("expression to compute");
+
+ old_chain = make_cleanup (free_funcalls, 0);
+ funcall_chain = 0;
+
+ expression_context_block = block ? block : get_selected_block ();
+
+ namecopy = (char *) alloca (strlen (lexptr) + 1);
+ expout_size = 10;
+ expout_ptr = 0;
+ expout = (struct expression *)
+ xmalloc (sizeof (struct expression)
+ + expout_size * sizeof (union exp_element));
+ make_cleanup (free_current_contents, &expout);
+ if (yyparse ())
+ yyerror (NULL);
+ discard_cleanups (old_chain);
+ expout->nelts = expout_ptr;
+ expout = (struct expression *)
+ xrealloc (expout,
+ sizeof (struct expression)
+ + expout_ptr * sizeof (union exp_element));
+ prefixify_expression (expout);
+ *stringptr = lexptr;
+ return expout;
+}
+
+/* Parse STRING as an expression, and complain if this fails
+ to use up all of the contents of STRING. */
+
+struct expression *
+parse_c_expression (string)
+ char *string;
+{
+ register struct expression *exp;
+ exp = parse_c_1 (&string, 0, 0);
+ if (*string)
+ error ("Junk after end of expression.");
+ return exp;
+}
+
+static void
+push_type (tp)
+ enum type_pieces tp;
+{
+ if (type_stack_depth == type_stack_size)
+ {
+ type_stack_size *= 2;
+ type_stack = (enum type_pieces *)
+ xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces));
+ }
+ type_stack[type_stack_depth++] = tp;
+}
+
+static enum type_pieces
+pop_type ()
+{
+ if (type_stack_depth)
+ return type_stack[--type_stack_depth];
+ return tp_end;
+}
+
+void
+_initialize_expread ()
+{
+ type_stack_size = 80;
+ type_stack_depth = 0;
+ type_stack = (enum type_pieces *)
+ xmalloc (type_stack_size * sizeof (enum type_pieces));
+}
--- /dev/null
+/* Parse C expressions for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+\f
+/* Parse a C expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result. */
+
+%{
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "expression.h"
+#include "value.h"
+#include "command.h"
+
+static struct expression *expout;
+static int expout_size;
+static int expout_ptr;
+
+static int yylex ();
+static void yyerror ();
+static void write_exp_elt ();
+static void write_exp_elt_opcode ();
+static void write_exp_elt_sym ();
+static void write_exp_elt_longcst ();
+static void write_exp_elt_dblcst ();
+static void write_exp_elt_type ();
+static void write_exp_elt_intern ();
+static void write_exp_string ();
+static void start_arglist ();
+static int end_arglist ();
+static void free_funcalls ();
+static char *copy_name ();
+static int parse_number ();
+
+/* If this is nonzero, this block is used as the lexical context
+ for symbol names. */
+
+static struct block *expression_context_block;
+
+/* The innermost context required by the stack and register variables
+ we've encountered so far. */
+struct block *innermost_block;
+
+/* The block in which the most recently discovered symbol was found. */
+struct block *block_found;
+
+/* Number of arguments seen so far in innermost function call. */
+static int arglist_len;
+
+/* Data structure for saving values of arglist_len
+ for function calls whose arguments contain other function calls. */
+
+struct funcall
+ {
+ struct funcall *next;
+ int arglist_len;
+ };
+
+struct funcall *funcall_chain;
+
+/* This kind of datum is used to represent the name
+ of a symbol token. */
+
+struct stoken
+ {
+ char *ptr;
+ int length;
+ };
+
+struct ttype
+ {
+ struct stoken stoken;
+ struct type *type;
+ };
+
+struct symtoken
+ {
+ struct stoken stoken;
+ struct symbol *sym;
+ int is_a_field_of_this;
+ };
+
+/* For parsing of complicated types.
+ An array should be preceded in the list by the size of the array. */
+enum type_pieces
+ {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function};
+static enum type_pieces *type_stack;
+static int type_stack_depth, type_stack_size;
+
+static void push_type ();
+static enum type_pieces pop_type ();
+
+/* Allow debugging of parsing. */
+#define YYDEBUG 1
+%}
+
+/* Although the yacc "value" of an expression is not used,
+ since the result is stored in the structure being created,
+ other node types do have values. */
+
+%union
+ {
+ LONGEST lval;
+ unsigned LONGEST ulval;
+ double dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ }
+
+%type <voidval> exp exp1 start variable
+%type <tval> type typebase
+%type <tvec> nonempty_typelist
+%type <bval> block
+
+/* Fancy type parsing. */
+%type <voidval> func_mod direct_abs_decl abs_decl
+%type <tval> ptype
+%type <lval> array_mod
+
+%token <lval> INT CHAR
+%token <ulval> UINT
+%token <dval> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+ and both convey their data as strings.
+ But a TYPENAME is a string that happens to be defined as a typedef
+ or builtin type name (such as int or char)
+ and a NAME is any other symbol.
+
+ Contexts where this distinction is not important can use the
+ nonterminal "name", which matches either NAME or TYPENAME. */
+
+%token <sval> STRING
+%token <ssym> NAME BLOCKNAME
+%token <tsym> TYPENAME
+%type <sval> name
+%type <ssym> name_not_typename
+%type <tsym> typename
+
+/* A NAME_OR_INT is a symbol which is not known in the symbol table,
+ but which would parse as a valid number in the current input radix.
+ E.g. "c" when input_radix==16. Depending on the parse, it will be
+ turned into a name or into a number. NAME_OR_UINT ditto. */
+
+%token <ssym> NAME_OR_INT NAME_OR_UINT
+
+%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token SIGNED LONG SHORT INT_KEYWORD
+
+%token <lval> LAST REGNAME
+
+%token <ivar> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+/* C++ */
+%token THIS
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left OR
+%left AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY INCREMENT DECREMENT
+%right ARROW '.' '[' '('
+%left COLONCOLON
+\f
+%%
+
+start : exp1
+ ;
+
+/* Expressions, including the comma operator. */
+exp1 : exp
+ | exp1 ',' exp
+ { write_exp_elt_opcode (BINOP_COMMA); }
+ ;
+
+/* Expressions, not including the comma operator. */
+exp : '*' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_IND); }
+
+exp : '&' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_ADDR); }
+
+exp : '-' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_NEG); }
+ ;
+
+exp : '!' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_ZEROP); }
+ ;
+
+exp : '~' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGNOT); }
+ ;
+
+exp : INCREMENT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_PREINCREMENT); }
+ ;
+
+exp : DECREMENT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_PREDECREMENT); }
+ ;
+
+exp : exp INCREMENT %prec UNARY
+ { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
+ ;
+
+exp : exp DECREMENT %prec UNARY
+ { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
+ ;
+
+exp : SIZEOF exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+exp : exp ARROW name
+ { write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_PTR); }
+ ;
+
+exp : exp ARROW '*' exp
+ { write_exp_elt_opcode (STRUCTOP_MPTR); }
+ ;
+
+exp : exp '.' name
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
+exp : exp '.' '*' exp
+ { write_exp_elt_opcode (STRUCTOP_MEMBER); }
+ ;
+
+exp : exp '[' exp1 ']'
+ { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+ ;
+
+exp : exp '('
+ /* This is to save the value of arglist_len
+ being accumulated by an outer function call. */
+ { start_arglist (); }
+ arglist ')' %prec ARROW
+ { write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+exp : '{' type '}' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_MEMVAL); }
+ ;
+
+exp : '(' type ')' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+exp : '(' exp1 ')'
+ { }
+ ;
+
+/* Binary operators in order of decreasing precedence. */
+
+exp : exp '@' exp
+ { write_exp_elt_opcode (BINOP_REPEAT); }
+ ;
+
+exp : exp '*' exp
+ { write_exp_elt_opcode (BINOP_MUL); }
+ ;
+
+exp : exp '/' exp
+ { write_exp_elt_opcode (BINOP_DIV); }
+ ;
+
+exp : exp '%' exp
+ { write_exp_elt_opcode (BINOP_REM); }
+ ;
+
+exp : exp '+' exp
+ { write_exp_elt_opcode (BINOP_ADD); }
+ ;
+
+exp : exp '-' exp
+ { write_exp_elt_opcode (BINOP_SUB); }
+ ;
+
+exp : exp LSH exp
+ { write_exp_elt_opcode (BINOP_LSH); }
+ ;
+
+exp : exp RSH exp
+ { write_exp_elt_opcode (BINOP_RSH); }
+ ;
+
+exp : exp EQUAL exp
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+ ;
+
+exp : exp NOTEQUAL exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ ;
+
+exp : exp LEQ exp
+ { write_exp_elt_opcode (BINOP_LEQ); }
+ ;
+
+exp : exp GEQ exp
+ { write_exp_elt_opcode (BINOP_GEQ); }
+ ;
+
+exp : exp '<' exp
+ { write_exp_elt_opcode (BINOP_LESS); }
+ ;
+
+exp : exp '>' exp
+ { write_exp_elt_opcode (BINOP_GTR); }
+ ;
+
+exp : exp '&' exp
+ { write_exp_elt_opcode (BINOP_LOGAND); }
+ ;
+
+exp : exp '^' exp
+ { write_exp_elt_opcode (BINOP_LOGXOR); }
+ ;
+
+exp : exp '|' exp
+ { write_exp_elt_opcode (BINOP_LOGIOR); }
+ ;
+
+exp : exp AND exp
+ { write_exp_elt_opcode (BINOP_AND); }
+ ;
+
+exp : exp OR exp
+ { write_exp_elt_opcode (BINOP_OR); }
+ ;
+
+exp : exp '?' exp ':' exp %prec '?'
+ { write_exp_elt_opcode (TERNOP_COND); }
+ ;
+
+exp : exp '=' exp
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+ ;
+
+exp : exp ASSIGN_MODIFY exp
+ { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode ($2);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : INT
+ { write_exp_elt_opcode (OP_LONG);
+ if ($1 == (int) $1 || $1 == (unsigned int) $1)
+ write_exp_elt_type (builtin_type_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : NAME_OR_INT
+ { YYSTYPE val;
+ parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ if (val.lval == (int) val.lval ||
+ val.lval == (unsigned int) val.lval)
+ write_exp_elt_type (builtin_type_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_LONGEST);
+ write_exp_elt_longcst (val.lval);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : UINT
+ {
+ write_exp_elt_opcode (OP_LONG);
+ if ($1 == (unsigned int) $1)
+ write_exp_elt_type (builtin_type_unsigned_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+exp : NAME_OR_UINT
+ { YYSTYPE val;
+ parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ if (val.ulval == (unsigned int) val.ulval)
+ write_exp_elt_type (builtin_type_unsigned_int);
+ else
+ write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
+ write_exp_elt_longcst ((LONGEST)val.ulval);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+exp : CHAR
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : FLOAT
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_double);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : LAST
+ { write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LAST); }
+ ;
+
+exp : REGNAME
+ { write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_REGISTER); }
+ ;
+
+exp : VARIABLE
+ { write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern ($1);
+ write_exp_elt_opcode (OP_INTERNALVAR); }
+ ;
+
+exp : SIZEOF '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : STRING
+ { write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING); }
+ ;
+
+/* C++. */
+exp : THIS
+ { write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS); }
+ ;
+
+/* end of C++. */
+
+block : BLOCKNAME
+ {
+ if ($1.sym != 0)
+ $$ = SYMBOL_BLOCK_VALUE ($1.sym);
+ else
+ {
+ struct symtab *tem =
+ lookup_symtab (copy_name ($1.stoken));
+ if (tem)
+ $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1);
+ else
+ error ("No file or function \"%s\".",
+ copy_name ($1.stoken));
+ }
+ }
+ ;
+
+block : block COLONCOLON name
+ { struct symbol *tem
+ = lookup_symbol (copy_name ($3), $1,
+ VAR_NAMESPACE, 0, NULL);
+ if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+ error ("No function \"%s\" in specified context.",
+ copy_name ($3));
+ $$ = SYMBOL_BLOCK_VALUE (tem); }
+ ;
+
+variable: block COLONCOLON name
+ { struct symbol *sym;
+ sym = lookup_symbol (copy_name ($3), $1,
+ VAR_NAMESPACE, 0, NULL);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name ($3));
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+variable: typebase COLONCOLON name
+ {
+ struct type *type = $1;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string ($3);
+ write_exp_elt_opcode (OP_SCOPE);
+ }
+ | COLONCOLON name
+ {
+ char *name = copy_name ($2);
+ struct symbol *sym;
+ int i;
+
+ sym =
+ lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym)
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, name))
+ break;
+
+ if (i < misc_function_count)
+ {
+ enum misc_function_type mft =
+ misc_function_vector[i].type;
+
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (mft == mf_data || mft == mf_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (mft == mf_text)
+ write_exp_elt_type (lookup_function_type (builtin_type_int));
+ else
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ }
+ else
+ if (symtab_list == 0
+ && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.", name);
+ }
+ ;
+
+variable: name_not_typename
+ { struct symbol *sym = $1.sym;
+
+ if (sym)
+ {
+ switch (sym->class)
+ {
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else if ($1.is_a_field_of_this)
+ {
+ /* C++: it hangs off of `this'. Must
+ not inadvertently convert from a method call
+ to data ref. */
+ if (innermost_block == 0 ||
+ contained_in (block_found, innermost_block))
+ innermost_block = block_found;
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string ($1.stoken);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ }
+ else
+ {
+ register int i;
+ register char *arg = copy_name ($1.stoken);
+
+ /* FIXME, this search is linear! At least
+ optimize the strcmp with a 1-char cmp... */
+ for (i = 0; i < misc_function_count; i++)
+ if (!strcmp (misc_function_vector[i].name, arg))
+ break;
+
+ if (i < misc_function_count)
+ {
+ enum misc_function_type mft =
+ misc_function_vector[i].type;
+
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (mft == mf_data || mft == mf_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (mft == mf_text)
+ write_exp_elt_type (lookup_function_type (builtin_type_int));
+ else
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ }
+ else if (symtab_list == 0
+ && partial_symtab_list == 0)
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1.stoken));
+ }
+ }
+ ;
+
+
+ptype : typebase
+ | typebase abs_decl
+ {
+ /* This is where the interesting stuff happens. */
+ int done = 0;
+ int array_size;
+ struct type *follow_type = $1;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = (int) pop_type ();
+ if (array_size != -1)
+ follow_type = create_array_type (follow_type,
+ array_size);
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ $$ = follow_type;
+ }
+ ;
+
+abs_decl: '*'
+ { push_type (tp_pointer); $$ = 0; }
+ | '*' abs_decl
+ { push_type (tp_pointer); $$ = $2; }
+ | direct_abs_decl
+ ;
+
+direct_abs_decl: '(' abs_decl ')'
+ { $$ = $2; }
+ | direct_abs_decl array_mod
+ {
+ push_type ((enum type_pieces) $2);
+ push_type (tp_array);
+ }
+ | array_mod
+ {
+ push_type ((enum type_pieces) $1);
+ push_type (tp_array);
+ $$ = 0;
+ }
+ | direct_abs_decl func_mod
+ { push_type (tp_function); }
+ | func_mod
+ { push_type (tp_function); }
+ ;
+
+array_mod: '[' ']'
+ { $$ = -1; }
+ | '[' INT ']'
+ { $$ = $2; }
+ ;
+
+func_mod: '(' ')'
+ { $$ = 0; }
+ ;
+
+type : ptype
+ | typebase COLONCOLON '*'
+ { $$ = lookup_member_type (builtin_type_int, $1); }
+ | type '(' typebase COLONCOLON '*' ')'
+ { $$ = lookup_member_type ($1, $3); }
+ | type '(' typebase COLONCOLON '*' ')' '(' ')'
+ { $$ = lookup_member_type
+ (lookup_function_type ($1), $3); }
+ | type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
+ { $$ = lookup_member_type
+ (lookup_function_type ($1), $3);
+ free ($8); }
+ ;
+
+typebase
+ : TYPENAME
+ { $$ = $1.type; }
+ | INT_KEYWORD
+ { $$ = builtin_type_int; }
+ | LONG
+ { $$ = builtin_type_long; }
+ | SHORT
+ { $$ = builtin_type_short; }
+ | LONG INT_KEYWORD
+ { $$ = builtin_type_long; }
+ | UNSIGNED LONG INT_KEYWORD
+ { $$ = builtin_type_unsigned_long; }
+ | SHORT INT_KEYWORD
+ { $$ = builtin_type_short; }
+ | UNSIGNED SHORT INT_KEYWORD
+ { $$ = builtin_type_unsigned_short; }
+ | STRUCT name
+ { $$ = lookup_struct (copy_name ($2),
+ expression_context_block); }
+ | UNION name
+ { $$ = lookup_union (copy_name ($2),
+ expression_context_block); }
+ | ENUM name
+ { $$ = lookup_enum (copy_name ($2),
+ expression_context_block); }
+ | UNSIGNED typename
+ { $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
+ | UNSIGNED
+ { $$ = builtin_type_unsigned_int; }
+ | SIGNED typename
+ { $$ = $2.type; }
+ | SIGNED
+ { $$ = builtin_type_int; }
+ ;
+
+typename: TYPENAME
+ | INT_KEYWORD
+ {
+ $$.stoken.ptr = "int";
+ $$.stoken.length = 3;
+ $$.type = builtin_type_int;
+ }
+ | LONG
+ {
+ $$.stoken.ptr = "long";
+ $$.stoken.length = 4;
+ $$.type = builtin_type_long;
+ }
+ | SHORT
+ {
+ $$.stoken.ptr = "short";
+ $$.stoken.length = 5;
+ $$.type = builtin_type_short;
+ }
+ ;
+
+nonempty_typelist
+ : type
+ { $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
+ $$[0] = (struct type *)0;
+ $$[1] = $1;
+ }
+ | nonempty_typelist ',' type
+ { int len = sizeof (struct type *) * ++($<ivec>1[0]);
+ $$ = (struct type **)xrealloc ($1, len);
+ $$[$<ivec>$[0]] = $3;
+ }
+ ;
+
+name : NAME { $$ = $1.stoken; }
+ | BLOCKNAME { $$ = $1.stoken; }
+ | TYPENAME { $$ = $1.stoken; }
+ | NAME_OR_INT { $$ = $1.stoken; }
+ | NAME_OR_UINT { $$ = $1.stoken; }
+ ;
+
+name_not_typename : NAME
+ | BLOCKNAME
+ | NAME_OR_INT
+ | NAME_OR_UINT
+ ;
+
+%%
+\f
+/* Begin counting arguments for a function call,
+ saving the data about any containing call. */
+
+static void
+start_arglist ()
+{
+ register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+
+ new->next = funcall_chain;
+ new->arglist_len = arglist_len;
+ arglist_len = 0;
+ funcall_chain = new;
+}
+
+/* Return the number of arguments in a function call just terminated,
+ and restore the data for the containing function call. */
+
+static int
+end_arglist ()
+{
+ register int val = arglist_len;
+ register struct funcall *call = funcall_chain;
+ funcall_chain = call->next;
+ arglist_len = call->arglist_len;
+ free (call);
+ return val;
+}
+
+/* Free everything in the funcall chain.
+ Used when there is an error inside parsing. */
+
+static void
+free_funcalls ()
+{
+ register struct funcall *call, *next;
+
+ for (call = funcall_chain; call; call = next)
+ {
+ next = call->next;
+ free (call);
+ }
+}
+\f
+/* This page contains the functions for adding data to the struct expression
+ being constructed. */
+
+/* Add one element to the end of the expression. */
+
+/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
+ a register through here */
+
+static void
+write_exp_elt (expelt)
+ union exp_element expelt;
+{
+ if (expout_ptr >= expout_size)
+ {
+ expout_size *= 2;
+ expout = (struct expression *) xrealloc (expout,
+ sizeof (struct expression)
+ + expout_size * sizeof (union exp_element));
+ }
+ expout->elts[expout_ptr++] = expelt;
+}
+
+static void
+write_exp_elt_opcode (expelt)
+ enum exp_opcode expelt;
+{
+ union exp_element tmp;
+
+ tmp.opcode = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_sym (expelt)
+ struct symbol *expelt;
+{
+ union exp_element tmp;
+
+ tmp.symbol = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_longcst (expelt)
+ LONGEST expelt;
+{
+ union exp_element tmp;
+
+ tmp.longconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_dblcst (expelt)
+ double expelt;
+{
+ union exp_element tmp;
+
+ tmp.doubleconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_type (expelt)
+ struct type *expelt;
+{
+ union exp_element tmp;
+
+ tmp.type = expelt;
+
+ write_exp_elt (tmp);
+}
+
+static void
+write_exp_elt_intern (expelt)
+ struct internalvar *expelt;
+{
+ union exp_element tmp;
+
+ tmp.internalvar = expelt;
+
+ write_exp_elt (tmp);
+}
+
+/* Add a string constant to the end of the expression.
+ Follow it by its length in bytes, as a separate exp_element. */
+
+static void
+write_exp_string (str)
+ struct stoken str;
+{
+ register int len = str.length;
+ register int lenelt
+ = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+
+ expout_ptr += lenelt;
+
+ if (expout_ptr >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + 10);
+ expout = (struct expression *)
+ xrealloc (expout, (sizeof (struct expression)
+ + (expout_size * sizeof (union exp_element))));
+ }
+ bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
+ ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+ write_exp_elt_longcst ((LONGEST) len);
+}
+\f
+/* During parsing of a C expression, the pointer to the next character
+ is in this variable. */
+
+static char *lexptr;
+
+/* Tokens that refer to names do so with explicit pointer and length,
+ so they can share the storage that lexptr is parsing.
+
+ When it is necessary to pass a name to a function that expects
+ a null-terminated string, the substring is copied out
+ into a block of storage that namecopy points to.
+
+ namecopy is allocated once, guaranteed big enough, for each parsing. */
+
+static char *namecopy;
+
+/* Current depth in parentheses within the expression. */
+
+static int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses). */
+
+static int comma_terminates;
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ register LONGEST n = 0;
+ register int i;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+
+ extern double atof ();
+
+ if (parsed_float)
+ {
+ /* It's a float since it contains a point or an exponent. */
+ putithere->dval = atof (p);
+ return FLOAT;
+ }
+
+ /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+ if (p[0] == '0')
+ switch (p[1])
+ {
+ case 'x':
+ case 'X':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ case 'd':
+ case 'D':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 10;
+ len -= 2;
+ }
+ break;
+
+ default:
+ base = 8;
+ break;
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ n += i = c - '0';
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ n += i = c - 'a' + 10;
+ else if (len == 0 && c == 'l')
+ ;
+ else if (len == 0 && c == 'u')
+ unsigned_p = 1;
+ else
+ return ERROR; /* Char not a digit */
+ }
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+ }
+
+ if (unsigned_p)
+ {
+ putithere->ulval = n;
+ return UINT;
+ }
+ else
+ {
+ putithere->lval = n;
+ return INT;
+ }
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static struct token tokentab3[] =
+ {
+ {">>=", ASSIGN_MODIFY, BINOP_RSH},
+ {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+ };
+
+static struct token tokentab2[] =
+ {
+ {"+=", ASSIGN_MODIFY, BINOP_ADD},
+ {"-=", ASSIGN_MODIFY, BINOP_SUB},
+ {"*=", ASSIGN_MODIFY, BINOP_MUL},
+ {"/=", ASSIGN_MODIFY, BINOP_DIV},
+ {"%=", ASSIGN_MODIFY, BINOP_REM},
+ {"|=", ASSIGN_MODIFY, BINOP_LOGIOR},
+ {"&=", ASSIGN_MODIFY, BINOP_LOGAND},
+ {"^=", ASSIGN_MODIFY, BINOP_LOGXOR},
+ {"++", INCREMENT, BINOP_END},
+ {"--", DECREMENT, BINOP_END},
+ {"->", ARROW, BINOP_END},
+ {"&&", AND, BINOP_END},
+ {"||", OR, BINOP_END},
+ {"::", COLONCOLON, BINOP_END},
+ {"<<", LSH, BINOP_END},
+ {">>", RSH, BINOP_END},
+ {"==", EQUAL, BINOP_END},
+ {"!=", NOTEQUAL, BINOP_END},
+ {"<=", LEQ, BINOP_END},
+ {">=", GEQ, BINOP_END}
+ };
+
+/* assign machine-independent names to certain registers
+ * (unless overridden by the REGISTER_NAMES table)
+ */
+struct std_regs {
+ char *name;
+ int regnum;
+} std_regs[] = {
+#ifdef PC_REGNUM
+ { "pc", PC_REGNUM },
+#endif
+#ifdef FP_REGNUM
+ { "fp", FP_REGNUM },
+#endif
+#ifdef SP_REGNUM
+ { "sp", SP_REGNUM },
+#endif
+#ifdef PS_REGNUM
+ { "ps", PS_REGNUM },
+#endif
+};
+
+#define NUM_STD_REGS (sizeof std_regs / sizeof std_regs[0])
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ register int c;
+ register int namelen;
+ register unsigned i;
+ register char *tokstart;
+
+ retry:
+
+ tokstart = lexptr;
+ /* See if it is a special token of length 3. */
+ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+ if (!strncmp (tokstart, tokentab3[i].operator, 3))
+ {
+ lexptr += 3;
+ yylval.opcode = tokentab3[i].opcode;
+ return tokentab3[i].token;
+ }
+
+ /* See if it is a special token of length 2. */
+ for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+ if (!strncmp (tokstart, tokentab2[i].operator, 2))
+ {
+ lexptr += 2;
+ yylval.opcode = tokentab2[i].opcode;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ lexptr++;
+ c = *lexptr++;
+ if (c == '\\')
+ c = parse_escape (&lexptr);
+ yylval.lval = c;
+ c = *lexptr++;
+ if (c != '\'')
+ error ("Invalid character constant.");
+ return CHAR;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] < '0' || lexptr[1] > '9')
+ goto symbol; /* Nope, must be a symbol. */
+ /* FALL THRU into number case. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!hex && !got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ /* We will take any letters or digits. parse_number will
+ complain if past the radix, or if L or U are not final. */
+ else if ((*p < '0' || *p > '9')
+ && ((*p < 'a' || *p > 'z')
+ && (*p < 'A' || *p > 'Z')))
+ break;
+ }
+ toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ bcopy (tokstart, err_copy, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ symbol:
+ lexptr++;
+ return c;
+
+ case '"':
+ for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++)
+ if (c == '\\')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ c = tokstart[++namelen];
+ }
+ }
+ yylval.sval.ptr = tokstart + 1;
+ yylval.sval.length = namelen - 1;
+ lexptr += namelen + 1;
+ return STRING;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen])
+ ;
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ lexptr += namelen;
+
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that).
+ Make token type LAST, and put the number (the digits) in yylval. */
+
+ if (*tokstart == '$')
+ {
+ register int negate = 0;
+ c = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (namelen >= 2 && tokstart[1] == '$')
+ {
+ negate = 1;
+ c = 2;
+ }
+ if (c == namelen)
+ {
+ /* Just dollars (one or two) */
+ yylval.lval = - negate;
+ return LAST;
+ }
+ /* Is the rest of the token digits? */
+ for (; c < namelen; c++)
+ if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
+ break;
+ if (c == namelen)
+ {
+ yylval.lval = atoi (tokstart + 1 + negate);
+ if (negate)
+ yylval.lval = - yylval.lval;
+ return LAST;
+ }
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+
+ if (*tokstart == '$') {
+ for (c = 0; c < NUM_REGS; c++)
+ if (namelen - 1 == strlen (reg_names[c])
+ && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+ {
+ yylval.lval = c;
+ return REGNAME;
+ }
+ for (c = 0; c < NUM_STD_REGS; c++)
+ if (namelen - 1 == strlen (std_regs[c].name)
+ && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+ {
+ yylval.lval = std_regs[c].regnum;
+ return REGNAME;
+ }
+ }
+ /* Catch specific keywords. Should be done with a data structure. */
+ switch (namelen)
+ {
+ case 8:
+ if (!strncmp (tokstart, "unsigned", 8))
+ return UNSIGNED;
+ break;
+ case 6:
+ if (!strncmp (tokstart, "struct", 6))
+ return STRUCT;
+ if (!strncmp (tokstart, "signed", 6))
+ return SIGNED;
+ if (!strncmp (tokstart, "sizeof", 6))
+ return SIZEOF;
+ break;
+ case 5:
+ if (!strncmp (tokstart, "union", 5))
+ return UNION;
+ if (!strncmp (tokstart, "short", 5))
+ return SHORT;
+ break;
+ case 4:
+ if (!strncmp (tokstart, "enum", 4))
+ return ENUM;
+ if (!strncmp (tokstart, "long", 4))
+ return LONG;
+ if (!strncmp (tokstart, "this", 4))
+ {
+ static const char this_name[] =
+ { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
+
+ if (lookup_symbol (this_name, expression_context_block,
+ VAR_NAMESPACE, 0, NULL))
+ return THIS;
+ }
+ break;
+ case 3:
+ if (!strncmp (tokstart, "int", 3))
+ return INT_KEYWORD;
+ break;
+ default:
+ break;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ if (*tokstart == '$')
+ {
+ yylval.ivar = lookup_internalvar (copy_name (yylval.sval) + 1);
+ return VARIABLE;
+ }
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions or symtabs. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+ int is_a_field_of_this = 0;
+ int hextype;
+
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, &is_a_field_of_this, NULL);
+ if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
+ lookup_partial_symtab (tmp))
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return BLOCKNAME;
+ }
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym &&
+ ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
+ (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ if (hextype == UINT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_UINT;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+static void
+yyerror (msg)
+ char *msg;
+{
+ error ("Invalid syntax in expression.");
+}
+
+/* Return a null-terminated temporary copy of the name
+ of a string token. */
+
+static char *
+copy_name (token)
+ struct stoken token;
+{
+ bcopy (token.ptr, namecopy, token.length);
+ namecopy[token.length] = 0;
+ return namecopy;
+}
+\f
+/* Reverse an expression from suffix form (in which it is constructed)
+ to prefix form (in which we can conveniently print or execute it). */
+
+static void prefixify_subexp ();
+
+static void
+prefixify_expression (expr)
+ register struct expression *expr;
+{
+ register int len = sizeof (struct expression) +
+ expr->nelts * sizeof (union exp_element);
+ register struct expression *temp;
+ register int inpos = expr->nelts, outpos = 0;
+
+ temp = (struct expression *) alloca (len);
+
+ /* Copy the original expression into temp. */
+ bcopy (expr, temp, len);
+
+ prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the subexpression of EXPR
+ whose last exp_element is at index ENDPOS - 1 in EXPR. */
+
+static int
+length_of_subexp (expr, endpos)
+ register struct expression *expr;
+ register int endpos;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+
+ if (endpos < 0)
+ error ("?error in length_of_subexp");
+
+ i = (int) expr->elts[endpos - 1].opcode;
+
+ switch (i)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((expr->elts[endpos - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ oplen = 4;
+ break;
+
+ case OP_VAR_VALUE:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + expr->elts[endpos - 2].longconst;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ case OP_STRING:
+ oplen = 3 + ((expr->elts[endpos - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + (i < (int) BINOP_END);
+ }
+
+ while (args > 0)
+ {
+ oplen += length_of_subexp (expr, endpos - oplen);
+ args--;
+ }
+
+ return oplen;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+ into OUTEXPR, starting at index OUTBEG.
+ In the process, convert it from suffix to prefix form. */
+
+static void
+prefixify_subexp (inexpr, outexpr, inend, outbeg)
+ register struct expression *inexpr;
+ struct expression *outexpr;
+ register int inend;
+ int outbeg;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+ int *arglens;
+ enum exp_opcode opcode;
+
+ /* Compute how long the last operation is (in OPLEN),
+ and also how many preceding subexpressions serve as
+ arguments for it (in ARGS). */
+
+ opcode = inexpr->elts[inend - 1].opcode;
+ switch (opcode)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = 4 + ((inexpr->elts[inend - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ oplen = 4;
+ break;
+
+ case OP_VAR_VALUE:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + inexpr->elts[inend - 2].longconst;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ case OP_STRING:
+ oplen = 3 + ((inexpr->elts[inend - 2].longconst
+ + sizeof (union exp_element))
+ / sizeof (union exp_element));
+
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + ((int) opcode < (int) BINOP_END);
+ }
+
+ /* Copy the final operator itself, from the end of the input
+ to the beginning of the output. */
+ inend -= oplen;
+ bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg],
+ oplen * sizeof (union exp_element));
+ outbeg += oplen;
+
+ /* Find the lengths of the arg subexpressions. */
+ arglens = (int *) alloca (args * sizeof (int));
+ for (i = args - 1; i >= 0; i--)
+ {
+ oplen = length_of_subexp (inexpr, inend);
+ arglens[i] = oplen;
+ inend -= oplen;
+ }
+
+ /* Now copy each subexpression, preserving the order of
+ the subexpressions, but prefixifying each one.
+ In this loop, inend starts at the beginning of
+ the expression this level is working on
+ and marches forward over the arguments.
+ outbeg does similarly in the output. */
+ for (i = 0; i < args; i++)
+ {
+ oplen = arglens[i];
+ inend += oplen;
+ prefixify_subexp (inexpr, outexpr, inend, outbeg);
+ outbeg += oplen;
+ }
+}
+\f
+/* This page contains the two entry points to this file. */
+
+/* Read a C expression from the string *STRINGPTR points to,
+ parse it, and return a pointer to a struct expression that we malloc.
+ Use block BLOCK as the lexical context for variable names;
+ if BLOCK is zero, use the block of the selected stack frame.
+ Meanwhile, advance *STRINGPTR to point after the expression,
+ at the first nonwhite character that is not part of the expression
+ (possibly a null character).
+
+ If COMMA is nonzero, stop if a comma is reached. */
+
+struct expression *
+parse_c_1 (stringptr, block, comma)
+ char **stringptr;
+ struct block *block;
+ int comma;
+{
+ struct cleanup *old_chain;
+
+ lexptr = *stringptr;
+
+ paren_depth = 0;
+ type_stack_depth = 0;
+
+ comma_terminates = comma;
+
+ if (lexptr == 0 || *lexptr == 0)
+ error_no_arg ("expression to compute");
+
+ old_chain = make_cleanup (free_funcalls, 0);
+ funcall_chain = 0;
+
+ expression_context_block = block ? block : get_selected_block ();
+
+ namecopy = (char *) alloca (strlen (lexptr) + 1);
+ expout_size = 10;
+ expout_ptr = 0;
+ expout = (struct expression *)
+ xmalloc (sizeof (struct expression)
+ + expout_size * sizeof (union exp_element));
+ make_cleanup (free_current_contents, &expout);
+ if (yyparse ())
+ yyerror (NULL);
+ discard_cleanups (old_chain);
+ expout->nelts = expout_ptr;
+ expout = (struct expression *)
+ xrealloc (expout,
+ sizeof (struct expression)
+ + expout_ptr * sizeof (union exp_element));
+ prefixify_expression (expout);
+ *stringptr = lexptr;
+ return expout;
+}
+
+/* Parse STRING as an expression, and complain if this fails
+ to use up all of the contents of STRING. */
+
+struct expression *
+parse_c_expression (string)
+ char *string;
+{
+ register struct expression *exp;
+ exp = parse_c_1 (&string, 0, 0);
+ if (*string)
+ error ("Junk after end of expression.");
+ return exp;
+}
+
+static void
+push_type (tp)
+ enum type_pieces tp;
+{
+ if (type_stack_depth == type_stack_size)
+ {
+ type_stack_size *= 2;
+ type_stack = (enum type_pieces *)
+ xrealloc (type_stack, type_stack_size * sizeof (enum type_pieces));
+ }
+ type_stack[type_stack_depth++] = tp;
+}
+
+static enum type_pieces
+pop_type ()
+{
+ if (type_stack_depth)
+ return type_stack[--type_stack_depth];
+ return tp_end;
+}
+
+void
+_initialize_expread ()
+{
+ type_stack_size = 80;
+ type_stack_depth = 0;
+ type_stack = (enum type_pieces *)
+ xmalloc (type_stack_size * sizeof (enum type_pieces));
+}
--- /dev/null
+#ifdef BSD
+#ifndef BSD4_1
+#define HAVE_GETPAGESIZE
+#endif
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+
+#include <sys/param.h>
+
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#define getpagesize() NBPC
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+
+#endif /* not HAVE_GETPAGESIZE */
+
--- /dev/null
+
+/* gmalloc.c - THIS FILE IS AUTOMAGICALLY GENERATED SO DON'T EDIT IT. */
+
+/* Single-file skeleton for GNU malloc.
+ Copyright 1989 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#define __ONEFILE
+
+/* DO NOT DELETE THIS LINE -- ansidecl.h INSERTED HERE. */
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the GNU C Library; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macros
+ PTR - Generic pointer type
+ LONG_DOUBLE - `long double' type
+ CONST - `const' keyword
+ VOLATILE - `volatile' keyword
+ SIGNED - `signed' keyword
+ PTRCONST - Generic const pointer (void *const)
+
+ EXFUN(name, prototype) - declare external function NAME
+ with prototype PROTOTYPE
+ DEFUN(name, arglist, args) - define function NAME with
+ args ARGLIST of types in ARGS
+ DEFUN_VOID(name) - define function NAME with no args
+ AND - argument separator for ARGS
+ NOARGS - null arglist
+ DOTS - `...' in args
+
+ For example:
+ extern int EXFUN(printf, (CONST char *format DOTS));
+ int DEFUN(fprintf, (stream, format),
+ FILE *stream AND CONST char *format DOTS) { ... }
+ void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef _ANSIDECL_H
+
+#define _ANSIDECL_H 1
+
+
+/* Every source file includes this file,
+ so they will all get the switch for lint. */
+/* LINTLIBRARY */
+
+
+#ifdef __STDC__
+
+#define PTR void *
+#define PTRCONST void *CONST
+#define LONG_DOUBLE long double
+
+#define AND ,
+#define NOARGS void
+#define CONST const
+#define VOLATILE volatile
+#define SIGNED signed
+#define DOTS , ...
+
+#define EXFUN(name, proto) name proto
+#define DEFUN(name, arglist, args) name(args)
+#define DEFUN_VOID(name) name(NOARGS)
+
+#else /* Not ANSI C. */
+
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define AND ;
+#define NOARGS
+#define CONST
+#define VOLATILE
+#define SIGNED
+#define DOTS
+
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+
+#endif /* ANSI C. */
+
+
+#endif /* ansidecl.h */
+
+#ifdef __STDC__
+#include <limits.h>
+#else
+/* DO NOT DELETE THIS LINE -- limits.h INSERTED HERE. */
+/* Number of bits in a `char'. */
+#define CHAR_BIT 8
+
+/* No multibyte characters supported yet. */
+#define MB_LEN_MAX 1
+
+/* Minimum and maximum values a `signed char' can hold. */
+#define SCHAR_MIN -128
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0). */
+#define UCHAR_MAX 255U
+
+/* Minimum and maximum values a `char' can hold. */
+#ifdef __CHAR_UNSIGNED__
+#define CHAR_MIN 0
+#define CHAR_MAX 255U
+#else
+#define CHAR_MIN -128
+#define CHAR_MAX 127
+#endif
+
+/* Minimum and maximum values a `signed short int' can hold. */
+#define SHRT_MIN -32768
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */
+#define USHRT_MAX 65535U
+
+/* Minimum and maximum values a `signed int' can hold. */
+#define INT_MIN -2147483648
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0). */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long int' can hold.
+ (Same as `int'). */
+#define LONG_MIN (-LONG_MAX-1)
+#define LONG_MAX 2147483647
+
+/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */
+#define ULONG_MAX 4294967295U
+#endif
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+/* DO NOT DELETE THIS LINE -- stddef.h INSERTED HERE. */
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+/* Signed type of difference of two pointers. */
+
+typedef long ptrdiff_t;
+
+/* Unsigned type of `sizeof' something. */
+
+#ifndef _SIZE_T /* in case <sys/types.h> has defined it. */
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif /* _SIZE_T */
+
+/* A null pointer constant. */
+
+#undef NULL /* in case <stdio.h> has defined it. */
+#define NULL 0
+
+/* Offset of member MEMBER in a struct of type TYPE. */
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* _STDDEF_H */
+#endif
+
+/* DO NOT DELETE THIS LINE -- stdlib.h INSERTED HERE. */
+/* Fake stdlib.h supplying the stuff needed by malloc. */
+
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern void EXFUN(abort, (void));
+extern void EXFUN(free, (PTR));
+extern PTR EXFUN(malloc, (size_t));
+extern PTR EXFUN(realloc, (PTR, size_t));
+
+/* DO NOT DELETE THIS LINE -- string.h INSERTED HERE. */
+/* Fake string.h supplying stuff used by malloc. */
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern PTR EXFUN(memcpy, (PTR, PTR, size_t));
+extern PTR EXFUN(memset, (PTR, int, size_t));
+#define memmove memcpy
+
+#define _MALLOC_INTERNAL
+/* DO NOT DELETE THIS LINE -- malloc.h INSERTED HERE. */
+/* Declarations for `malloc' and friends.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H 1
+
+#ifndef __ONEFILE
+#define __need_NULL
+#define __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+#endif
+
+#ifdef _MALLOC_INTERNAL
+
+#ifndef __ONEFILE
+#include <limits.h>
+#endif
+
+/* The allocator divides the heap into blocks of fixed size; large
+ requests receive one or more whole blocks, and small requests
+ receive a fragment of a block. Fragment sizes are powers of two,
+ and all fragments of a block are the same size. When all the
+ fragments in a block have been freed, the block itself is freed. */
+#define INT_BIT (CHAR_BIT * sizeof(int))
+#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+ (not an absolute limit). */
+#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+ memory before they will be returned to the system. */
+#define FINAL_FREE_BLOCKS 8
+
+/* Where to start searching the free list when looking for new memory.
+ The two possible values are 0 and _heapindex. Starting at 0 seems
+ to reduce total memory usage, while starting at _heapindex seems to
+ run faster. */
+#define MALLOC_SEARCH_START _heapindex
+
+/* Data structure giving per-block information. */
+typedef union
+ {
+ /* Heap information for a busy block. */
+ struct
+ {
+ /* Zero for a large block, or positive giving the
+ logarithm to the base two of the fragment size. */
+ int type;
+ union
+ {
+ struct
+ {
+ size_t nfree; /* Free fragments in a fragmented block. */
+ size_t first; /* First free fragment of the block. */
+ } frag;
+ /* Size (in blocks) of a large cluster. */
+ size_t size;
+ } info;
+ } busy;
+ /* Heap information for a free block (that may be the first of
+ a free cluster). */
+ struct
+ {
+ size_t size; /* Size (in blocks) of a free cluster. */
+ size_t next; /* Index of next free cluster. */
+ size_t prev; /* Index of previous free cluster. */
+ } free;
+ } malloc_info;
+
+/* Pointer to first block of the heap. */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information. */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa. */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table. */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices. */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments. */
+struct list
+ {
+ struct list *next;
+ struct list *prev;
+ };
+
+/* Free list headers for each fragment size. */
+extern struct list _fraghead[];
+
+/* Instrumentation. */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of free() used in morecore(). */
+extern void EXFUN(__free, (PTR __ptr));
+
+#endif /* _MALLOC_INTERNAL. */
+
+/* Underlying allocation function; successive calls should
+ return contiguous pieces of memory. */
+extern PTR EXFUN((*__morecore), (ptrdiff_t __size));
+
+/* Default value of previous. */
+extern PTR EXFUN(__default_morecore, (ptrdiff_t __size));
+
+/* Flag whether malloc has been called. */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions. */
+extern void EXFUN((*__free_hook), (PTR __ptr));
+extern PTR EXFUN((*__malloc_hook), (size_t __size));
+extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks. */
+extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
+
+/* Statistics available to the user. */
+struct mstats
+ {
+ size_t bytes_total; /* Total size of the heap. */
+ size_t chunks_used; /* Chunks allocated by the user. */
+ size_t bytes_used; /* Byte total of user-allocated chunks. */
+ size_t chunks_free; /* Chunks in the free list. */
+ size_t bytes_free; /* Byte total of chunks in the free list. */
+ };
+
+/* Pick up the current statistics. */
+extern struct mstats EXFUN(mstats, (NOARGS));
+
+#endif /* malloc.h */
+
+/* DO NOT DELETE THIS LINE -- free.c INSERTED HERE. */
+/* Free a block of memory allocated by `malloc'.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* Debugging hook for free. */
+void EXFUN((*__free_hook), (PTR __ptr));
+
+/* Return memory to the heap. Like free() but don't call a __free_hook
+ if there is one. */
+void
+DEFUN(__free, (ptr), PTR ptr)
+{
+ int type;
+ size_t block, blocks;
+ register size_t i;
+ struct list *prev, *next;
+
+ block = BLOCK(ptr);
+
+ type = _heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Get as many statistics as early as we can. */
+ --_chunks_used;
+ _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+ _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+ /* Find the free cluster previous to this one in the free list.
+ Start searching at the last block referenced; this may benefit
+ programs with locality of allocation. */
+ i = _heapindex;
+ if (i > block)
+ while (i > block)
+ i = _heapinfo[i].free.prev;
+ else
+ {
+ do
+ i = _heapinfo[i].free.next;
+ while (i > 0 && i < block);
+ i = _heapinfo[i].free.prev;
+ }
+
+ /* Determine how to link this block into the free list. */
+ if (block == i + _heapinfo[i].free.size)
+ {
+ /* Coalesce this block with its predecessor. */
+ _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+ block = i;
+ }
+ else
+ {
+ /* Really link this block back into the free list. */
+ _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+ _heapinfo[block].free.next = _heapinfo[i].free.next;
+ _heapinfo[block].free.prev = i;
+ _heapinfo[i].free.next = block;
+ _heapinfo[_heapinfo[block].free.next].free.prev = block;
+ ++_chunks_free;
+ }
+
+ /* Now that the block is linked in, see if we can coalesce it
+ with its successor (by deleting its successor from the list
+ and adding in its size). */
+ if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+ {
+ _heapinfo[block].free.size
+ += _heapinfo[_heapinfo[block].free.next].free.size;
+ _heapinfo[block].free.next
+ = _heapinfo[_heapinfo[block].free.next].free.next;
+ _heapinfo[_heapinfo[block].free.next].free.prev = block;
+ --_chunks_free;
+ }
+
+ /* Now see if we can return stuff to the system. */
+ blocks = _heapinfo[block].free.size;
+ if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+ && (*__morecore)(0) == ADDRESS(block + blocks))
+ {
+ register size_t bytes = blocks * BLOCKSIZE;
+ _heaplimit -= blocks;
+ (*__morecore)(- bytes);
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapinfo[block].free.next;
+ _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapinfo[block].free.prev;
+ block = _heapinfo[block].free.prev;
+ --_chunks_free;
+ _bytes_free -= bytes;
+ }
+
+ /* Set the next search to begin at this block. */
+ _heapindex = block;
+ break;
+
+ default:
+ /* Do some of the statistics. */
+ --_chunks_used;
+ _bytes_used -= 1 << type;
+ ++_chunks_free;
+ _bytes_free += 1 << type;
+
+ /* Get the address of the first free fragment in this block. */
+ prev = (struct list *) ((char *) ADDRESS(block) +
+ (_heapinfo[block].busy.info.frag.first << type));
+
+ if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+ {
+ /* If all fragments of this block are free, remove them
+ from the fragment list and free the whole block. */
+ next = prev;
+ for (i = 1; i < BLOCKSIZE >> type; ++i)
+ next = next->next;
+ prev->prev->next = next;
+ if (next != NULL)
+ next->prev = prev->prev;
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = 1;
+
+ /* Keep the statistics accurate. */
+ ++_chunks_used;
+ _bytes_used += BLOCKSIZE;
+ _chunks_free -= BLOCKSIZE >> type;
+ _bytes_free -= BLOCKSIZE;
+
+ free(ADDRESS(block));
+ }
+ else if (_heapinfo[block].busy.info.frag.nfree != 0)
+ {
+ /* If some fragments of this block are free, link this
+ fragment into the fragment list after the first free
+ fragment of this block. */
+ next = (struct list *) ptr;
+ next->next = prev->next;
+ next->prev = prev;
+ prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ ++_heapinfo[block].busy.info.frag.nfree;
+ }
+ else
+ {
+ /* No fragments of this block are free, so link this
+ fragment into the fragment list and announce that
+ it is the first free fragment of this block. */
+ prev = (struct list *) ptr;
+ _heapinfo[block].busy.info.frag.nfree = 1;
+ _heapinfo[block].busy.info.frag.first = (unsigned int)
+ (((char *) ptr - (char *) NULL) % BLOCKSIZE >> type);
+ prev->next = _fraghead[type].next;
+ prev->prev = &_fraghead[type];
+ prev->prev->next = prev;
+ if (prev->next != NULL)
+ prev->next->prev = prev;
+ }
+ break;
+ }
+}
+
+/* Return memory to the heap. */
+void
+DEFUN(free, (ptr), PTR ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ if (__free_hook != NULL)
+ (*__free_hook)(ptr);
+ else
+ __free (ptr);
+}
+
+/* DO NOT DELETE THIS LINE -- malloc.c INSERTED HERE. */
+/* Memory allocator `malloc'.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* How to really get more memory. */
+PTR EXFUN((*__morecore), (ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'. */
+PTR EXFUN((*__malloc_hook), (size_t __size));
+
+/* Pointer to the base of the first block. */
+char *_heapbase;
+
+/* Block information table. Allocated with align/__free (not malloc/free). */
+malloc_info *_heapinfo;
+
+/* Number of info entries. */
+static size_t heapsize;
+
+/* Search index in the info table. */
+size_t _heapindex;
+
+/* Limit of valid info table indices. */
+size_t _heaplimit;
+
+/* Free lists for each fragment size. */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation. */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced? */
+int __malloc_initialized;
+
+/* Aligned allocation. */
+static PTR
+DEFUN(align, (size), size_t size)
+{
+ PTR result;
+ unsigned int adj;
+
+ result = (*__morecore)(size);
+ adj = (unsigned int) ((char *) result - (char *) NULL) % BLOCKSIZE;
+ if (adj != 0)
+ {
+ adj = BLOCKSIZE - adj;
+ (void) (*__morecore)(adj);
+ result = (char *) result + adj;
+ }
+ return result;
+}
+
+/* Set everything up and remember that we have. */
+static int
+DEFUN_VOID(initialize)
+{
+ heapsize = HEAP / BLOCKSIZE;
+ _heapinfo = (malloc_info *) align(heapsize * sizeof(malloc_info));
+ if (_heapinfo == NULL)
+ return 0;
+ memset(_heapinfo, 0, heapsize * sizeof(malloc_info));
+ _heapinfo[0].free.size = 0;
+ _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+ _heapindex = 0;
+ _heapbase = (char *) _heapinfo;
+ __malloc_initialized = 1;
+ return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+ growing the heap info table as necessary. */
+static PTR
+DEFUN(morecore, (size), size_t size)
+{
+ PTR result;
+ malloc_info *newinfo, *oldinfo;
+ size_t newsize;
+
+ result = align(size);
+ if (result == NULL)
+ return NULL;
+
+ /* Check if we need to grow the info table. */
+ if (BLOCK((char *) result + size) > heapsize)
+ {
+ newsize = heapsize;
+ while (BLOCK((char *) result + size) > newsize)
+ newsize *= 2;
+ newinfo = (malloc_info *) align(newsize * sizeof(malloc_info));
+ if (newinfo == NULL)
+ {
+ (*__morecore)(- size);
+ return NULL;
+ }
+ memset(newinfo, 0, newsize * sizeof(malloc_info));
+ memcpy(newinfo, _heapinfo, heapsize * sizeof(malloc_info));
+ oldinfo = _heapinfo;
+ newinfo[BLOCK(oldinfo)].busy.type = 0;
+ newinfo[BLOCK(oldinfo)].busy.info.size
+ = BLOCKIFY(heapsize * sizeof(malloc_info));
+ _heapinfo = newinfo;
+ __free(oldinfo);
+ heapsize = newsize;
+ }
+
+ _heaplimit = BLOCK((char *) result + size);
+ return result;
+}
+
+/* Allocate memory from the heap. */
+PTR
+DEFUN(malloc, (size), size_t size)
+{
+ PTR result;
+ size_t block, blocks, lastblocks, start;
+ register size_t i;
+ struct list *next;
+
+ if (size == 0)
+ return NULL;
+
+ if (__malloc_hook != NULL)
+ return (*__malloc_hook)(size);
+
+ if (!__malloc_initialized)
+ if (!initialize())
+ return NULL;
+
+ if (size < sizeof(struct list))
+ size = sizeof(struct list);
+
+ /* Determine the allocation policy based on the request size. */
+ if (size <= BLOCKSIZE / 2)
+ {
+ /* Small allocation to receive a fragment of a block.
+ Determine the logarithm to base two of the fragment size. */
+ register size_t log = 1;
+ --size;
+ while ((size /= 2) != 0)
+ ++log;
+
+ /* Look in the fragment lists for a
+ free fragment of the desired size. */
+ next = _fraghead[log].next;
+ if (next != NULL)
+ {
+ /* There are free fragments of this size.
+ Pop a fragment out of the fragment list and return it.
+ Update the block's nfree and first counters. */
+ result = (PTR) next;
+ next->prev->next = next->next;
+ if (next->next != NULL)
+ next->next->prev = next->prev;
+ block = BLOCK(result);
+ if (--_heapinfo[block].busy.info.frag.nfree != 0)
+ _heapinfo[block].busy.info.frag.first = (unsigned int)
+ (((char *) next->next - (char *) NULL) % BLOCKSIZE) >> log;
+
+ /* Update the statistics. */
+ ++_chunks_used;
+ _bytes_used += 1 << log;
+ --_chunks_free;
+ _bytes_free -= 1 << log;
+ }
+ else
+ {
+ /* No free fragments of the desired size, so get a new block
+ and break it into fragments, returning the first. */
+ result = malloc(BLOCKSIZE);
+ if (result == NULL)
+ return NULL;
+
+ /* Link all fragments but the first into the free list. */
+ for (i = 1; i < BLOCKSIZE >> log; ++i)
+ {
+ next = (struct list *) ((char *) result + (i << log));
+ next->next = _fraghead[log].next;
+ next->prev = &_fraghead[log];
+ next->prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ }
+
+ /* Initialize the nfree and first counters for this block. */
+ block = BLOCK(result);
+ _heapinfo[block].busy.type = log;
+ _heapinfo[block].busy.info.frag.nfree = i - 1;
+ _heapinfo[block].busy.info.frag.first = i - 1;
+
+ _chunks_free += (BLOCKSIZE >> log) - 1;
+ _bytes_free += BLOCKSIZE - (1 << log);
+ }
+ }
+ else
+ {
+ /* Large allocation to receive one or more blocks.
+ Search the free list in a circle starting at the last place visited.
+ If we loop completely around without finding a large enough
+ space we will have to get more memory from the system. */
+ blocks = BLOCKIFY(size);
+ start = block = MALLOC_SEARCH_START;
+ while (_heapinfo[block].free.size < blocks)
+ {
+ block = _heapinfo[block].free.next;
+ if (block == start)
+ {
+ /* Need to get more from the system. Check to see if
+ the new core will be contiguous with the final free
+ block; if so we don't need to get as much. */
+ block = _heapinfo[0].free.prev;
+ lastblocks = _heapinfo[block].free.size;
+ if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+ (*__morecore)(0) == ADDRESS(block + lastblocks) &&
+ (morecore((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+ {
+ _heapinfo[block].free.size = blocks;
+ _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+ continue;
+ }
+ result = morecore(blocks * BLOCKSIZE);
+ if (result == NULL)
+ return NULL;
+ block = BLOCK(result);
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = blocks;
+ ++_chunks_used;
+ _bytes_used += blocks * BLOCKSIZE;
+ return result;
+ }
+ }
+
+ /* At this point we have found a suitable free list entry.
+ Figure out how to remove what we need from the list. */
+ result = ADDRESS(block);
+ if (_heapinfo[block].free.size > blocks)
+ {
+ /* The block we found has a bit left over,
+ so relink the tail end back into the free list. */
+ _heapinfo[block + blocks].free.size
+ = _heapinfo[block].free.size - blocks;
+ _heapinfo[block + blocks].free.next
+ = _heapinfo[block].free.next;
+ _heapinfo[block + blocks].free.prev
+ = _heapinfo[block].free.prev;
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapindex = block + blocks;
+ }
+ else
+ {
+ /* The block exactly matches our requirements,
+ so just remove it from the list. */
+ _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapinfo[block].free.prev;
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapindex = _heapinfo[block].free.next;
+ --_chunks_free;
+ }
+
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = blocks;
+ ++_chunks_used;
+ _bytes_used += blocks * BLOCKSIZE;
+ _bytes_free -= blocks * BLOCKSIZE;
+ }
+
+ return result;
+}
+
+/* DO NOT DELETE THIS LINE -- realloc.c INSERTED HERE. */
+/* Change the size of a block allocated by `malloc'.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc. */
+PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+ to the (possibly moved) region. This is optimized for speed;
+ some benchmarks seem to indicate that greater compactness is
+ achieved by unconditionally allocating and copying to a
+ new region. This module has incestuous knowledge of the
+ internals of both free and malloc. */
+PTR
+DEFUN(realloc, (ptr, size), PTR ptr AND size_t size)
+{
+ PTR result;
+ int type;
+ size_t block, blocks, oldlimit;
+
+ if (size == 0)
+ {
+ free(ptr);
+ return NULL;
+ }
+ else if (ptr == NULL)
+ return malloc(size);
+
+ if (__realloc_hook != NULL)
+ return (*__realloc_hook)(ptr, size);
+
+ block = BLOCK(ptr);
+
+ type = _heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Maybe reallocate a large block to a small fragment. */
+ if (size <= BLOCKSIZE / 2)
+ {
+ result = malloc(size);
+ if (result != NULL)
+ {
+ memcpy(result, ptr, size);
+ free(ptr);
+ return result;
+ }
+ }
+
+ /* The new size is a large allocation as well;
+ see if we can hold it in place. */
+ blocks = BLOCKIFY(size);
+ if (blocks < _heapinfo[block].busy.info.size)
+ {
+ /* The new size is smaller; return
+ excess memory to the free list. */
+ _heapinfo[block + blocks].busy.type = 0;
+ _heapinfo[block + blocks].busy.info.size
+ = _heapinfo[block].busy.info.size - blocks;
+ _heapinfo[block].busy.info.size = blocks;
+ free(ADDRESS(block + blocks));
+ result = ptr;
+ }
+ else if (blocks == _heapinfo[block].busy.info.size)
+ /* No size change necessary. */
+ result = ptr;
+ else
+ {
+ /* Won't fit, so allocate a new region that will.
+ Free the old region first in case there is sufficient
+ adjacent free space to grow without moving. */
+ blocks = _heapinfo[block].busy.info.size;
+ /* Prevent free from actually returning memory to the system. */
+ oldlimit = _heaplimit;
+ _heaplimit = 0;
+ free(ptr);
+ _heaplimit = oldlimit;
+ result = malloc(size);
+ if (result == NULL)
+ {
+ (void) malloc(blocks * BLOCKSIZE);
+ return NULL;
+ }
+ if (ptr != result)
+ memmove(result, ptr, blocks * BLOCKSIZE);
+ }
+ break;
+
+ default:
+ /* Old size is a fragment; type is logarithm
+ to base two of the fragment size. */
+ if (size > 1 << (type - 1) && size <= 1 << type)
+ /* The new size is the same kind of fragment. */
+ result = ptr;
+ else
+ {
+ /* The new size is different; allocate a new space,
+ and copy the lesser of the new size and the old. */
+ result = malloc(size);
+ if (result == NULL)
+ return NULL;
+ memcpy(result, ptr, MIN(size, 1 << type));
+ free(ptr);
+ }
+ break;
+ }
+
+ return result;
+}
+
+/* DO NOT DELETE THIS LINE -- unix.c INSERTED HERE. */
+/* unix.c - get more memory with a UNIX system call.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+extern PTR EXFUN(sbrk, (ptrdiff_t size));
+
+PTR
+DEFUN(__default_morecore, (size), ptrdiff_t size)
+{
+ PTR result;
+
+ result = sbrk(size);
+ if (result == (PTR) -1)
+ return NULL;
+ return result;
+}
+
+#define __getpagesize getpagesize
+/* DO NOT DELETE THIS LINE -- valloc.c INSERTED HERE. */
+/* Allocate memory on a page boundary.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#endif /* __ONEFILE */
+
+extern size_t EXFUN(__getpagesize, (NOARGS));
+
+static size_t pagesize;
+
+PTR
+DEFUN(valloc, (size), size_t size)
+{
+ PTR result;
+ unsigned int adj;
+
+ if (pagesize == 0)
+ pagesize = __getpagesize();
+
+ result = malloc(size + pagesize);
+ if (result == NULL)
+ return NULL;
+ adj = (unsigned int) ((char *) result - (char *) NULL) % pagesize;
+ if (adj != 0)
+ result = (char *) result + pagesize - adj;
+ return result;
+}
--- /dev/null
+/* Declarations for `malloc' and friends.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H 1
+
+#ifndef __ONEFILE
+#define __need_NULL
+#define __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+#endif
+
+#ifdef _MALLOC_INTERNAL
+
+#ifndef __ONEFILE
+#include <limits.h>
+#endif
+
+/* The allocator divides the heap into blocks of fixed size; large
+ requests receive one or more whole blocks, and small requests
+ receive a fragment of a block. Fragment sizes are powers of two,
+ and all fragments of a block are the same size. When all the
+ fragments in a block have been freed, the block itself is freed. */
+#define INT_BIT (CHAR_BIT * sizeof(int))
+#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+ (not an absolute limit). */
+#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+ memory before they will be returned to the system. */
+#define FINAL_FREE_BLOCKS 8
+
+/* Where to start searching the free list when looking for new memory.
+ The two possible values are 0 and _heapindex. Starting at 0 seems
+ to reduce total memory usage, while starting at _heapindex seems to
+ run faster. */
+#define MALLOC_SEARCH_START _heapindex
+
+/* Data structure giving per-block information. */
+typedef union
+ {
+ /* Heap information for a busy block. */
+ struct
+ {
+ /* Zero for a large block, or positive giving the
+ logarithm to the base two of the fragment size. */
+ int type;
+ union
+ {
+ struct
+ {
+ size_t nfree; /* Free fragments in a fragmented block. */
+ size_t first; /* First free fragment of the block. */
+ } frag;
+ /* Size (in blocks) of a large cluster. */
+ size_t size;
+ } info;
+ } busy;
+ /* Heap information for a free block (that may be the first of
+ a free cluster). */
+ struct
+ {
+ size_t size; /* Size (in blocks) of a free cluster. */
+ size_t next; /* Index of next free cluster. */
+ size_t prev; /* Index of previous free cluster. */
+ } free;
+ } malloc_info;
+
+/* Pointer to first block of the heap. */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information. */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa. */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table. */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices. */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments. */
+struct list
+ {
+ struct list *next;
+ struct list *prev;
+ };
+
+/* Free list headers for each fragment size. */
+extern struct list _fraghead[];
+
+/* Instrumentation. */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of free() used in morecore(). */
+extern void EXFUN(__free, (PTR __ptr));
+
+#endif /* _MALLOC_INTERNAL. */
+
+/* Underlying allocation function; successive calls should
+ return contiguous pieces of memory. */
+extern PTR EXFUN((*__morecore), (ptrdiff_t __size));
+
+/* Default value of previous. */
+extern PTR EXFUN(__default_morecore, (ptrdiff_t __size));
+
+/* Flag whether malloc has been called. */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions. */
+extern void EXFUN((*__free_hook), (PTR __ptr));
+extern PTR EXFUN((*__malloc_hook), (size_t __size));
+extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks. */
+extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
+
+/* Statistics available to the user. */
+struct mstats
+ {
+ size_t bytes_total; /* Total size of the heap. */
+ size_t chunks_used; /* Chunks allocated by the user. */
+ size_t bytes_used; /* Byte total of user-allocated chunks. */
+ size_t chunks_free; /* Chunks in the free list. */
+ size_t bytes_free; /* Byte total of chunks in the free list. */
+ };
+
+/* Pick up the current statistics. */
+extern struct mstats EXFUN(mstats, (NOARGS));
+
+#endif /* malloc.h */
--- /dev/null
+/* Print GOULD RISC instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "gdbcore.h"
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#if defined GOULD_PN
+#include "pn-opcode.h"
+#else
+#include "np1-opcode.h"
+#endif
+
+/* GOULD RISC instructions are never longer than this many bytes. */
+#define MAXLEN 4
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof gld_opcodes / sizeof gld_opcodes[0])
+
+\f
+/* Print the GOULD instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register char *d;
+ register int bestmask;
+ unsigned best;
+ int temp, index, bestlen;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ bestmask = 0;
+ index = -1;
+ best = 0xffffffff;
+ for (i = 0; i < NOPCODES; i++)
+ {
+ register unsigned int opcode = gld_opcodes[i].opcode;
+ register unsigned int mask = gld_opcodes[i].mask;
+ register unsigned int len = gld_opcodes[i].length;
+ register unsigned int test;
+
+ /* Get possible opcode bytes into integer */
+ test = buffer[0] << 24;
+ test |= buffer[1] << 16;
+ test |= buffer[2] << 8;
+ test |= buffer[3];
+
+ /* Mask with opcode and see if match */
+ if ((opcode & mask) == (test & mask))
+ {
+ /* See if second or third match */
+ if (index >= 0)
+ {
+ /* Take new one if it looks good */
+ if (bestlen == MAXLEN && len == MAXLEN)
+ {
+ /* See if lower bits matched */
+ if (((bestmask & 3) == 0) &&
+ ((mask & 3) != 0))
+ {
+ bestmask = mask;
+ bestlen = len;
+ best = test;
+ index = i;
+ }
+ }
+ }
+ else
+ {
+ /* First match, save it */
+ bestmask = mask;
+ bestlen = len;
+ best = test;
+ index = i;
+ }
+ }
+ }
+
+ /* Handle undefined instructions. */
+ if (index < 0)
+ {
+ fprintf (stream, "undefined 0%o",(buffer[0]<<8)+buffer[1]);
+ return 2;
+ }
+
+ /* Print instruction name */
+ fprintf (stream, "%-12s", gld_opcodes[index].name);
+
+ /* Adjust if short instruction */
+ if (gld_opcodes[index].length < 4)
+ {
+ best >>= 16;
+ i = 0;
+ }
+ else
+ {
+ i = 16;
+ }
+
+ /* Dump out instruction arguments */
+ for (d = gld_opcodes[index].args; *d; ++d)
+ {
+ switch (*d)
+ {
+ case 'f':
+ fprintf (stream, "%d", (best >> (7 + i)) & 7);
+ break;
+ case 'r':
+ fprintf (stream, "r%d", (best >> (7 + i)) & 7);
+ break;
+ case 'R':
+ fprintf (stream, "r%d", (best >> (4 + i)) & 7);
+ break;
+ case 'b':
+ fprintf (stream, "b%d", (best >> (7 + i)) & 7);
+ break;
+ case 'B':
+ fprintf (stream, "b%d", (best >> (4 + i)) & 7);
+ break;
+ case 'v':
+ fprintf (stream, "b%d", (best >> (7 + i)) & 7);
+ break;
+ case 'V':
+ fprintf (stream, "b%d", (best >> (4 + i)) & 7);
+ break;
+ case 'X':
+ temp = (best >> 20) & 7;
+ if (temp)
+ fprintf (stream, "r%d", temp);
+ else
+ putc ('0', stream);
+ break;
+ case 'A':
+ temp = (best >> 16) & 7;
+ if (temp)
+ fprintf (stream, "(b%d)", temp);
+ break;
+ case 'S':
+ fprintf (stream, "#%d", best & 0x1f);
+ break;
+ case 'I':
+ fprintf (stream, "#%x", best & 0xffff);
+ break;
+ case 'O':
+ fprintf (stream, "%x", best & 0xffff);
+ break;
+ case 'h':
+ fprintf (stream, "%d", best & 0xfffe);
+ break;
+ case 'd':
+ fprintf (stream, "%d", best & 0xfffc);
+ break;
+ case 'T':
+ fprintf (stream, "%d", (best >> 8) & 0xff);
+ break;
+ case 'N':
+ fprintf (stream, "%d", best & 0xff);
+ break;
+ default:
+ putc (*d, stream);
+ break;
+ }
+ }
+
+ /* Return length of instruction */
+ return (gld_opcodes[index].length);
+}
+
+/*
+ * Find the number of arguments to a function.
+ */
+findarg(frame)
+ struct frame_info *frame;
+{
+ register struct symbol *func;
+ register unsigned pc;
+
+#ifdef notdef
+ /* find starting address of frame function */
+ pc = get_pc_function_start (frame->pc);
+
+ /* find function symbol info */
+ func = find_pc_function (pc);
+
+ /* call blockframe code to look for match */
+ if (func != NULL)
+ return (func->value.block->nsyms / sizeof(int));
+#endif
+
+ return (-1);
+}
+
+/*
+ * In the case of the NPL, the frame's norminal address is Br2 and the
+ * previous routines frame is up the stack X bytes. Finding out what
+ * 'X' is can be tricky.
+ *
+ * 1.) stored in the code function header xA(Br1).
+ * 2.) must be careful of recurssion.
+ */
+FRAME_ADDR
+findframe(thisframe)
+ FRAME thisframe;
+{
+ register FRAME_ADDR pointer;
+ FRAME_ADDR framechain();
+#if 0
+ struct frame_info *frame;
+
+ /* Setup toplevel frame structure */
+ frame->pc = read_pc();
+ frame->next_frame = 0;
+ frame->frame = read_register (SP_REGNUM); /* Br2 */
+
+ /* Search for this frame (start at current Br2) */
+ do
+ {
+ pointer = framechain(frame);
+ frame->next_frame = frame->frame;
+ frame->frame = pointer;
+ frame->pc = FRAME_SAVED_PC(frame);
+ }
+ while (frame->next_frame != thisframe);
+#endif
+
+ pointer = framechain (thisframe);
+
+ /* stop gap for now, end at __base3 */
+ if (thisframe->pc == 0)
+ return 0;
+
+ return pointer;
+}
+
+/*
+ * Gdb front-end and internal framechain routine.
+ * Go back up stack one level. Tricky...
+ */
+FRAME_ADDR
+framechain(frame)
+ register struct frame_info *frame;
+{
+ register CORE_ADDR func, prevsp;
+ register unsigned value;
+
+ /* Get real function start address from internal frame address */
+ func = get_pc_function_start(frame->pc);
+
+ /* If no stack given, read register Br1 "(sp)" */
+ if (!frame->frame)
+ prevsp = read_register (SP_REGNUM);
+ else
+ prevsp = frame->frame;
+
+ /* Check function header, case #2 */
+ value = read_memory_integer (func, 4);
+ if (value)
+ {
+ /* 32bit call push value stored in function header */
+ prevsp += value;
+ }
+ else
+ {
+ /* read half-word from suabr at start of function */
+ prevsp += read_memory_integer (func + 10, 2);
+ }
+
+ return (prevsp);
+}
--- /dev/null
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+ int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name (filename);
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+ reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ core_aouthdr.a_magic = 0;
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0)
+ perror_with_name (filename);
+
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
--- /dev/null
+/* HP/UX interface for HP 300's, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+/* Defining this means some system include files define some extra stuff. */
+#define WOPR
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <sys/trap.h>
+
+#include "gdbcore.h"
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#define INFERIOR_AR0(u) \
+ ((ptrace \
+ (PT_RUAREA, inferior_pid, ((char *) &u.u_ar0 - (char *) &u), 0)) \
+ - KERNEL_U_ADDR)
+
+static void
+fetch_inferior_register (regno, regaddr)
+ register int regno;
+ register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+ if (regno == PS_REGNUM)
+ {
+ union { int i; short s[2]; } ps_val;
+ int regval;
+
+ ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+ regval = ps_val.s[0];
+ supply_register (regno, ®val);
+ }
+ else
+#endif /* not HPUX_VERSION_5 */
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (PT_RUAREA, inferior_pid, regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+ return;
+}
+
+static void
+store_inferior_register_1 (regno, regaddr, value)
+ int regno;
+ unsigned int regaddr;
+ int value;
+{
+ errno = 0;
+ ptrace (PT_WUAREA, inferior_pid, regaddr, value);
+#if 0
+ /* HP-UX randomly sets errno to non-zero for regno == 25.
+ However, the value is correctly written, so ignore errno. */
+ if (errno != 0)
+ {
+ char string_buf[64];
+
+ sprintf (string_buf, "writing register number %d", regno);
+ perror_with_name (string_buf);
+ }
+#endif
+ return;
+}
+
+static void
+store_inferior_register (regno, regaddr)
+ register int regno;
+ register unsigned int regaddr;
+{
+#ifndef HPUX_VERSION_5
+ if (regno == PS_REGNUM)
+ {
+ union { int i; short s[2]; } ps_val;
+
+ ps_val.i = (ptrace (PT_RUAREA, inferior_pid, regaddr, 0));
+ ps_val.s[0] = (read_register (regno));
+ store_inferior_register_1 (regno, regaddr, ps_val.i);
+ }
+ else
+#endif /* not HPUX_VERSION_5 */
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+ extern char registers[];
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ store_inferior_register_1
+ (regno, regaddr,
+ (*(int *) ®isters[(REGISTER_BYTE (regno)) + i]));
+ regaddr += sizeof (int);
+ }
+ }
+ return;
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct user u;
+ register int regno;
+ register unsigned int ar0_offset;
+
+ ar0_offset = (INFERIOR_AR0 (u));
+ if (regno == -1)
+ {
+ for (regno = 0; (regno < FP0_REGNUM); regno++)
+ fetch_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ for (; (regno < NUM_REGS); regno++)
+ fetch_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+ }
+ else
+ fetch_inferior_register (regno,
+ (regno < FP0_REGNUM
+ ? REGISTER_ADDR (ar0_offset, regno)
+ : FP_REGISTER_ADDR (u, regno)));
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ register int regno;
+{
+ struct user u;
+ register unsigned int ar0_offset;
+ extern char registers[];
+
+ if (regno >= FP0_REGNUM)
+ {
+ store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+ return;
+ }
+
+ ar0_offset = (INFERIOR_AR0 (u));
+ if (regno >= 0)
+ {
+ store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ return;
+ }
+
+ for (regno = 0; (regno < FP0_REGNUM); regno++)
+ store_inferior_register (regno, (REGISTER_ADDR (ar0_offset, regno)));
+ for (; (regno < NUM_REGS); regno++)
+ store_inferior_register (regno, (FP_REGISTER_ADDR (u, regno)));
+ return;
+}
+
+\f
+/* Take the register values out of a core file and store
+ them where `read_register' will find them. */
+
+#ifdef HPUX_VERSION_5
+#define e_PS e_regs[PS]
+#define e_PC e_regs[PC]
+#endif /* HPUX_VERSION_5 */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which)
+ char *core_reg_sect;
+ int core_reg_size;
+ int which;
+{
+ int val, regno;
+ struct user u;
+ struct exception_stack *pes = (struct exception_stack *) core_reg_sect;
+#define es (*pes)
+ char *buf;
+
+ if (which == 0) {
+ if (core_reg_size <
+ ((char *) &es.e_offset - (char *) &es.e_regs[R0]))
+ error ("Not enough registers in core file");
+ for (regno = 0; (regno < PS_REGNUM); regno++)
+ supply_register (regno, &es.e_regs[regno + R0]);
+ val = es.e_PS;
+ supply_register (regno++, &val);
+ supply_register (regno++, &es.e_PC);
+
+ } else if (which == 2) {
+
+ /* FIXME: This may not work if the float regs and control regs are
+ discontinuous. */
+ for (regno = FP0_REGNUM, buf = core_reg_sect;
+ (regno < NUM_REGS);
+ buf += REGISTER_RAW_SIZE (regno), regno++)
+ {
+ supply_register (regno, buf);
+ }
+ }
+}
--- /dev/null
+/* Print i386 instructions for GDB, the GNU debugger.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual. Usually, there is a capital letter, followed
+ * by a small letter. The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size. Refer to
+ * the Intel manual for details.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0
+#define Mp OP_E, 0 /* ? */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rw OP_rm, w_mode
+#define Rd OP_rm, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define ONE OP_ONE, 0
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, lptr
+#define Av OP_DIR, v_mode
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSSI, b_mode
+#define Xv OP_DSSI, v_mode
+#define Yb OP_ESDI, b_mode
+#define Yv OP_ESDI, v_mode
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
+int OP_J(), OP_SEG();
+int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
+int OP_D(), OP_T(), OP_rm();
+
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+#define eAX_reg 107
+#define eCX_reg 108
+#define eDX_reg 109
+#define eBX_reg 110
+#define eSP_reg 111
+#define eBP_reg 112
+#define eSI_reg 113
+#define eDI_reg 114
+
+#define lptr 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define GRP1b NULL, NULL, 0
+#define GRP1S NULL, NULL, 1
+#define GRP1Ss NULL, NULL, 2
+#define GRP2b NULL, NULL, 3
+#define GRP2S NULL, NULL, 4
+#define GRP2b_one NULL, NULL, 5
+#define GRP2S_one NULL, NULL, 6
+#define GRP2b_cl NULL, NULL, 7
+#define GRP2S_cl NULL, NULL, 8
+#define GRP3b NULL, NULL, 9
+#define GRP3S NULL, NULL, 10
+#define GRP4 NULL, NULL, 11
+#define GRP5 NULL, NULL, 12
+#define GRP6 NULL, NULL, 13
+#define GRP7 NULL, NULL, 14
+#define GRP8 NULL, NULL, 15
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE
+
+struct dis386 {
+ char *name;
+ int (*op1)();
+ int bytemode1;
+ int (*op2)();
+ int bytemode2;
+ int (*op3)();
+ int bytemode3;
+};
+
+struct dis386 dis386[] = {
+ /* 00 */
+ { "addb", Eb, Gb },
+ { "addS", Ev, Gv },
+ { "addb", Gb, Eb },
+ { "addS", Gv, Ev },
+ { "addb", AL, Ib },
+ { "addS", eAX, Iv },
+ { "pushl", es },
+ { "popl", es },
+ /* 08 */
+ { "orb", Eb, Gb },
+ { "orS", Ev, Gv },
+ { "orb", Gb, Eb },
+ { "orS", Gv, Ev },
+ { "orb", AL, Ib },
+ { "orS", eAX, Iv },
+ { "pushl", cs },
+ { "(bad)" }, /* 0x0f extended opcode escape */
+ /* 10 */
+ { "adcb", Eb, Gb },
+ { "adcS", Ev, Gv },
+ { "adcb", Gb, Eb },
+ { "adcS", Gv, Ev },
+ { "adcb", AL, Ib },
+ { "adcS", eAX, Iv },
+ { "pushl", ss },
+ { "popl", ss },
+ /* 18 */
+ { "sbbb", Eb, Gb },
+ { "sbbS", Ev, Gv },
+ { "sbbb", Gb, Eb },
+ { "sbbS", Gv, Ev },
+ { "sbbb", AL, Ib },
+ { "sbbS", eAX, Iv },
+ { "pushl", ds },
+ { "popl", ds },
+ /* 20 */
+ { "andb", Eb, Gb },
+ { "andS", Ev, Gv },
+ { "andb", Gb, Eb },
+ { "andS", Gv, Ev },
+ { "andb", AL, Ib },
+ { "andS", eAX, Iv },
+ { "(bad)" }, /* SEG ES prefix */
+ { "daa" },
+ /* 28 */
+ { "subb", Eb, Gb },
+ { "subS", Ev, Gv },
+ { "subb", Gb, Eb },
+ { "subS", Gv, Ev },
+ { "subb", AL, Ib },
+ { "subS", eAX, Iv },
+ { "(bad)" }, /* SEG CS prefix */
+ { "das" },
+ /* 30 */
+ { "xorb", Eb, Gb },
+ { "xorS", Ev, Gv },
+ { "xorb", Gb, Eb },
+ { "xorS", Gv, Ev },
+ { "xorb", AL, Ib },
+ { "xorS", eAX, Iv },
+ { "(bad)" }, /* SEG SS prefix */
+ { "aaa" },
+ /* 38 */
+ { "cmpb", Eb, Gb },
+ { "cmpS", Ev, Gv },
+ { "cmpb", Gb, Eb },
+ { "cmpS", Gv, Ev },
+ { "cmpb", AL, Ib },
+ { "cmpS", eAX, Iv },
+ { "(bad)" }, /* SEG DS prefix */
+ { "aas" },
+ /* 40 */
+ { "incS", eAX },
+ { "incS", eCX },
+ { "incS", eDX },
+ { "incS", eBX },
+ { "incS", eSP },
+ { "incS", eBP },
+ { "incS", eSI },
+ { "incS", eDI },
+ /* 48 */
+ { "decS", eAX },
+ { "decS", eCX },
+ { "decS", eDX },
+ { "decS", eBX },
+ { "decS", eSP },
+ { "decS", eBP },
+ { "decS", eSI },
+ { "decS", eDI },
+ /* 50 */
+ { "pushS", eAX },
+ { "pushS", eCX },
+ { "pushS", eDX },
+ { "pushS", eBX },
+ { "pushS", eSP },
+ { "pushS", eBP },
+ { "pushS", eSI },
+ { "pushS", eDI },
+ /* 58 */
+ { "popS", eAX },
+ { "popS", eCX },
+ { "popS", eDX },
+ { "popS", eBX },
+ { "popS", eSP },
+ { "popS", eBP },
+ { "popS", eSI },
+ { "popS", eDI },
+ /* 60 */
+ { "pusha" },
+ { "popa" },
+ { "boundS", Gv, Ma },
+ { "arpl", Ew, Gw },
+ { "(bad)" }, /* seg fs */
+ { "(bad)" }, /* seg gs */
+ { "(bad)" }, /* op size prefix */
+ { "(bad)" }, /* adr size prefix */
+ /* 68 */
+ { "pushS", Iv }, /* 386 book wrong */
+ { "imulS", Gv, Ev, Iv },
+ { "pushl", sIb }, /* push of byte really pushes 4 bytes */
+ { "imulS", Gv, Ev, Ib },
+ { "insb", Yb, indirDX },
+ { "insS", Yv, indirDX },
+ { "outsb", indirDX, Xb },
+ { "outsS", indirDX, Xv },
+ /* 70 */
+ { "jo", Jb },
+ { "jno", Jb },
+ { "jb", Jb },
+ { "jae", Jb },
+ { "je", Jb },
+ { "jne", Jb },
+ { "jbe", Jb },
+ { "ja", Jb },
+ /* 78 */
+ { "js", Jb },
+ { "jns", Jb },
+ { "jp", Jb },
+ { "jnp", Jb },
+ { "jl", Jb },
+ { "jnl", Jb },
+ { "jle", Jb },
+ { "jg", Jb },
+ /* 80 */
+ { GRP1b },
+ { GRP1S },
+ { "(bad)" },
+ { GRP1Ss },
+ { "testb", Eb, Gb },
+ { "testS", Ev, Gv },
+ { "xchgb", Eb, Gb },
+ { "xchgS", Ev, Gv },
+ /* 88 */
+ { "movb", Eb, Gb },
+ { "movS", Ev, Gv },
+ { "movb", Gb, Eb },
+ { "movS", Gv, Ev },
+ { "movw", Ew, Sw },
+ { "leaS", Gv, M },
+ { "movw", Sw, Ew },
+ { "popS", Ev },
+ /* 90 */
+ { "nop" },
+ { "xchgS", eCX, eAX },
+ { "xchgS", eDX, eAX },
+ { "xchgS", eBX, eAX },
+ { "xchgS", eSP, eAX },
+ { "xchgS", eBP, eAX },
+ { "xchgS", eSI, eAX },
+ { "xchgS", eDI, eAX },
+ /* 98 */
+ { "cwtl" },
+ { "cltd" },
+ { "lcall", Ap },
+ { "(bad)" }, /* fwait */
+ { "pushf" },
+ { "popf" },
+ { "sahf" },
+ { "lahf" },
+ /* a0 */
+ { "movb", AL, Ob },
+ { "movS", eAX, Ov },
+ { "movb", Ob, AL },
+ { "movS", Ov, eAX },
+ { "movsb", Yb, Xb },
+ { "movsS", Yv, Xv },
+ { "cmpsb", Yb, Xb },
+ { "cmpsS", Yv, Xv },
+ /* a8 */
+ { "testb", AL, Ib },
+ { "testS", eAX, Iv },
+ { "stosb", Yb, AL },
+ { "stosS", Yv, eAX },
+ { "lodsb", AL, Xb },
+ { "lodsS", eAX, Xv },
+ { "scasb", AL, Xb },
+ { "scasS", eAX, Xv },
+ /* b0 */
+ { "movb", AL, Ib },
+ { "movb", CL, Ib },
+ { "movb", DL, Ib },
+ { "movb", BL, Ib },
+ { "movb", AH, Ib },
+ { "movb", CH, Ib },
+ { "movb", DH, Ib },
+ { "movb", BH, Ib },
+ /* b8 */
+ { "movS", eAX, Iv },
+ { "movS", eCX, Iv },
+ { "movS", eDX, Iv },
+ { "movS", eBX, Iv },
+ { "movS", eSP, Iv },
+ { "movS", eBP, Iv },
+ { "movS", eSI, Iv },
+ { "movS", eDI, Iv },
+ /* c0 */
+ { GRP2b },
+ { GRP2S },
+ { "ret", Iw },
+ { "ret" },
+ { "lesS", Gv, Mp },
+ { "ldsS", Gv, Mp },
+ { "movb", Eb, Ib },
+ { "movS", Ev, Iv },
+ /* c8 */
+ { "enter", Iw, Ib },
+ { "leave" },
+ { "lret", Iw },
+ { "lret" },
+ { "int3" },
+ { "int", Ib },
+ { "into" },
+ { "iret" },
+ /* d0 */
+ { GRP2b_one },
+ { GRP2S_one },
+ { GRP2b_cl },
+ { GRP2S_cl },
+ { "aam", Ib },
+ { "aad", Ib },
+ { "(bad)" },
+ { "xlat" },
+ /* d8 */
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ /* e0 */
+ { "loopne", Jb },
+ { "loope", Jb },
+ { "loop", Jb },
+ { "jCcxz", Jb },
+ { "inb", AL, Ib },
+ { "inS", eAX, Ib },
+ { "outb", Ib, AL },
+ { "outS", Ib, eAX },
+ /* e8 */
+ { "call", Av },
+ { "jmp", Jv },
+ { "ljmp", Ap },
+ { "jmp", Jb },
+ { "inb", AL, indirDX },
+ { "inS", eAX, indirDX },
+ { "outb", indirDX, AL },
+ { "outS", indirDX, eAX },
+ /* f0 */
+ { "(bad)" }, /* lock prefix */
+ { "(bad)" },
+ { "(bad)" }, /* repne */
+ { "(bad)" }, /* repz */
+ { "hlt" },
+ { "cmc" },
+ { GRP3b },
+ { GRP3S },
+ /* f8 */
+ { "clc" },
+ { "stc" },
+ { "cli" },
+ { "sti" },
+ { "cld" },
+ { "std" },
+ { GRP4 },
+ { GRP5 },
+};
+
+struct dis386 dis386_twobyte[] = {
+ /* 00 */
+ { GRP6 },
+ { GRP7 },
+ { "larS", Gv, Ew },
+ { "lslS", Gv, Ew },
+ { "(bad)" },
+ { "(bad)" },
+ { "clts" },
+ { "(bad)" },
+ /* 08 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 10 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 18 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 20 */
+ /* these are all backward in appendix A of the intel book */
+ { "movl", Rd, Cd },
+ { "movl", Rd, Dd },
+ { "movl", Cd, Rd },
+ { "movl", Dd, Rd },
+ { "movl", Rd, Td },
+ { "(bad)" },
+ { "movl", Td, Rd },
+ { "(bad)" },
+ /* 28 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 30 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 38 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 40 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 48 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 50 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 58 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 60 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 68 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 70 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 78 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 80 */
+ { "jo", Jv },
+ { "jno", Jv },
+ { "jb", Jv },
+ { "jae", Jv },
+ { "je", Jv },
+ { "jne", Jv },
+ { "jbe", Jv },
+ { "ja", Jv },
+ /* 88 */
+ { "js", Jv },
+ { "jns", Jv },
+ { "jp", Jv },
+ { "jnp", Jv },
+ { "jl", Jv },
+ { "jge", Jv },
+ { "jle", Jv },
+ { "jg", Jv },
+ /* 90 */
+ { "seto", Eb },
+ { "setno", Eb },
+ { "setb", Eb },
+ { "setae", Eb },
+ { "sete", Eb },
+ { "setne", Eb },
+ { "setbe", Eb },
+ { "seta", Eb },
+ /* 98 */
+ { "sets", Eb },
+ { "setns", Eb },
+ { "setp", Eb },
+ { "setnp", Eb },
+ { "setl", Eb },
+ { "setge", Eb },
+ { "setle", Eb },
+ { "setg", Eb },
+ /* a0 */
+ { "pushl", fs },
+ { "popl", fs },
+ { "(bad)" },
+ { "btS", Ev, Gv },
+ { "shldS", Ev, Gv, Ib },
+ { "shldS", Ev, Gv, CL },
+ { "(bad)" },
+ { "(bad)" },
+ /* a8 */
+ { "pushl", gs },
+ { "popl", gs },
+ { "(bad)" },
+ { "btsS", Ev, Gv },
+ { "shrdS", Ev, Gv, Ib },
+ { "shrdS", Ev, Gv, CL },
+ { "(bad)" },
+ { "imulS", Gv, Ev },
+ /* b0 */
+ { "(bad)" },
+ { "(bad)" },
+ { "lssS", Gv, Mp }, /* 386 lists only Mp */
+ { "btrS", Ev, Gv },
+ { "lfsS", Gv, Mp }, /* 386 lists only Mp */
+ { "lgsS", Gv, Mp }, /* 386 lists only Mp */
+ { "movzbS", Gv, Eb },
+ { "movzwS", Gv, Ew },
+ /* b8 */
+ { "(bad)" },
+ { "(bad)" },
+ { GRP8 },
+ { "btcS", Ev, Gv },
+ { "bsfS", Gv, Ev },
+ { "bsrS", Gv, Ev },
+ { "movsbS", Gv, Eb },
+ { "movswS", Gv, Ew },
+ /* c0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* c8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* d0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* d8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *codep;
+static int mod;
+static int rm;
+static int reg;
+static void oappend ();
+
+static char *names32[]={
+ "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static char *names16[] = {
+ "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static char *names8[] = {
+ "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static char *names_seg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+
+struct dis386 grps[][8] = {
+ /* GRP1b */
+ {
+ { "addb", Eb, Ib },
+ { "orb", Eb, Ib },
+ { "adcb", Eb, Ib },
+ { "sbbb", Eb, Ib },
+ { "andb", Eb, Ib },
+ { "subb", Eb, Ib },
+ { "xorb", Eb, Ib },
+ { "cmpb", Eb, Ib }
+ },
+ /* GRP1S */
+ {
+ { "addS", Ev, Iv },
+ { "orS", Ev, Iv },
+ { "adcS", Ev, Iv },
+ { "sbbS", Ev, Iv },
+ { "andS", Ev, Iv },
+ { "subS", Ev, Iv },
+ { "xorS", Ev, Iv },
+ { "cmpS", Ev, Iv }
+ },
+ /* GRP1Ss */
+ {
+ { "addS", Ev, sIb },
+ { "orS", Ev, sIb },
+ { "adcS", Ev, sIb },
+ { "sbbS", Ev, sIb },
+ { "andS", Ev, sIb },
+ { "subS", Ev, sIb },
+ { "xorS", Ev, sIb },
+ { "cmpS", Ev, sIb }
+ },
+ /* GRP2b */
+ {
+ { "rolb", Eb, Ib },
+ { "rorb", Eb, Ib },
+ { "rclb", Eb, Ib },
+ { "rcrb", Eb, Ib },
+ { "shlb", Eb, Ib },
+ { "shrb", Eb, Ib },
+ { "(bad)" },
+ { "sarb", Eb, Ib },
+ },
+ /* GRP2S */
+ {
+ { "rolS", Ev, Ib },
+ { "rorS", Ev, Ib },
+ { "rclS", Ev, Ib },
+ { "rcrS", Ev, Ib },
+ { "shlS", Ev, Ib },
+ { "shrS", Ev, Ib },
+ { "(bad)" },
+ { "sarS", Ev, Ib },
+ },
+ /* GRP2b_one */
+ {
+ { "rolb", Eb },
+ { "rorb", Eb },
+ { "rclb", Eb },
+ { "rcrb", Eb },
+ { "shlb", Eb },
+ { "shrb", Eb },
+ { "(bad)" },
+ { "sarb", Eb },
+ },
+ /* GRP2S_one */
+ {
+ { "rolS", Ev },
+ { "rorS", Ev },
+ { "rclS", Ev },
+ { "rcrS", Ev },
+ { "shlS", Ev },
+ { "shrS", Ev },
+ { "(bad)" },
+ { "sarS", Ev },
+ },
+ /* GRP2b_cl */
+ {
+ { "rolb", Eb, CL },
+ { "rorb", Eb, CL },
+ { "rclb", Eb, CL },
+ { "rcrb", Eb, CL },
+ { "shlb", Eb, CL },
+ { "shrb", Eb, CL },
+ { "(bad)" },
+ { "sarb", Eb, CL },
+ },
+ /* GRP2S_cl */
+ {
+ { "rolS", Ev, CL },
+ { "rorS", Ev, CL },
+ { "rclS", Ev, CL },
+ { "rcrS", Ev, CL },
+ { "shlS", Ev, CL },
+ { "shrS", Ev, CL },
+ { "(bad)" },
+ { "sarS", Ev, CL }
+ },
+ /* GRP3b */
+ {
+ { "testb", Eb, Ib },
+ { "(bad)", Eb },
+ { "notb", Eb },
+ { "negb", Eb },
+ { "mulb", AL, Eb },
+ { "imulb", AL, Eb },
+ { "divb", AL, Eb },
+ { "idivb", AL, Eb }
+ },
+ /* GRP3S */
+ {
+ { "testS", Ev, Iv },
+ { "(bad)" },
+ { "notS", Ev },
+ { "negS", Ev },
+ { "mulS", eAX, Ev },
+ { "imulS", eAX, Ev },
+ { "divS", eAX, Ev },
+ { "idivS", eAX, Ev },
+ },
+ /* GRP4 */
+ {
+ { "incb", Eb },
+ { "decb", Eb },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* GRP5 */
+ {
+ { "incS", Ev },
+ { "decS", Ev },
+ { "call", indirEv },
+ { "lcall", indirEv },
+ { "jmp", indirEv },
+ { "ljmp", indirEv },
+ { "pushS", Ev },
+ { "(bad)" },
+ },
+ /* GRP6 */
+ {
+ { "sldt", Ew },
+ { "str", Ew },
+ { "lldt", Ew },
+ { "ltr", Ew },
+ { "verr", Ew },
+ { "verw", Ew },
+ { "(bad)" },
+ { "(bad)" }
+ },
+ /* GRP7 */
+ {
+ { "sgdt", Ew },
+ { "sidt", Ew },
+ { "lgdt", Ew },
+ { "lidt", Ew },
+ { "smsw", Ew },
+ { "(bad)" },
+ { "lmsw", Ew },
+ { "(bad)" },
+ },
+ /* GRP8 */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "btS", Ev, Ib },
+ { "btsS", Ev, Ib },
+ { "btrS", Ev, Ib },
+ { "btcS", Ev, Ib },
+ }
+};
+
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADR 0x400
+#define PREFIX_FWAIT 0x800
+
+static int prefixes;
+
+ckprefix ()
+{
+ prefixes = 0;
+ while (1)
+ {
+ switch (*codep)
+ {
+ case 0xf3:
+ prefixes |= PREFIX_REPZ;
+ break;
+ case 0xf2:
+ prefixes |= PREFIX_REPNZ;
+ break;
+ case 0xf0:
+ prefixes |= PREFIX_LOCK;
+ break;
+ case 0x2e:
+ prefixes |= PREFIX_CS;
+ break;
+ case 0x36:
+ prefixes |= PREFIX_SS;
+ break;
+ case 0x3e:
+ prefixes |= PREFIX_DS;
+ break;
+ case 0x26:
+ prefixes |= PREFIX_ES;
+ break;
+ case 0x64:
+ prefixes |= PREFIX_FS;
+ break;
+ case 0x65:
+ prefixes |= PREFIX_GS;
+ break;
+ case 0x66:
+ prefixes |= PREFIX_DATA;
+ break;
+ case 0x67:
+ prefixes |= PREFIX_ADR;
+ break;
+ case 0x9b:
+ prefixes |= PREFIX_FWAIT;
+ break;
+ default:
+ return;
+ }
+ codep++;
+ }
+}
+
+static int dflag;
+static int aflag;
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_address[3], op_ad, op_index[3];
+static int start_pc;
+extern void fputs_filtered ();
+
+/*
+ * disassemble the first instruction in 'inbuf'. You have to make
+ * sure all of the bytes of the instruction are filled in.
+ * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ * (see topic "Redundant prefixes" in the "Differences from 8086"
+ * section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ * be used to print the target address if this is a relative jump or call
+ * 'outbuf' gets filled in with the disassembled instruction. it should
+ * be long enough to hold the longest disassembled instruction.
+ * 100 bytes is certainly enough, unless symbol printing is added later
+ * The function returns the length of this instruction in bytes.
+ */
+i386dis (pc, inbuf, stream)
+ int pc;
+ unsigned char *inbuf;
+ FILE *stream;
+{
+ struct dis386 *dp;
+ char *p;
+ int i;
+ int enter_instruction;
+ char *first, *second, *third;
+ int needcomma;
+
+ obuf[0] = 0;
+ op1out[0] = 0;
+ op2out[0] = 0;
+ op3out[0] = 0;
+
+ op_index[0] = op_index[1] = op_index[2] = -1;
+
+ start_pc = pc;
+ start_codep = inbuf;
+ codep = inbuf;
+
+ ckprefix ();
+
+ if (*codep == 0xc8)
+ enter_instruction = 1;
+ else
+ enter_instruction = 0;
+
+ obufp = obuf;
+
+ if (prefixes & PREFIX_REPZ)
+ oappend ("repz ");
+ if (prefixes & PREFIX_REPNZ)
+ oappend ("repnz ");
+ if (prefixes & PREFIX_LOCK)
+ oappend ("lock ");
+
+ if ((prefixes & PREFIX_FWAIT)
+ && ((*codep < 0xd8) || (*codep > 0xdf)))
+ {
+ /* fwait not followed by floating point instruction */
+ fputs_filtered ("fwait", stream);
+ return (1);
+ }
+
+ /* these would be initialized to 0 if disassembling for 8086 or 286 */
+ dflag = 1;
+ aflag = 1;
+
+ if (prefixes & PREFIX_DATA)
+ dflag ^= 1;
+
+ if (prefixes & PREFIX_ADR)
+ {
+ aflag ^= 1;
+ oappend ("addr16 ");
+ }
+
+ if (*codep == 0x0f)
+ dp = &dis386_twobyte[*++codep];
+ else
+ dp = &dis386[*codep];
+ codep++;
+ mod = (*codep >> 6) & 3;
+ reg = (*codep >> 3) & 7;
+ rm = *codep & 7;
+
+ if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+ {
+ dofloat ();
+ }
+ else
+ {
+ if (dp->name == NULL)
+ dp = &grps[dp->bytemode1][reg];
+
+ putop (dp->name);
+
+ obufp = op1out;
+ op_ad = 2;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+
+ obufp = op2out;
+ op_ad = 1;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+
+ obufp = op3out;
+ op_ad = 0;
+ if (dp->op3)
+ (*dp->op3)(dp->bytemode3);
+ }
+
+ obufp = obuf + strlen (obuf);
+ for (i = strlen (obuf); i < 6; i++)
+ oappend (" ");
+ oappend (" ");
+ fputs_filtered (obuf, stream);
+
+ /* enter instruction is printed with operands in the
+ * same order as the intel book; everything else
+ * is printed in reverse order
+ */
+ if (enter_instruction)
+ {
+ first = op1out;
+ second = op2out;
+ third = op3out;
+ op_ad = op_index[0];
+ op_index[0] = op_index[2];
+ op_index[2] = op_ad;
+ }
+ else
+ {
+ first = op3out;
+ second = op2out;
+ third = op1out;
+ }
+ needcomma = 0;
+ if (*first)
+ {
+ if (op_index[0] != -1)
+ print_address (op_address[op_index[0]], stream);
+ else
+ fputs_filtered (first, stream);
+ needcomma = 1;
+ }
+ if (*second)
+ {
+ if (needcomma)
+ fputs_filtered (",", stream);
+ if (op_index[1] != -1)
+ print_address (op_address[op_index[1]], stream);
+ else
+ fputs_filtered (second, stream);
+ needcomma = 1;
+ }
+ if (*third)
+ {
+ if (needcomma)
+ fputs_filtered (",", stream);
+ if (op_index[2] != -1)
+ print_address (op_address[op_index[2]], stream);
+ else
+ fputs_filtered (third, stream);
+ }
+ return (codep - inbuf);
+}
+
+char *float_mem[] = {
+ /* d8 */
+ "fadds",
+ "fmuls",
+ "fcoms",
+ "fcomps",
+ "fsubs",
+ "fsubrs",
+ "fdivs",
+ "fdivrs",
+ /* d9 */
+ "flds",
+ "(bad)",
+ "fsts",
+ "fstps",
+ "fldenv",
+ "fldcw",
+ "fNstenv",
+ "fNstcw",
+ /* da */
+ "fiaddl",
+ "fimull",
+ "ficoml",
+ "ficompl",
+ "fisubl",
+ "fisubrl",
+ "fidivl",
+ "fidivrl",
+ /* db */
+ "fildl",
+ "(bad)",
+ "fistl",
+ "fistpl",
+ "(bad)",
+ "fldt",
+ "(bad)",
+ "fstpt",
+ /* dc */
+ "faddl",
+ "fmull",
+ "fcoml",
+ "fcompl",
+ "fsubl",
+ "fsubrl",
+ "fdivl",
+ "fdivrl",
+ /* dd */
+ "fldl",
+ "(bad)",
+ "fstl",
+ "fstpl",
+ "frstor",
+ "(bad)",
+ "fNsave",
+ "fNstsw",
+ /* de */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* df */
+ "fild",
+ "(bad)",
+ "fist",
+ "fistp",
+ "fbld",
+ "fildll",
+ "fbstp",
+ "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+int OP_ST(), OP_STi();
+
+#define FGRPd9_2 NULL, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1
+#define FGRPd9_5 NULL, NULL, 2
+#define FGRPd9_6 NULL, NULL, 3
+#define FGRPd9_7 NULL, NULL, 4
+#define FGRPda_5 NULL, NULL, 5
+#define FGRPdb_4 NULL, NULL, 6
+#define FGRPde_3 NULL, NULL, 7
+#define FGRPdf_4 NULL, NULL, 8
+
+struct dis386 float_reg[][8] = {
+ /* d8 */
+ {
+ { "fadd", ST, STi },
+ { "fmul", ST, STi },
+ { "fcom", STi },
+ { "fcomp", STi },
+ { "fsub", ST, STi },
+ { "fsubr", ST, STi },
+ { "fdiv", ST, STi },
+ { "fdivr", ST, STi },
+ },
+ /* d9 */
+ {
+ { "fld", STi },
+ { "fxch", STi },
+ { FGRPd9_2 },
+ { "(bad)" },
+ { FGRPd9_4 },
+ { FGRPd9_5 },
+ { FGRPd9_6 },
+ { FGRPd9_7 },
+ },
+ /* da */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPda_5 },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* db */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPdb_4 },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* dc */
+ {
+ { "fadd", STi, ST },
+ { "fmul", STi, ST },
+ { "(bad)" },
+ { "(bad)" },
+ { "fsub", STi, ST },
+ { "fsubr", STi, ST },
+ { "fdiv", STi, ST },
+ { "fdivr", STi, ST },
+ },
+ /* dd */
+ {
+ { "ffree", STi },
+ { "(bad)" },
+ { "fst", STi },
+ { "fstp", STi },
+ { "fucom", STi },
+ { "fucomp", STi },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* de */
+ {
+ { "faddp", STi, ST },
+ { "fmulp", STi, ST },
+ { "(bad)" },
+ { FGRPde_3 },
+ { "fsubp", STi, ST },
+ { "fsubrp", STi, ST },
+ { "fdivp", STi, ST },
+ { "fdivrp", STi, ST },
+ },
+ /* df */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPdf_4 },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+};
+
+
+char *fgrps[][8] = {
+ /* d9_2 0 */
+ {
+ "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* d9_4 1 */
+ {
+ "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+ },
+
+ /* d9_5 2 */
+ {
+ "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+ },
+
+ /* d9_6 3 */
+ {
+ "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+ },
+
+ /* d9_7 4 */
+ {
+ "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+ },
+
+ /* da_5 5 */
+ {
+ "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* db_4 6 */
+ {
+ "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+ "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+ },
+
+ /* de_3 7 */
+ {
+ "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* df_4 8 */
+ {
+ "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+};
+
+
+dofloat ()
+{
+ struct dis386 *dp;
+ unsigned char floatop;
+
+ floatop = codep[-1];
+
+ if (mod != 3)
+ {
+ putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+ obufp = op1out;
+ OP_E (v_mode);
+ return;
+ }
+ codep++;
+
+ dp = &float_reg[floatop - 0xd8][reg];
+ if (dp->name == NULL)
+ {
+ putop (fgrps[dp->bytemode1][rm]);
+ /* instruction fnstsw is only one with strange arg */
+ if (floatop == 0xdf && *codep == 0xe0)
+ strcpy (op1out, "%eax");
+ }
+ else
+ {
+ putop (dp->name);
+ obufp = op1out;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+ obufp = op2out;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+ }
+}
+
+/* ARGSUSED */
+OP_ST (ignore)
+{
+ oappend ("%st");
+}
+
+/* ARGSUSED */
+OP_STi (ignore)
+{
+ sprintf (scratchbuf, "%%st(%d)", rm);
+ oappend (scratchbuf);
+}
+
+
+/* capital letters in template are macros */
+putop (template)
+ char *template;
+{
+ char *p;
+
+ for (p = template; *p; p++)
+ {
+ switch (*p)
+ {
+ default:
+ *obufp++ = *p;
+ break;
+ case 'C': /* For jcxz/jecxz */
+ if (aflag == 0)
+ *obufp++ = 'e';
+ break;
+ case 'N':
+ if ((prefixes & PREFIX_FWAIT) == 0)
+ *obufp++ = 'n';
+ break;
+ case 'S':
+ /* operand size flag */
+ if (dflag)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ break;
+ }
+ }
+ *obufp = 0;
+}
+
+static void
+oappend (s)
+char *s;
+{
+ strcpy (obufp, s);
+ obufp += strlen (s);
+ *obufp = 0;
+}
+
+append_prefix ()
+{
+ if (prefixes & PREFIX_CS)
+ oappend ("%cs:");
+ if (prefixes & PREFIX_DS)
+ oappend ("%ds:");
+ if (prefixes & PREFIX_SS)
+ oappend ("%ss:");
+ if (prefixes & PREFIX_ES)
+ oappend ("%es:");
+ if (prefixes & PREFIX_FS)
+ oappend ("%fs:");
+ if (prefixes & PREFIX_GS)
+ oappend ("%gs:");
+}
+
+OP_indirE (bytemode)
+{
+ oappend ("*");
+ OP_E (bytemode);
+}
+
+OP_E (bytemode)
+{
+ int disp;
+ int havesib;
+ int didoutput = 0;
+ int base;
+ int index;
+ int scale;
+ int havebase;
+
+ /* skip mod/rm byte */
+ codep++;
+
+ havesib = 0;
+ havebase = 0;
+ disp = 0;
+
+ if (mod == 3)
+ {
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[rm]);
+ else
+ oappend (names16[rm]);
+ break;
+ default:
+ oappend ("<bad dis table>");
+ break;
+ }
+ return;
+ }
+
+ append_prefix ();
+ if (rm == 4)
+ {
+ havesib = 1;
+ havebase = 1;
+ scale = (*codep >> 6) & 3;
+ index = (*codep >> 3) & 7;
+ base = *codep & 7;
+ codep++;
+ }
+
+ switch (mod)
+ {
+ case 0:
+ switch (rm)
+ {
+ case 4:
+ /* implies havesib and havebase */
+ if (base == 5) {
+ havebase = 0;
+ disp = get32 ();
+ }
+ break;
+ case 5:
+ disp = get32 ();
+ break;
+ default:
+ havebase = 1;
+ base = rm;
+ break;
+ }
+ break;
+ case 1:
+ disp = *(char *)codep++;
+ if (rm != 4)
+ {
+ havebase = 1;
+ base = rm;
+ }
+ break;
+ case 2:
+ disp = get32 ();
+ if (rm != 4)
+ {
+ havebase = 1;
+ base = rm;
+ }
+ break;
+ }
+
+ if (mod != 0 || rm == 5 || (havesib && base == 5))
+ {
+ sprintf (scratchbuf, "%d", disp);
+ oappend (scratchbuf);
+ }
+
+ if (havebase || havesib)
+ {
+ oappend ("(");
+ if (havebase)
+ oappend (names32[base]);
+ if (havesib)
+ {
+ if (index != 4)
+ {
+ sprintf (scratchbuf, ",%s", names32[index]);
+ oappend (scratchbuf);
+ }
+ sprintf (scratchbuf, ",%d", 1 << scale);
+ oappend (scratchbuf);
+ }
+ oappend (")");
+ }
+}
+
+OP_G (bytemode)
+{
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[reg]);
+ break;
+ case w_mode:
+ oappend (names16[reg]);
+ break;
+ case d_mode:
+ oappend (names32[reg]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[reg]);
+ else
+ oappend (names16[reg]);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+}
+
+get32 ()
+{
+ int x = 0;
+
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ x |= (*codep++ & 0xff) << 16;
+ x |= (*codep++ & 0xff) << 24;
+ return (x);
+}
+
+get16 ()
+{
+ int x = 0;
+
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ return (x);
+}
+
+set_op (op)
+int op;
+{
+ op_index[op_ad] = op_ad;
+ op_address[op_ad] = op;
+}
+
+OP_REG (code)
+{
+ char *s;
+
+ switch (code)
+ {
+ case indir_dx_reg: s = "(%dx)"; break;
+ case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+ case sp_reg: case bp_reg: case si_reg: case di_reg:
+ s = names16[code - ax_reg];
+ break;
+ case es_reg: case ss_reg: case cs_reg:
+ case ds_reg: case fs_reg: case gs_reg:
+ s = names_seg[code - es_reg];
+ break;
+ case al_reg: case ah_reg: case cl_reg: case ch_reg:
+ case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+ s = names8[code - al_reg];
+ break;
+ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+ case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+ if (dflag)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ break;
+ default:
+ s = "<internal disassembler error>";
+ break;
+ }
+ oappend (s);
+}
+
+OP_I (bytemode)
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ op = *codep++ & 0xff;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = get16 ();
+ break;
+ case w_mode:
+ op = get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+}
+
+OP_sI (bytemode)
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ op = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = (short)get16();
+ break;
+ case w_mode:
+ op = (short)get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+}
+
+OP_J (bytemode)
+{
+ int disp;
+ int mask = -1;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ disp = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ disp = get32 ();
+ else
+ {
+ disp = (short)get16 ();
+ /* for some reason, a data16 prefix on a jump instruction
+ means that the pc is masked to 16 bits after the
+ displacement is added! */
+ mask = 0xffff;
+ }
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return;
+ }
+ disp = (start_pc + codep - start_codep + disp) & mask;
+ set_op (disp);
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_SEG (dummy)
+{
+ static char *sreg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+ };
+
+ oappend (sreg[reg]);
+}
+
+OP_DIR (size)
+{
+ int seg, offset;
+
+ switch (size)
+ {
+ case lptr:
+ if (aflag)
+ {
+ offset = get32 ();
+ seg = get16 ();
+ }
+ else
+ {
+ offset = get16 ();
+ seg = get16 ();
+ }
+ sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+ oappend (scratchbuf);
+ break;
+ case v_mode:
+ if (aflag)
+ offset = get32 ();
+ else
+ offset = (short)get16 ();
+
+ offset = start_pc + codep - start_codep + offset;
+ set_op (offset);
+ sprintf (scratchbuf, "0x%x", offset);
+ oappend (scratchbuf);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+}
+
+/* ARGSUSED */
+OP_OFF (bytemode)
+{
+ int off;
+
+ if (aflag)
+ off = get32 ();
+ else
+ off = get16 ();
+
+ sprintf (scratchbuf, "0x%x", off);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_ESDI (dummy)
+{
+ oappend ("%es:(");
+ oappend (aflag ? "%edi" : "%di");
+ oappend (")");
+}
+
+/* ARGSUSED */
+OP_DSSI (dummy)
+{
+ oappend ("%ds:(");
+ oappend (aflag ? "%esi" : "%si");
+ oappend (")");
+}
+
+/* ARGSUSED */
+OP_ONE (dummy)
+{
+ oappend ("1");
+}
+
+/* ARGSUSED */
+OP_C (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%cr%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_D (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%db%d", reg);
+ oappend (scratchbuf);
+}
+
+/* ARGSUSED */
+OP_T (dummy)
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%tr%d", reg);
+ oappend (scratchbuf);
+}
+
+OP_rm (bytemode)
+{
+ switch (bytemode)
+ {
+ case d_mode:
+ oappend (names32[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ }
+}
+
+/* GDB interface */
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#define MAXLEN 20
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ return (i386dis ((int)memaddr, buffer, stream));
+}
+
--- /dev/null
+/* Intel 386 stuff.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <sys/reg.h>
+\f
+/* this table must line up with REGISTER_NAMES in m-i386.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+i386_register_u_addr (blockend, regnum)
+{
+#if 0
+ /* this will be needed if fp registers are reinstated */
+ /* for now, you can look at them with 'info float'
+ * sys5 wont let you change them with ptrace anyway
+ */
+ if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
+ {
+ int ubase, fpstate;
+ struct user u;
+ ubase = blockend + 4 * (SS + 1) - KSTKSZ;
+ fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
+ return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+ }
+ else
+#endif
+ return (blockend + 4 * regmap[regnum]);
+
+}
+
+/* This is broken for cross debugging. Possible solutions are:
+
+1. Don't worry about whether the thing compiles for cross-debugging.
+Go ahead and call them from i386-tdep.c.
+1a. Same thing but use some macros in xm-i386.h so that gdb will
+compile for cross-debugging but just give an error (or some such behavior)
+when you attempt to convert floats.
+
+2. Write a portable (in the sense of running on any machine; it would
+always be for i387 floating-point formats) extended<->double converter
+(which just deals with the values as arrays of char).
+
+3. Assume the host machine has *some* IEEE chip. However, IEEE does
+not standardize formats for extended floats (387 is 10 bytes, 68881 is
+12 bytes), so this won't work. */
+
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ long *lp;
+ /* push extended mode on 387 stack, then pop in double mode
+ *
+ * first, set exception masks so no error is generated -
+ * number will be rounded to inf or 0, if necessary
+ */
+ asm ("pushl %eax"); /* grab a stack slot */
+ asm ("fstcw (%esp)"); /* get 387 control word */
+ asm ("movl (%esp),%eax"); /* save old value */
+ asm ("orl $0x3f,%eax"); /* mask all exceptions */
+ asm ("pushl %eax");
+ asm ("fldcw (%esp)"); /* load new value into 387 */
+
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldt (%eax)"); /* push extended number on 387 stack */
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpl (%eax)"); /* pop double */
+ asm ("fwait");
+
+ asm ("popl %eax"); /* flush modified control word */
+ asm ("fnclex"); /* clear exceptions */
+ asm ("fldcw (%esp)"); /* restore original control word */
+ asm ("popl %eax"); /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ /* push double mode on 387 stack, then pop in extended mode
+ * no errors are possible because every 64-bit pattern
+ * can be converted to an extended
+ */
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldl (%eax)");
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpt (%eax)");
+ asm ("fwait");
+}
+
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
+
+static
+print_387_control_word (control)
+unsigned short control;
+{
+ printf ("control 0x%04x: ", control);
+ printf ("compute to ");
+ switch ((control >> 8) & 3)
+ {
+ case 0: printf ("24 bits; "); break;
+ case 1: printf ("(bad); "); break;
+ case 2: printf ("53 bits; "); break;
+ case 3: printf ("64 bits; "); break;
+ }
+ printf ("round ");
+ switch ((control >> 10) & 3)
+ {
+ case 0: printf ("NEAREST; "); break;
+ case 1: printf ("DOWN; "); break;
+ case 2: printf ("UP; "); break;
+ case 3: printf ("CHOP; "); break;
+ }
+ if (control & 0x3f)
+ {
+ printf ("mask:");
+ if (control & 0x0001) printf (" INVALID");
+ if (control & 0x0002) printf (" DENORM");
+ if (control & 0x0004) printf (" DIVZ");
+ if (control & 0x0008) printf (" OVERF");
+ if (control & 0x0010) printf (" UNDERF");
+ if (control & 0x0020) printf (" LOS");
+ printf (";");
+ }
+ printf ("\n");
+ if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
+ control & 0xe080);
+}
+
+static
+print_387_status_word (status)
+ unsigned short status;
+{
+ printf ("status 0x%04x: ", status);
+ if (status & 0xff)
+ {
+ printf ("exceptions:");
+ if (status & 0x0001) printf (" INVALID");
+ if (status & 0x0002) printf (" DENORM");
+ if (status & 0x0004) printf (" DIVZ");
+ if (status & 0x0008) printf (" OVERF");
+ if (status & 0x0010) printf (" UNDERF");
+ if (status & 0x0020) printf (" LOS");
+ if (status & 0x0040) printf (" FPSTACK");
+ printf ("; ");
+ }
+ printf ("flags: %d%d%d%d; ",
+ (status & 0x4000) != 0,
+ (status & 0x0400) != 0,
+ (status & 0x0200) != 0,
+ (status & 0x0100) != 0);
+
+ printf ("top %d\n", (status >> 11) & 7);
+}
+
+static
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf ("last exception: ");
+ printf ("opcode 0x%x; ", ep->opcode);
+ printf ("pc 0x%x:0x%x; ", ep->code_seg, ep->eip);
+ printf ("operand 0x%x:0x%x\n", ep->operand_seg, ep->operand);
+
+ top = (ep->status >> 11) & 7;
+
+ printf ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf ("valid "); break;
+ case 1: printf ("zero "); break;
+ case 2: printf ("trap "); break;
+ case 3: printf ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf ("%02x", ep->regs[fpreg][i]);
+
+ i387_to_double (ep->regs[fpreg], (char *)&val);
+ printf (" %g\n", val);
+ }
+ if (ep->r0)
+ printf ("warning: reserved0 is 0x%x\n", ep->r0);
+ if (ep->r1)
+ printf ("warning: reserved1 is 0x%x\n", ep->r1);
+ if (ep->r2)
+ printf ("warning: reserved2 is 0x%x\n", ep->r2);
+ if (ep->r3)
+ printf ("warning: reserved3 is 0x%x\n", ep->r3);
+}
+
+#ifndef U_FPSTATE
+#define U_FPSTATE(u) u.u_fpstate
+#endif
+
+i386_float_info ()
+{
+ struct user u; /* just for address computations */
+ int i;
+ /* fpstate defined in <sys/user.h> */
+ struct fpstate *fpstatep;
+ char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
+ unsigned int uaddr;
+ char fpvalid;
+ unsigned int rounded_addr;
+ unsigned int rounded_size;
+ extern int corechan;
+ int skip;
+
+ uaddr = (char *)&u.u_fpvalid - (char *)&u;
+ if (have_inferior_p())
+ {
+ unsigned int data;
+ unsigned int mask;
+
+ rounded_addr = uaddr & -sizeof (int);
+ data = ptrace (3, inferior_pid, rounded_addr, 0);
+ mask = 0xff << ((uaddr - rounded_addr) * 8);
+
+ fpvalid = ((data & mask) != 0);
+ }
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror ("seek on core file");
+ if (myread (corechan, &fpvalid, 1) < 0)
+ perror ("read on core file");
+
+ }
+
+ if (fpvalid == 0)
+ {
+ printf ("no floating point status saved\n");
+ return;
+ }
+
+ uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+ if (have_inferior_p ())
+ {
+ int *ip;
+
+ rounded_addr = uaddr & -sizeof (int);
+ rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
+ sizeof (int) - 1) / sizeof (int);
+ skip = uaddr - rounded_addr;
+
+ ip = (int *)buf;
+ for (i = 0; i < rounded_size; i++)
+ {
+ *ip++ = ptrace (3, inferior_pid, rounded_addr, 0);
+ rounded_addr += sizeof (int);
+ }
+ }
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror_with_name ("seek on core file");
+ if (myread (corechan, buf, sizeof (struct fpstate)) < 0)
+ perror_with_name ("read from core file");
+ skip = 0;
+ }
+
+ fpstatep = (struct fpstate *)(buf + skip);
+ print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
+}
+
--- /dev/null
+/* Disassemble i80960 instructions.
+ */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+extern char *reg_names[];
+
+static FILE *stream; /* Output goes here */
+static void print_addr();
+static void ctrl();
+static void cobr();
+static void reg();
+static int mem();
+static void ea();
+static void dstop();
+static void regop();
+static void invalid();
+static int pinsn();
+static void put_abs();
+
+
+/* Print the i960 instruction at address 'memaddr' in debugged memory,
+ on stream 's'. Returns length of the instruction, in bytes. */
+int
+print_insn( memaddr, s )
+ CORE_ADDR memaddr;
+ FILE *s;
+{
+ unsigned int word1, word2;
+
+ stream = s;
+ word1 = read_memory_integer( memaddr, 4 );
+ word2 = read_memory_integer( memaddr+4, 4 );
+ return pinsn( memaddr, word1, word2 );
+}
+
+
+/* Read the i960 instruction at 'memaddr' and return the address of
+ the next instruction after that, or 0 if 'memaddr' is not the
+ address of a valid instruction. The first word of the instruction
+ is stored at 'pword1', and the second word, if any, is stored at
+ 'pword2'. */
+
+CORE_ADDR
+next_insn (memaddr, pword1, pword2)
+ unsigned long *pword1, *pword2;
+ CORE_ADDR memaddr;
+{
+ int len;
+ unsigned long buf[2];
+
+ /* Read the two (potential) words of the instruction at once,
+ to eliminate the overhead of two calls to read_memory ().
+ TODO: read more instructions at once and cache them. */
+
+ read_memory (memaddr, buf, sizeof (buf));
+ *pword1 = buf[0];
+ SWAP_TARGET_AND_HOST (pword1, sizeof (long));
+ *pword2 = buf[1];
+ SWAP_TARGET_AND_HOST (pword2, sizeof (long));
+
+ /* Divide instruction set into classes based on high 4 bits of opcode*/
+
+ switch ((*pword1 >> 28) & 0xf)
+ {
+ case 0x0:
+ case 0x1: /* ctrl */
+
+ case 0x2:
+ case 0x3: /* cobr */
+
+ case 0x5:
+ case 0x6:
+ case 0x7: /* reg */
+ len = 4;
+ break;
+
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb:
+ case 0xc:
+ len = mem (memaddr, *pword1, *pword2, 1);
+ break;
+
+ default: /* invalid instruction */
+ len = 0;
+ break;
+ }
+
+ if (len)
+ return memaddr + len;
+ else
+ return 0;
+}
+\f
+#define IN_GDB
+
+/*****************************************************************************
+ * All code below this point should be identical with that of
+ * the disassembler in gdmp960.
+ *****************************************************************************/
+
+struct tabent {
+ char *name;
+ char numops;
+};
+
+static int
+pinsn( memaddr, word1, word2 )
+ unsigned long memaddr;
+ unsigned long word1, word2;
+{
+ int instr_len;
+
+ instr_len = 4;
+ put_abs( word1, word2 );
+
+ /* Divide instruction set into classes based on high 4 bits of opcode*/
+
+ switch ( (word1 >> 28) & 0xf ){
+ case 0x0:
+ case 0x1:
+ ctrl( memaddr, word1, word2 );
+ break;
+ case 0x2:
+ case 0x3:
+ cobr( memaddr, word1, word2 );
+ break;
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ reg( word1 );
+ break;
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb:
+ case 0xc:
+ instr_len = mem( memaddr, word1, word2, 0 );
+ break;
+ default:
+ /* invalid instruction, print as data word */
+ invalid( word1 );
+ break;
+ }
+ return instr_len;
+}
+
+/****************************************/
+/* CTRL format */
+/****************************************/
+static void
+ctrl( memaddr, word1, word2 )
+ unsigned long memaddr;
+ unsigned long word1, word2;
+{
+ int i;
+ static struct tabent ctrl_tab[] = {
+ NULL, 0, /* 0x00 */
+ NULL, 0, /* 0x01 */
+ NULL, 0, /* 0x02 */
+ NULL, 0, /* 0x03 */
+ NULL, 0, /* 0x04 */
+ NULL, 0, /* 0x05 */
+ NULL, 0, /* 0x06 */
+ NULL, 0, /* 0x07 */
+ "b", 1, /* 0x08 */
+ "call", 1, /* 0x09 */
+ "ret", 0, /* 0x0a */
+ "bal", 1, /* 0x0b */
+ NULL, 0, /* 0x0c */
+ NULL, 0, /* 0x0d */
+ NULL, 0, /* 0x0e */
+ NULL, 0, /* 0x0f */
+ "bno", 1, /* 0x10 */
+ "bg", 1, /* 0x11 */
+ "be", 1, /* 0x12 */
+ "bge", 1, /* 0x13 */
+ "bl", 1, /* 0x14 */
+ "bne", 1, /* 0x15 */
+ "ble", 1, /* 0x16 */
+ "bo", 1, /* 0x17 */
+ "faultno", 0, /* 0x18 */
+ "faultg", 0, /* 0x19 */
+ "faulte", 0, /* 0x1a */
+ "faultge", 0, /* 0x1b */
+ "faultl", 0, /* 0x1c */
+ "faultne", 0, /* 0x1d */
+ "faultle", 0, /* 0x1e */
+ "faulto", 0, /* 0x1f */
+ };
+
+ i = (word1 >> 24) & 0xff;
+ if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){
+ invalid( word1 );
+ return;
+ }
+
+ fputs( ctrl_tab[i].name, stream );
+ if ( word1 & 2 ){ /* Predicts branch not taken */
+ fputs( ".f", stream );
+ }
+
+ if ( ctrl_tab[i].numops == 1 ){
+ /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */
+ word1 &= 0x00ffffff;
+ if ( word1 & 0x00800000 ){ /* Sign bit is set */
+ word1 |= (-1 & ~0xffffff); /* Sign extend */
+ }
+ putc( '\t', stream );
+ print_addr( word1 + memaddr );
+ }
+}
+
+/****************************************/
+/* COBR format */
+/****************************************/
+static void
+cobr( memaddr, word1, word2 )
+ unsigned long memaddr;
+ unsigned long word1, word2;
+{
+ int src1;
+ int src2;
+ int i;
+
+ static struct tabent cobr_tab[] = {
+ "testno", 1, /* 0x20 */
+ "testg", 1, /* 0x21 */
+ "teste", 1, /* 0x22 */
+ "testge", 1, /* 0x23 */
+ "testl", 1, /* 0x24 */
+ "testne", 1, /* 0x25 */
+ "testle", 1, /* 0x26 */
+ "testo", 1, /* 0x27 */
+ NULL, 0, /* 0x28 */
+ NULL, 0, /* 0x29 */
+ NULL, 0, /* 0x2a */
+ NULL, 0, /* 0x2b */
+ NULL, 0, /* 0x2c */
+ NULL, 0, /* 0x2d */
+ NULL, 0, /* 0x2e */
+ NULL, 0, /* 0x2f */
+ "bbc", 3, /* 0x30 */
+ "cmpobg", 3, /* 0x31 */
+ "cmpobe", 3, /* 0x32 */
+ "cmpobge", 3, /* 0x33 */
+ "cmpobl", 3, /* 0x34 */
+ "cmpobne", 3, /* 0x35 */
+ "cmpoble", 3, /* 0x36 */
+ "bbs", 3, /* 0x37 */
+ "cmpibno", 3, /* 0x38 */
+ "cmpibg", 3, /* 0x39 */
+ "cmpibe", 3, /* 0x3a */
+ "cmpibge", 3, /* 0x3b */
+ "cmpibl", 3, /* 0x3c */
+ "cmpibne", 3, /* 0x3d */
+ "cmpible", 3, /* 0x3e */
+ "cmpibo", 3, /* 0x3f */
+ };
+
+ i = ((word1 >> 24) & 0xff) - 0x20;
+ if ( cobr_tab[i].name == NULL ){
+ invalid( word1 );
+ return;
+ }
+
+ fputs( cobr_tab[i].name, stream );
+ if ( word1 & 2 ){ /* Predicts branch not taken */
+ fputs( ".f", stream );
+ }
+ putc( '\t', stream );
+
+ src1 = (word1 >> 19) & 0x1f;
+ src2 = (word1 >> 14) & 0x1f;
+
+ if ( word1 & 0x02000 ){ /* M1 is 1 */
+ fprintf( stream, "%d", src1 );
+ } else { /* M1 is 0 */
+ fputs( reg_names[src1], stream );
+ }
+
+ if ( cobr_tab[i].numops > 1 ){
+ if ( word1 & 1 ){ /* S2 is 1 */
+ fprintf( stream, ",sf%d,", src2 );
+ } else { /* S1 is 0 */
+ fprintf( stream, ",%s,", reg_names[src2] );
+ }
+
+ /* Extract displacement and convert to address
+ */
+ word1 &= 0x00001ffc;
+ if ( word1 & 0x00001000 ){ /* Negative displacement */
+ word1 |= (-1 & ~0x1fff); /* Sign extend */
+ }
+ print_addr( memaddr + word1 );
+ }
+}
+
+/****************************************/
+/* MEM format */
+/****************************************/
+static int /* returns instruction length: 4 or 8 */
+mem( memaddr, word1, word2, noprint )
+ unsigned long memaddr;
+ unsigned long word1, word2;
+ int noprint; /* If TRUE, return instruction length, but
+ don't output any text. */
+{
+ int i, j;
+ int len;
+ int mode;
+ int offset;
+ char *reg1, *reg2, *reg3;
+
+ /* This lookup table is too sparse to make it worth typing in, but not
+ * so large as to make a sparse array necessary. We allocate the
+ * table at runtime, initialize all entries to empty, and copy the
+ * real ones in from an initialization table.
+ *
+ * NOTE: In this table, the meaning of 'numops' is:
+ * 1: single operand
+ * 2: 2 operands, load instruction
+ * -2: 2 operands, store instruction
+ */
+ static struct tabent *mem_tab = NULL;
+ static struct { int opcode; char *name; char numops; } mem_init[] = {
+#define MEM_MIN 0x80
+ 0x80, "ldob", 2,
+ 0x82, "stob", -2,
+ 0x84, "bx", 1,
+ 0x85, "balx", 2,
+ 0x86, "callx", 1,
+ 0x88, "ldos", 2,
+ 0x8a, "stos", -2,
+ 0x8c, "lda", 2,
+ 0x90, "ld", 2,
+ 0x92, "st", -2,
+ 0x98, "ldl", 2,
+ 0x9a, "stl", -2,
+ 0xa0, "ldt", 2,
+ 0xa2, "stt", -2,
+ 0xb0, "ldq", 2,
+ 0xb2, "stq", -2,
+ 0xc0, "ldib", 2,
+ 0xc2, "stib", -2,
+ 0xc8, "ldis", 2,
+ 0xca, "stis", -2,
+#define MEM_MAX 0xca
+#define MEM_SIZ ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
+ 0, NULL, 0
+ };
+
+ if ( mem_tab == NULL ){
+ mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
+ bzero( mem_tab, MEM_SIZ );
+ for ( i = 0; mem_init[i].opcode != 0; i++ ){
+ j = mem_init[i].opcode - MEM_MIN;
+ mem_tab[j].name = mem_init[i].name;
+ mem_tab[j].numops = mem_init[i].numops;
+ }
+ }
+
+ i = ((word1 >> 24) & 0xff) - MEM_MIN;
+ mode = (word1 >> 10) & 0xf;
+
+ if ( (mem_tab[i].name != NULL) /* Valid instruction */
+ && ((mode == 5) || (mode >=12)) ){ /* With 32-bit displacement */
+ len = 8;
+ } else {
+ len = 4;
+ }
+
+ if ( noprint ){
+ return len;
+ }
+
+ if ( (mem_tab[i].name == NULL) || (mode == 6) ){
+ invalid( word1 );
+ return len;
+ }
+
+ fprintf( stream, "%s\t", mem_tab[i].name );
+
+ reg1 = reg_names[ (word1 >> 19) & 0x1f ]; /* MEMB only */
+ reg2 = reg_names[ (word1 >> 14) & 0x1f ];
+ reg3 = reg_names[ word1 & 0x1f ]; /* MEMB only */
+ offset = word1 & 0xfff; /* MEMA only */
+
+ switch ( mem_tab[i].numops ){
+
+ case 2: /* LOAD INSTRUCTION */
+ if ( mode & 4 ){ /* MEMB FORMAT */
+ ea( memaddr, mode, reg2, reg3, word1, word2 );
+ fprintf( stream, ",%s", reg1 );
+ } else { /* MEMA FORMAT */
+ fprintf( stream, "0x%x", offset );
+ if (mode & 8) {
+ fprintf( stream, "(%s)", reg2 );
+ }
+ fprintf( stream, ",%s", reg1 );
+ }
+ break;
+
+ case -2: /* STORE INSTRUCTION */
+ if ( mode & 4 ){ /* MEMB FORMAT */
+ fprintf( stream, "%s,", reg1 );
+ ea( memaddr, mode, reg2, reg3, word1, word2 );
+ } else { /* MEMA FORMAT */
+ fprintf( stream, "%s,0x%x", reg1, offset );
+ if (mode & 8) {
+ fprintf( stream, "(%s)", reg2 );
+ }
+ }
+ break;
+
+ case 1: /* BX/CALLX INSTRUCTION */
+ if ( mode & 4 ){ /* MEMB FORMAT */
+ ea( memaddr, mode, reg2, reg3, word1, word2 );
+ } else { /* MEMA FORMAT */
+ fprintf( stream, "0x%x", offset );
+ if (mode & 8) {
+ fprintf( stream, "(%s)", reg2 );
+ }
+ }
+ break;
+ }
+
+ return len;
+}
+
+/****************************************/
+/* REG format */
+/****************************************/
+static void
+reg( word1 )
+ unsigned long word1;
+{
+ int i, j;
+ int opcode;
+ int fp;
+ int m1, m2, m3;
+ int s1, s2;
+ int src, src2, dst;
+ char *mnemp;
+
+ /* This lookup table is too sparse to make it worth typing in, but not
+ * so large as to make a sparse array necessary. We allocate the
+ * table at runtime, initialize all entries to empty, and copy the
+ * real ones in from an initialization table.
+ *
+ * NOTE: In this table, the meaning of 'numops' is:
+ * 1: single operand, which is NOT a destination.
+ * -1: single operand, which IS a destination.
+ * 2: 2 operands, the 2nd of which is NOT a destination.
+ * -2: 2 operands, the 2nd of which IS a destination.
+ * 3: 3 operands
+ *
+ * If an opcode mnemonic begins with "F", it is a floating-point
+ * opcode (the "F" is not printed).
+ */
+
+ static struct tabent *reg_tab = NULL;
+ static struct { int opcode; char *name; char numops; } reg_init[] = {
+#define REG_MIN 0x580
+ 0x580, "notbit", 3,
+ 0x581, "and", 3,
+ 0x582, "andnot", 3,
+ 0x583, "setbit", 3,
+ 0x584, "notand", 3,
+ 0x586, "xor", 3,
+ 0x587, "or", 3,
+ 0x588, "nor", 3,
+ 0x589, "xnor", 3,
+ 0x58a, "not", -2,
+ 0x58b, "ornot", 3,
+ 0x58c, "clrbit", 3,
+ 0x58d, "notor", 3,
+ 0x58e, "nand", 3,
+ 0x58f, "alterbit", 3,
+ 0x590, "addo", 3,
+ 0x591, "addi", 3,
+ 0x592, "subo", 3,
+ 0x593, "subi", 3,
+ 0x598, "shro", 3,
+ 0x59a, "shrdi", 3,
+ 0x59b, "shri", 3,
+ 0x59c, "shlo", 3,
+ 0x59d, "rotate", 3,
+ 0x59e, "shli", 3,
+ 0x5a0, "cmpo", 2,
+ 0x5a1, "cmpi", 2,
+ 0x5a2, "concmpo", 2,
+ 0x5a3, "concmpi", 2,
+ 0x5a4, "cmpinco", 3,
+ 0x5a5, "cmpinci", 3,
+ 0x5a6, "cmpdeco", 3,
+ 0x5a7, "cmpdeci", 3,
+ 0x5ac, "scanbyte", 2,
+ 0x5ae, "chkbit", 2,
+ 0x5b0, "addc", 3,
+ 0x5b2, "subc", 3,
+ 0x5cc, "mov", -2,
+ 0x5d8, "eshro", 3,
+ 0x5dc, "movl", -2,
+ 0x5ec, "movt", -2,
+ 0x5fc, "movq", -2,
+ 0x600, "synmov", 2,
+ 0x601, "synmovl", 2,
+ 0x602, "synmovq", 2,
+ 0x603, "cmpstr", 3,
+ 0x604, "movqstr", 3,
+ 0x605, "movstr", 3,
+ 0x610, "atmod", 3,
+ 0x612, "atadd", 3,
+ 0x613, "inspacc", -2,
+ 0x614, "ldphy", -2,
+ 0x615, "synld", -2,
+ 0x617, "fill", 3,
+ 0x630, "sdma", 3,
+ 0x631, "udma", 0,
+ 0x640, "spanbit", -2,
+ 0x641, "scanbit", -2,
+ 0x642, "daddc", 3,
+ 0x643, "dsubc", 3,
+ 0x644, "dmovt", -2,
+ 0x645, "modac", 3,
+ 0x646, "condrec", -2,
+ 0x650, "modify", 3,
+ 0x651, "extract", 3,
+ 0x654, "modtc", 3,
+ 0x655, "modpc", 3,
+ 0x656, "receive", -2,
+ 0x659, "sysctl", 3,
+ 0x660, "calls", 1,
+ 0x662, "send", 3,
+ 0x663, "sendserv", 1,
+ 0x664, "resumprcs", 1,
+ 0x665, "schedprcs", 1,
+ 0x666, "saveprcs", 0,
+ 0x668, "condwait", 1,
+ 0x669, "wait", 1,
+ 0x66a, "signal", 1,
+ 0x66b, "mark", 0,
+ 0x66c, "fmark", 0,
+ 0x66d, "flushreg", 0,
+ 0x66f, "syncf", 0,
+ 0x670, "emul", 3,
+ 0x671, "ediv", 3,
+ 0x673, "ldtime", -1,
+ 0x674, "Fcvtir", -2,
+ 0x675, "Fcvtilr", -2,
+ 0x676, "Fscalerl", 3,
+ 0x677, "Fscaler", 3,
+ 0x680, "Fatanr", 3,
+ 0x681, "Flogepr", 3,
+ 0x682, "Flogr", 3,
+ 0x683, "Fremr", 3,
+ 0x684, "Fcmpor", 2,
+ 0x685, "Fcmpr", 2,
+ 0x688, "Fsqrtr", -2,
+ 0x689, "Fexpr", -2,
+ 0x68a, "Flogbnr", -2,
+ 0x68b, "Froundr", -2,
+ 0x68c, "Fsinr", -2,
+ 0x68d, "Fcosr", -2,
+ 0x68e, "Ftanr", -2,
+ 0x68f, "Fclassr", 1,
+ 0x690, "Fatanrl", 3,
+ 0x691, "Flogeprl", 3,
+ 0x692, "Flogrl", 3,
+ 0x693, "Fremrl", 3,
+ 0x694, "Fcmporl", 2,
+ 0x695, "Fcmprl", 2,
+ 0x698, "Fsqrtrl", -2,
+ 0x699, "Fexprl", -2,
+ 0x69a, "Flogbnrl", -2,
+ 0x69b, "Froundrl", -2,
+ 0x69c, "Fsinrl", -2,
+ 0x69d, "Fcosrl", -2,
+ 0x69e, "Ftanrl", -2,
+ 0x69f, "Fclassrl", 1,
+ 0x6c0, "Fcvtri", -2,
+ 0x6c1, "Fcvtril", -2,
+ 0x6c2, "Fcvtzri", -2,
+ 0x6c3, "Fcvtzril", -2,
+ 0x6c9, "Fmovr", -2,
+ 0x6d9, "Fmovrl", -2,
+ 0x6e1, "Fmovre", -2,
+ 0x6e2, "Fcpysre", 3,
+ 0x6e3, "Fcpyrsre", 3,
+ 0x701, "mulo", 3,
+ 0x708, "remo", 3,
+ 0x70b, "divo", 3,
+ 0x741, "muli", 3,
+ 0x748, "remi", 3,
+ 0x749, "modi", 3,
+ 0x74b, "divi", 3,
+ 0x78b, "Fdivr", 3,
+ 0x78c, "Fmulr", 3,
+ 0x78d, "Fsubr", 3,
+ 0x78f, "Faddr", 3,
+ 0x79b, "Fdivrl", 3,
+ 0x79c, "Fmulrl", 3,
+ 0x79d, "Fsubrl", 3,
+ 0x79f, "Faddrl", 3,
+#define REG_MAX 0x79f
+#define REG_SIZ ((REG_MAX-REG_MIN+1) * sizeof(struct tabent))
+ 0, NULL, 0
+ };
+
+ if ( reg_tab == NULL ){
+ reg_tab = (struct tabent *) xmalloc( REG_SIZ );
+ bzero( reg_tab, REG_SIZ );
+ for ( i = 0; reg_init[i].opcode != 0; i++ ){
+ j = reg_init[i].opcode - REG_MIN;
+ reg_tab[j].name = reg_init[i].name;
+ reg_tab[j].numops = reg_init[i].numops;
+ }
+ }
+
+ opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf);
+ i = opcode - REG_MIN;
+
+ if ( (opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL) ){
+ invalid( word1 );
+ return;
+ }
+
+ mnemp = reg_tab[i].name;
+ if ( *mnemp == 'F' ){
+ fp = 1;
+ mnemp++;
+ } else {
+ fp = 0;
+ }
+
+ fputs( mnemp, stream );
+
+ s1 = (word1 >> 5) & 1;
+ s2 = (word1 >> 6) & 1;
+ m1 = (word1 >> 11) & 1;
+ m2 = (word1 >> 12) & 1;
+ m3 = (word1 >> 13) & 1;
+ src = word1 & 0x1f;
+ src2 = (word1 >> 14) & 0x1f;
+ dst = (word1 >> 19) & 0x1f;
+
+ if ( reg_tab[i].numops != 0 ){
+ putc( '\t', stream );
+
+ switch ( reg_tab[i].numops ){
+ case 1:
+ regop( m1, s1, src, fp );
+ break;
+ case -1:
+ dstop( m3, dst, fp );
+ break;
+ case 2:
+ regop( m1, s1, src, fp );
+ putc( ',', stream );
+ regop( m2, s2, src2, fp );
+ break;
+ case -2:
+ regop( m1, s1, src, fp );
+ putc( ',', stream );
+ dstop( m3, dst, fp );
+ break;
+ case 3:
+ regop( m1, s1, src, fp );
+ putc( ',', stream );
+ regop( m2, s2, src2, fp );
+ putc( ',', stream );
+ dstop( m3, dst, fp );
+ break;
+ }
+ }
+}
+
+
+/*
+ * Print out effective address for memb instructions.
+ */
+static void
+ea( memaddr, mode, reg2, reg3, word1, word2 )
+ unsigned long memaddr;
+ int mode;
+ char *reg2, *reg3;
+ unsigned int word2;
+{
+ int scale;
+ static int scale_tab[] = { 1, 2, 4, 8, 16 };
+
+ scale = (word1 >> 7) & 0x07;
+ if ( (scale > 4) || ((word1 >> 5) & 0x03 != 0) ){
+ invalid( word1 );
+ return;
+ }
+ scale = scale_tab[scale];
+
+ switch (mode) {
+ case 4: /* (reg) */
+ fprintf( stream, "(%s)", reg2 );
+ break;
+ case 5: /* displ+8(ip) */
+ print_addr( word2+8+memaddr );
+ break;
+ case 7: /* (reg)[index*scale] */
+ if (scale == 1) {
+ fprintf( stream, "(%s)[%s]", reg2, reg3 );
+ } else {
+ fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale);
+ }
+ break;
+ case 12: /* displacement */
+ print_addr( word2 );
+ break;
+ case 13: /* displ(reg) */
+ print_addr( word2 );
+ fprintf( stream, "(%s)", reg2 );
+ break;
+ case 14: /* displ[index*scale] */
+ print_addr( word2 );
+ if (scale == 1) {
+ fprintf( stream, "[%s]", reg3 );
+ } else {
+ fprintf( stream, "[%s*%d]", reg3, scale );
+ }
+ break;
+ case 15: /* displ(reg)[index*scale] */
+ print_addr( word2 );
+ if (scale == 1) {
+ fprintf( stream, "(%s)[%s]", reg2, reg3 );
+ } else {
+ fprintf( stream, "(%s)[%s*%d]",reg2,reg3,scale );
+ }
+ break;
+ default:
+ invalid( word1 );
+ return;
+ }
+}
+
+
+/************************************************/
+/* Register Instruction Operand */
+/************************************************/
+static void
+regop( mode, spec, reg, fp )
+ int mode, spec, reg, fp;
+{
+ if ( fp ){ /* FLOATING POINT INSTRUCTION */
+ if ( mode == 1 ){ /* FP operand */
+ switch ( reg ){
+ case 0: fputs( "fp0", stream ); break;
+ case 1: fputs( "fp1", stream ); break;
+ case 2: fputs( "fp2", stream ); break;
+ case 3: fputs( "fp3", stream ); break;
+ case 16: fputs( "0f0.0", stream ); break;
+ case 22: fputs( "0f1.0", stream ); break;
+ default: putc( '?', stream ); break;
+ }
+ } else { /* Non-FP register */
+ fputs( reg_names[reg], stream );
+ }
+ } else { /* NOT FLOATING POINT */
+ if ( mode == 1 ){ /* Literal */
+ fprintf( stream, "%d", reg );
+ } else { /* Register */
+ if ( spec == 0 ){
+ fputs( reg_names[reg], stream );
+ } else {
+ fprintf( stream, "sf%d", reg );
+ }
+ }
+ }
+}
+
+/************************************************/
+/* Register Instruction Destination Operand */
+/************************************************/
+static void
+dstop( mode, reg, fp )
+ int mode, reg, fp;
+{
+ /* 'dst' operand can't be a literal. On non-FP instructions, register
+ * mode is assumed and "m3" acts as if were "s3"; on FP-instructions,
+ * sf registers are not allowed so m3 acts normally.
+ */
+ if ( fp ){
+ regop( mode, 0, reg, fp );
+ } else {
+ regop( 0, mode, reg, fp );
+ }
+}
+
+
+static void
+invalid( word1 )
+ int word1;
+{
+ fprintf( stream, ".word\t0x%08x", word1 );
+}
+
+static void
+print_addr(a)
+{
+ fprintf( stream, "0x%x", a );
+}
+
+static void
+put_abs( word1, word2 )
+ unsigned long word1, word2;
+{
+#ifdef IN_GDB
+ return;
+#else
+ int len;
+
+ switch ( (word1 >> 28) & 0xf ){
+ case 0x8:
+ case 0x9:
+ case 0xa:
+ case 0xb:
+ case 0xc:
+ /* MEM format instruction */
+ len = mem( 0, word1, word2, 1 );
+ break;
+ default:
+ len = 4;
+ break;
+ }
+
+ if ( len == 8 ){
+ fprintf( stream, "%08x %08x\t", word1, word2 );
+ } else {
+ fprintf( stream, "%08x \t", word1 );
+ }
+;
+
+#endif
+}
--- /dev/null
+/* Target-machine dependent code for the Intel 960
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+ examine_prologue and other parts contributed by Wind River Systems.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Miscellaneous i80960-dependent routines.
+ Most are called from macros defined in "tm-i960.h". */
+
+#include <stdio.h>
+#include <signal.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "frame.h"
+#include "signame.h"
+#include "ieee-float.h"
+
+/* Structure of i960 extended floating point format. */
+
+const struct ext_format ext_format_i960 [] = {
+/* tot sbyte smask expbyte manbyte */
+ { 12, 9, 0x80, 9,8, 4,0 }, /* i960 */
+};
+
+/* gdb960 is always running on a non-960 host. Check its characteristics.
+ This routine must be called as part of gdb initialization. */
+
+static void
+check_host()
+{
+ int i;
+
+ static struct typestruct {
+ int hostsize; /* Size of type on host */
+ int i960size; /* Size of type on i960 */
+ char *typename; /* Name of type, for error msg */
+ } types[] = {
+ { sizeof(short), 2, "short" },
+ { sizeof(int), 4, "int" },
+ { sizeof(long), 4, "long" },
+ { sizeof(float), 4, "float" },
+ { sizeof(double), 8, "double" },
+ { sizeof(char *), 4, "pointer" },
+ };
+#define TYPELEN (sizeof(types) / sizeof(struct typestruct))
+
+ /* Make sure that host type sizes are same as i960
+ */
+ for ( i = 0; i < TYPELEN; i++ ){
+ if ( types[i].hostsize != types[i].i960size ){
+ printf("sizeof(%s) != %d: PROCEED AT YOUR OWN RISK!\n",
+ types[i].typename, types[i].i960size );
+ }
+
+ }
+}
+\f
+/* Examine an i960 function prologue, recording the addresses at which
+ registers are saved explicitly by the prologue code, and returning
+ the address of the first instruction after the prologue (but not
+ after the instruction at address LIMIT, as explained below).
+
+ LIMIT places an upper bound on addresses of the instructions to be
+ examined. If the prologue code scan reaches LIMIT, the scan is
+ aborted and LIMIT is returned. This is used, when examining the
+ prologue for the current frame, to keep examine_prologue () from
+ claiming that a given register has been saved when in fact the
+ instruction that saves it has not yet been executed. LIMIT is used
+ at other times to stop the scan when we hit code after the true
+ function prologue (e.g. for the first source line) which might
+ otherwise be mistaken for function prologue.
+
+ The format of the function prologue matched by this routine is
+ derived from examination of the source to gcc960 1.21, particularly
+ the routine i960_function_prologue (). A "regular expression" for
+ the function prologue is given below:
+
+ (lda LRn, g14
+ mov g14, g[0-7]
+ (mov 0, g14) | (lda 0, g14))?
+
+ (mov[qtl]? g[0-15], r[4-15])*
+ ((addo [1-31], sp, sp) | (lda n(sp), sp))?
+ (st[qtl]? g[0-15], n(fp))*
+
+ (cmpobne 0, g14, LFn
+ mov sp, g14
+ lda 0x30(sp), sp
+ LFn: stq g0, (g14)
+ stq g4, 0x10(g14)
+ stq g8, 0x20(g14))?
+
+ (st g14, n(fp))?
+ (mov g13,r[4-15])?
+*/
+
+/* Macros for extracting fields from i960 instructions. */
+
+#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
+#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
+
+#define REG_SRC1(insn) EXTRACT_FIELD (insn, 0, 5)
+#define REG_SRC2(insn) EXTRACT_FIELD (insn, 14, 5)
+#define REG_SRCDST(insn) EXTRACT_FIELD (insn, 19, 5)
+#define MEM_SRCDST(insn) EXTRACT_FIELD (insn, 19, 5)
+#define MEMA_OFFSET(insn) EXTRACT_FIELD (insn, 0, 12)
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction, and (for two-word instructions), *PWORD2 receives
+ the second. */
+
+#define NEXT_PROLOGUE_INSN(addr, lim, pword1, pword2) \
+ (((addr) < (lim)) ? next_insn (addr, pword1, pword2) : 0)
+
+static CORE_ADDR
+examine_prologue (ip, limit, frame_addr, fsr)
+ register CORE_ADDR ip;
+ register CORE_ADDR limit;
+ FRAME_ADDR frame_addr;
+ struct frame_saved_regs *fsr;
+{
+ register CORE_ADDR next_ip;
+ register int src, dst;
+ register unsigned int *pcode;
+ unsigned int insn1, insn2;
+ int size;
+ int within_leaf_prologue;
+ CORE_ADDR save_addr;
+ static unsigned int varargs_prologue_code [] =
+ {
+ 0x3507a00c, /* cmpobne 0x0, g14, LFn */
+ 0x5cf01601, /* mov sp, g14 */
+ 0x8c086030, /* lda 0x30(sp), sp */
+ 0xb2879000, /* LFn: stq g0, (g14) */
+ 0xb2a7a010, /* stq g4, 0x10(g14) */
+ 0xb2c7a020 /* stq g8, 0x20(g14) */
+ };
+
+ /* Accept a leaf procedure prologue code fragment if present.
+ Note that ip might point to either the leaf or non-leaf
+ entry point; we look for the non-leaf entry point first: */
+
+ within_leaf_prologue = 0;
+ if ((next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2))
+ && ((insn1 & 0xfffff000) == 0x8cf00000 /* lda LRx, g14 (MEMA) */
+ || (insn1 & 0xfffffc60) == 0x8cf03000)) /* lda LRx, g14 (MEMB) */
+ {
+ within_leaf_prologue = 1;
+ next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2);
+ }
+
+ /* Now look for the prologue code at a leaf entry point: */
+
+ if (next_ip
+ && (insn1 & 0xff87ffff) == 0x5c80161e /* mov g14, gx */
+ && REG_SRCDST (insn1) <= G0_REGNUM + 7)
+ {
+ within_leaf_prologue = 1;
+ if ((next_ip = NEXT_PROLOGUE_INSN (next_ip, limit, &insn1, &insn2))
+ && (insn1 == 0x8cf00000 /* lda 0, g14 */
+ || insn1 == 0x5cf01e00)) /* mov 0, g14 */
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ within_leaf_prologue = 0;
+ }
+ }
+
+ /* If something that looks like the beginning of a leaf prologue
+ has been seen, but the remainder of the prologue is missing, bail.
+ We don't know what we've got. */
+
+ if (within_leaf_prologue)
+ return (ip);
+
+ /* Accept zero or more instances of "mov[qtl]? gx, ry", where y >= 4.
+ This may cause us to mistake the moving of a register
+ parameter to a local register for the saving of a callee-saved
+ register, but that can't be helped, since with the
+ "-fcall-saved" flag, any register can be made callee-saved. */
+
+ while (next_ip
+ && (insn1 & 0xfc802fb0) == 0x5c000610
+ && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))
+ {
+ src = REG_SRC1 (insn1);
+ size = EXTRACT_FIELD (insn1, 24, 2) + 1;
+ save_addr = frame_addr + ((dst - R0_REGNUM) * 4);
+ while (size--)
+ {
+ fsr->regs[src++] = save_addr;
+ save_addr += 4;
+ }
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept an optional "addo n, sp, sp" or "lda n(sp), sp". */
+
+ if (next_ip &&
+ ((insn1 & 0xffffffe0) == 0x59084800 /* addo n, sp, sp */
+ || (insn1 & 0xfffff000) == 0x8c086000 /* lda n(sp), sp (MEMA) */
+ || (insn1 & 0xfffffc60) == 0x8c087400)) /* lda n(sp), sp (MEMB) */
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept zero or more instances of "st[qtl]? gx, n(fp)".
+ This may cause us to mistake the copying of a register
+ parameter to the frame for the saving of a callee-saved
+ register, but that can't be helped, since with the
+ "-fcall-saved" flag, any register can be made callee-saved.
+ We can, however, refuse to accept a save of register g14,
+ since that is matched explicitly below. */
+
+ while (next_ip &&
+ ((insn1 & 0xf787f000) == 0x9287e000 /* stl? gx, n(fp) (MEMA) */
+ || (insn1 & 0xf787fc60) == 0x9287f400 /* stl? gx, n(fp) (MEMB) */
+ || (insn1 & 0xef87f000) == 0xa287e000 /* st[tq] gx, n(fp) (MEMA) */
+ || (insn1 & 0xef87fc60) == 0xa287f400) /* st[tq] gx, n(fp) (MEMB) */
+ && ((src = MEM_SRCDST (insn1)) != G14_REGNUM))
+ {
+ save_addr = frame_addr + ((insn1 & BITMASK (12, 1))
+ ? insn2 : MEMA_OFFSET (insn1));
+ size = (insn1 & BITMASK (29, 1)) ? ((insn1 & BITMASK (28, 1)) ? 4 : 3)
+ : ((insn1 & BITMASK (27, 1)) ? 2 : 1);
+ while (size--)
+ {
+ fsr->regs[src++] = save_addr;
+ save_addr += 4;
+ }
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept the varargs prologue code if present. */
+
+ size = sizeof (varargs_prologue_code) / sizeof (int);
+ pcode = varargs_prologue_code;
+ while (size-- && next_ip && *pcode++ == insn1)
+ {
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept an optional "st g14, n(fp)". */
+
+ if (next_ip &&
+ ((insn1 & 0xfffff000) == 0x92f7e000 /* st g14, n(fp) (MEMA) */
+ || (insn1 & 0xfffffc60) == 0x92f7f400)) /* st g14, n(fp) (MEMB) */
+ {
+ fsr->regs[G14_REGNUM] = frame_addr + ((insn1 & BITMASK (12, 1))
+ ? insn2 : MEMA_OFFSET (insn1));
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+ }
+
+ /* Accept zero or one instance of "mov g13, ry", where y >= 4.
+ This is saving the address where a struct should be returned. */
+
+ if (next_ip
+ && (insn1 & 0xff802fbf) == 0x5c00061d
+ && (dst = REG_SRCDST (insn1)) >= (R0_REGNUM + 4))
+ {
+ save_addr = frame_addr + ((dst - R0_REGNUM) * 4);
+ fsr->regs[G0_REGNUM+13] = save_addr;
+ ip = next_ip;
+#if 0 /* We'll need this once there is a subsequent instruction examined. */
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn1, &insn2);
+#endif
+ }
+
+ return (ip);
+}
+
+/* Given an ip value corresponding to the start of a function,
+ return the ip of the first instruction after the function
+ prologue. */
+
+CORE_ADDR
+skip_prologue (ip)
+ CORE_ADDR (ip);
+{
+ struct frame_saved_regs saved_regs_dummy;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end) ? sal.end : 0xffffffff;
+
+ return (examine_prologue (ip, limit, (FRAME_ADDR) 0, &saved_regs_dummy));
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ We cache the result of doing this in the frame_cache_obstack, since
+ it is fairly expensive. */
+
+void
+frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ register CORE_ADDR next_addr;
+ register CORE_ADDR *saved_regs;
+ register int regnum;
+ register struct frame_saved_regs *cache_fsr;
+ extern struct obstack frame_cache_obstack;
+ CORE_ADDR ip;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ if (!fi->fsr)
+ {
+ cache_fsr = (struct frame_saved_regs *)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_saved_regs));
+ bzero (cache_fsr, sizeof (struct frame_saved_regs));
+ fi->fsr = cache_fsr;
+
+ /* Find the start and end of the function prologue. If the PC
+ is in the function prologue, we only consider the part that
+ has executed already. */
+
+ ip = get_pc_function_start (fi->pc);
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end && sal.end < fi->pc) ? sal.end: fi->pc;
+
+ examine_prologue (ip, limit, fi->frame, cache_fsr);
+
+ /* Record the addresses at which the local registers are saved.
+ Strictly speaking, we should only do this for non-leaf procedures,
+ but no one will ever look at these values if it is a leaf procedure,
+ since local registers are always caller-saved. */
+
+ next_addr = (CORE_ADDR) fi->frame;
+ saved_regs = cache_fsr->regs;
+ for (regnum = R0_REGNUM; regnum <= R15_REGNUM; regnum++)
+ {
+ *saved_regs++ = next_addr;
+ next_addr += 4;
+ }
+
+ cache_fsr->regs[FP_REGNUM] = cache_fsr->regs[PFP_REGNUM];
+ }
+
+ *fsr = *fi->fsr;
+
+ /* Fetch the value of the sp from memory every time, since it
+ is conceivable that it has changed since the cache was flushed.
+ This unfortunately undoes much of the savings from caching the
+ saved register values. I suggest adding an argument to
+ get_frame_saved_regs () specifying the register number we're
+ interested in (or -1 for all registers). This would be passed
+ through to FRAME_FIND_SAVED_REGS (), permitting more efficient
+ computation of saved register addresses (e.g., on the i960,
+ we don't have to examine the prologue to find local registers).
+ -- markf@wrs.com
+ FIXME, we don't need to refetch this, since the cache is cleared
+ every time the child process is restarted. If GDB itself
+ modifies SP, it has to clear the cache by hand (does it?). -gnu */
+
+ fsr->regs[SP_REGNUM] = read_memory_integer (fsr->regs[SP_REGNUM], 4);
+}
+
+/* Return the address of the argument block for the frame
+ described by FI. Returns 0 if the address is unknown. */
+
+CORE_ADDR
+frame_args_address (fi, must_be_correct)
+ struct frame_info *fi;
+{
+ register FRAME frame;
+ struct frame_saved_regs fsr;
+ CORE_ADDR ap;
+
+ /* If g14 was saved in the frame by the function prologue code, return
+ the saved value. If the frame is current and we are being sloppy,
+ return the value of g14. Otherwise, return zero. */
+
+ frame = FRAME_INFO_ID (fi);
+ get_frame_saved_regs (fi, &fsr);
+ if (fsr.regs[G14_REGNUM])
+ ap = read_memory_integer (fsr.regs[G14_REGNUM],4);
+ else {
+ if (must_be_correct)
+ return 0; /* Don't cache this result */
+ if (get_next_frame (frame))
+ ap = 0;
+ else
+ ap = read_register (G14_REGNUM);
+ }
+ fi->arg_pointer = ap; /* Cache it for next time */
+ return ap;
+}
+
+/* Return the address of the return struct for the frame
+ described by FI. Returns 0 if the address is unknown. */
+
+CORE_ADDR
+frame_struct_result_address (fi)
+ struct frame_info *fi;
+{
+ register FRAME frame;
+ struct frame_saved_regs fsr;
+ CORE_ADDR ap;
+
+ /* If the frame is non-current, check to see if g14 was saved in the
+ frame by the function prologue code; return the saved value if so,
+ zero otherwise. If the frame is current, return the value of g14.
+
+ FIXME, shouldn't this use the saved value as long as we are past
+ the function prologue, and only use the current value if we have
+ no saved value and are at TOS? -- gnu@cygnus.com */
+
+ frame = FRAME_INFO_ID (fi);
+ if (get_next_frame (frame)) {
+ get_frame_saved_regs (fi, &fsr);
+ if (fsr.regs[G13_REGNUM])
+ ap = read_memory_integer (fsr.regs[G13_REGNUM],4);
+ else
+ ap = 0;
+ } else {
+ ap = read_register (G13_REGNUM);
+ }
+ return ap;
+}
+
+/* Return address to which the currently executing leafproc will return,
+ or 0 if ip is not in a leafproc (or if we can't tell if it is).
+
+ Do this by finding the starting address of the routine in which ip lies.
+ If the instruction there is "mov g14, gx" (where x is in [0,7]), this
+ is a leafproc and the return address is in register gx. Well, this is
+ true unless the return address points at a RET instruction in the current
+ procedure, which indicates that we have a 'dual entry' routine that
+ has been entered through the CALL entry point. */
+
+CORE_ADDR
+leafproc_return (ip)
+ CORE_ADDR ip; /* ip from currently executing function */
+{
+ int i;
+ register struct misc_function *mf;
+ char *p;
+ int dst;
+ unsigned int insn1, insn2;
+ CORE_ADDR return_addr;
+ char *index ();
+
+ if ((i = find_pc_misc_function (ip)) >= 0)
+ {
+ mf = &misc_function_vector[i];
+ if ((p = index (mf->name, '.')) && !strcmp (p, ".lf"))
+ {
+ if (next_insn (mf->address, &insn1, &insn2)
+ && (insn1 & 0xff87ffff) == 0x5c80161e /* mov g14, gx */
+ && (dst = REG_SRCDST (insn1)) <= G0_REGNUM + 7)
+ {
+ /* Get the return address. If the "mov g14, gx"
+ instruction hasn't been executed yet, read
+ the return address from g14; otherwise, read it
+ from the register into which g14 was moved. */
+
+ return_addr = read_register ((ip == mf->address)
+ ? G14_REGNUM : dst);
+
+ /* We know we are in a leaf procedure, but we don't know
+ whether the caller actually did a "bal" to the ".lf"
+ entry point, or a normal "call" to the non-leaf entry
+ point one instruction before. In the latter case, the
+ return address will be the address of a "ret"
+ instruction within the procedure itself. We test for
+ this below. */
+
+ if (!next_insn (return_addr, &insn1, &insn2)
+ || (insn1 & 0xff000000) != 0xa000000 /* ret */
+ || find_pc_misc_function (return_addr) != i)
+ return (return_addr);
+ }
+ }
+ }
+
+ return (0);
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions.
+ On the i960, the frame *is* set up immediately after the call,
+ unless the function is a leaf procedure. */
+
+CORE_ADDR
+saved_pc_after_call (frame)
+ FRAME frame;
+{
+ CORE_ADDR saved_pc;
+ CORE_ADDR get_frame_pc ();
+
+ saved_pc = leafproc_return (get_frame_pc (frame));
+ if (!saved_pc)
+ saved_pc = FRAME_SAVED_PC (frame);
+
+ return (saved_pc);
+}
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+pop_frame ()
+{
+ register struct frame_info *current_fi, *prev_fi;
+ register int i;
+ CORE_ADDR save_addr;
+ CORE_ADDR leaf_return_addr;
+ struct frame_saved_regs fsr;
+ char local_regs_buf[16 * 4];
+
+ current_fi = get_frame_info (get_current_frame ());
+
+ /* First, undo what the hardware does when we return.
+ If this is a non-leaf procedure, restore local registers from
+ the save area in the calling frame. Otherwise, load the return
+ address obtained from leafproc_return () into the rip. */
+
+ leaf_return_addr = leafproc_return (current_fi->pc);
+ if (!leaf_return_addr)
+ {
+ /* Non-leaf procedure. Restore local registers, incl IP. */
+ prev_fi = get_frame_info (get_prev_frame (FRAME_INFO_ID (current_fi)));
+ read_memory (prev_fi->frame, local_regs_buf, sizeof (local_regs_buf));
+ write_register_bytes (REGISTER_BYTE (R0_REGNUM), local_regs_buf,
+ sizeof (local_regs_buf));
+
+ /* Restore frame pointer. */
+ write_register (FP_REGNUM, prev_fi->frame);
+ }
+ else
+ {
+ /* Leaf procedure. Just restore the return address into the IP. */
+ write_register (RIP_REGNUM, leaf_return_addr);
+ }
+
+ /* Now restore any global regs that the current function had saved. */
+ get_frame_saved_regs (current_fi, &fsr);
+ for (i = G0_REGNUM; i < G14_REGNUM; i++)
+ {
+ if (save_addr = fsr.regs[i])
+ write_register (i, read_memory_integer (save_addr, 4));
+ }
+
+ /* Flush the frame cache, create a frame for the new innermost frame,
+ and make it the current frame. */
+
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_register (FP_REGNUM), read_pc ()));
+}
+
+/* Print out text describing a "signal number" with which the i80960 halted.
+
+ See the file "fault.c" in the nindy monitor source code for a list
+ of stop codes. */
+
+void
+print_fault( siggnal )
+ int siggnal; /* Signal number, as returned by target_wait() */
+{
+ static char unknown[] = "Unknown fault or trace";
+ static char *sigmsgs[] = {
+ /* FAULTS */
+ "parallel fault", /* 0x00 */
+ unknown, /* 0x01 */
+ "operation fault", /* 0x02 */
+ "arithmetic fault", /* 0x03 */
+ "floating point fault", /* 0x04 */
+ "constraint fault", /* 0x05 */
+ "virtual memory fault", /* 0x06 */
+ "protection fault", /* 0x07 */
+ "machine fault", /* 0x08 */
+ "structural fault", /* 0x09 */
+ "type fault", /* 0x0a */
+ "reserved (0xb) fault", /* 0x0b */
+ "process fault", /* 0x0c */
+ "descriptor fault", /* 0x0d */
+ "event fault", /* 0x0e */
+ "reserved (0xf) fault", /* 0x0f */
+
+ /* TRACES */
+ "single-step trace", /* 0x10 */
+ "branch trace", /* 0x11 */
+ "call trace", /* 0x12 */
+ "return trace", /* 0x13 */
+ "pre-return trace", /* 0x14 */
+ "supervisor call trace",/* 0x15 */
+ "breakpoint trace", /* 0x16 */
+ };
+# define NUMMSGS ((int)( sizeof(sigmsgs) / sizeof(sigmsgs[0]) ))
+
+ if (siggnal < NSIG) {
+ printf ("\nProgram received signal %d, %s\n",
+ siggnal,
+ sys_siglist[siggnal]);
+ } else {
+ /* The various target_wait()s bias the 80960 "signal number"
+ by adding NSIG to it, so it won't get confused with any
+ of the Unix signals elsewhere in GDB. We need to
+ "unbias" it before using it. */
+ siggnal -= NSIG;
+
+ printf("Program stopped for reason #%d: %s.\n", siggnal,
+ (siggnal < NUMMSGS && siggnal >= 0)?
+ sigmsgs[siggnal] : unknown );
+ }
+}
+
+/* Initialization stub */
+
+_initialize_i960_tdep ()
+{
+ check_host ();
+}
--- /dev/null
+/* IEEE floating point support routines, for GDB, the GNU Debugger.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+#include "ieee-float.h"
+#include <math.h> /* ldexp */
+
+/* Convert an IEEE extended float to a double.
+ FROM is the address of the extended float.
+ Store the double in *TO. */
+
+void
+ieee_extended_to_double (ext_format, from, to)
+ struct ext_format *ext_format;
+ char *from;
+ double *to;
+{
+ unsigned char *ufrom = (unsigned char *)from;
+ double dto;
+ unsigned long mant0, mant1, exp;
+
+ bcopy (&from[MANBYTE_H], &mant0, 4);
+ bcopy (&from[MANBYTE_L], &mant1, 4);
+ exp = ((ufrom[EXPBYTE_H] & (unsigned char)~SIGNMASK) << 8) | ufrom[EXPBYTE_L];
+
+ if (exp == EXT_EXP_NAN) {
+ /* We have a NaN source. */
+ dto = 0.123456789; /* Not much else useful to do */
+ } else if (exp == 0 && mant0 == 0 && mant1 == 0) {
+ dto = 0;
+ } else {
+ /* Build the result algebraically. Might go infinite, underflow, etc;
+ who cares. */
+ mant0 |= 0x80000000;
+ dto = ldexp ((double)mant0, exp - EXT_EXP_BIAS - 31);
+ dto += ldexp ((double)mant1, exp - EXT_EXP_BIAS - 31 - 32);
+ }
+ *to = dto;
+}
+
+/* The converse: convert the double *FROM to an extended float
+ and store where TO points. */
+
+void
+double_to_ieee_extended (ext_format, from, to)
+ struct ext_format *ext_format;
+ double *from;
+ char *to;
+{
+ double dfrom = *from;
+ unsigned long twolongs[2];
+ unsigned long mant0, mant1, exp;
+ unsigned char twobytes[2];
+
+ bzero (to, TOTALSIZE);
+ if (dfrom == 0)
+ return; /* Result is zero */
+ if (dfrom != dfrom) {
+ /* From is NaN */
+ to[EXPBYTE_H] = (unsigned char)(EXT_EXP_NAN >> 8);
+ to[EXPBYTE_L] = (unsigned char)EXT_EXP_NAN;
+ to[MANBYTE_H] = 1; /* Be sure it's not infinity, but NaN value is irrel */
+ return; /* Result is NaN */
+ }
+ if (dfrom < 0)
+ to[SIGNBYTE] |= SIGNMASK; /* Set negative sign */
+ /* How to tell an infinity from an ordinary number? FIXME-someday */
+
+ /* The following code assumes that the host has IEEE doubles. FIXME-someday.
+ It also assumes longs are 32 bits! FIXME-someday. */
+ bcopy (from, twolongs, 8);
+ bcopy (from, twobytes, 2);
+#if HOST_BYTE_ORDER == BIG_ENDIAN
+ exp = ((twobytes[1] & 0xF0) >> 4) | (twobytes[0] & 0x7F) << 4;
+ mant0 = (twolongs[0] << 11) | twolongs[1] >> 21;
+ mant1 = (twolongs[1] << 11);
+#else
+ exp = ((twobytes[0] & 0xF0) >> 4) | (twobytes[1] & 0x7F) << 4;
+ mant0 = (twolongs[1] << 11) | twolongs[0] >> 21;
+ mant1 = (twolongs[0] << 11);
+#endif
+
+ /* Fiddle with leading 1-bit, implied in double, explicit in extended. */
+ if (exp == 0)
+ mant0 &= 0x7FFFFFFF;
+ else
+ mant0 |= 0x80000000;
+
+ exp -= DBL_EXP_BIAS; /* Get integer exp */
+ exp += EXT_EXP_BIAS; /* Offset for extended *&/
+
+ /* OK, now store it in extended format. */
+ to[EXPBYTE_H] |= (unsigned char)(exp >> 8); /* Retain sign */
+ to[EXPBYTE_L] = (unsigned char) exp;
+
+ bcopy (&mant0, &to[MANBYTE_H], 4);
+ bcopy (&mant1, &to[MANBYTE_L], 4);
+}
+
+
+#ifdef DEBUG
+
+/* Test some numbers to see that extended/double conversion works for them. */
+
+ieee_test (n)
+ int n;
+{
+ union { double d; int i[2]; } di;
+ double result;
+ int i;
+ char exten[16];
+ extern struct ext_format ext_format_68881;
+
+ for (i = 0; i < n; i++) {
+ di.i[0] = random();
+ di.i[1] = random();
+ double_to_ieee_extended (ext_format_68881, &di.d, exten);
+ ieee_extended_to_double (ext_format_68881, exten, &result);
+ if (di.d != result)
+ printf ("Differ: %x %x %g => %x %x %g\n", di.d, di.d, result, result);
+ }
+}
+
+#endif
--- /dev/null
+/* IEEE floating point support declarations, for GDB, the GNU Debugger.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Parameters for extended float format: */
+
+struct ext_format {
+ unsigned totalsize; /* Total size of extended number */
+ unsigned signbyte; /* Byte number of sign bit */
+ unsigned char signmask; /* Mask for sign bit */
+ unsigned expbyte_h; /* High byte of exponent */
+ unsigned expbyte_l; /* Low byte of exponent */
+ unsigned manbyte_h; /* High byte of mantissa */
+ unsigned manbyte_l; /* Low byte of mantissa */
+};
+
+#define TOTALSIZE ext_format->totalsize
+#define SIGNBYTE ext_format->signbyte
+#define SIGNMASK ext_format->signmask
+#define EXPBYTE_H ext_format->expbyte_h
+#define EXPBYTE_L ext_format->expbyte_l
+#define MANBYTE_H ext_format->manbyte_h
+#define MANBYTE_L ext_format->manbyte_l
+
+/* Actual ext_format structs for various machines are in the *-tdep.c file
+ for each machine. */
+
+#define EXT_EXP_NAN 0x7FFF /* Exponent value that indicates NaN */
+#define EXT_EXP_BIAS 0x3FFF /* Amount added to "true" exponent for ext */
+#define DBL_EXP_BIAS 0x3FF /* Ditto, for doubles */
+
+/* Convert an IEEE extended float to a double.
+ FROM is the address of the extended float.
+ Store the double in *TO. */
+
+extern void
+ieee_extended_to_double (
+#ifdef __STDC__
+ struct ext_format *ext_format, char *from, double *to
+#endif
+);
+
+/* The converse: convert the double *FROM to an extended float
+ and store where TO points. */
+
+void
+double_to_ieee_extended (
+#ifdef __STDC__
+ struct ext_format *ext_format, double *from, char *to
+#endif
+);
--- /dev/null
+/* Main loop for the standalone kernel debugger.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+
+static char *args[] = {"kdb", "kdb-symbols", 0};
+
+static char *environment[] = {0};
+
+char **environ;
+
+start ()
+{
+#ifdef NAMES_HAVE_UNDERSCORE
+ INIT_STACK (_kdb_stack_beg, _kdb_stack_end);
+#else /* not NAMES_HAVE_UNDERSCORE */
+ INIT_STACK (kdb_stack_beg, kdb_stack_end);
+#endif /* not NAMES_HAVE_UNDERSCORE */
+
+ environ = environment;
+
+ main (2, args, environment);
+}
--- /dev/null
+/* Opcode table for m68000/m68020 and m68881.
+ Copyright (C) 1989, Free Software Foundation.
+
+This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.
+
+Both GDB and GAS are free software; you can redistribute and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB and GAS are distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB or GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+struct m68k_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long match;
+ char *args;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and is as much longer as necessary to
+ hold the operands it has.
+
+ The match component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing two characters
+ for each operand of the instruction. The first specifies
+ the kind of operand; the second, the place it is stored. */
+
+/* Kinds of operands:
+ D data register only. Stored as 3 bits.
+ A address register only. Stored as 3 bits.
+ R either kind of register. Stored as 4 bits.
+ F floating point coprocessor register only. Stored as 3 bits.
+ O an offset (or width): immediate data 0-31 or data register.
+ Stored as 6 bits in special format for BF... insns.
+ + autoincrement only. Stored as 3 bits (number of the address register).
+ - autodecrement only. Stored as 3 bits (number of the address register).
+ Q quick immediate data. Stored as 3 bits.
+ This matches an immediate operand only when value is in range 1 .. 8.
+ M moveq immediate data. Stored as 8 bits.
+ This matches an immediate operand only when value is in range -128..127
+ T trap vector immediate data. Stored as 4 bits.
+
+ k K-factor for fmove.p instruction. Stored as a 7-bit constant or
+ a three bit register offset, depending on the field type.
+
+ # immediate data. Stored in special places (b, w or l)
+ which say how many bits to store.
+ ^ immediate data for floating point instructions. Special places
+ are offset by 2 bytes from '#'...
+ B pc-relative address, converted to an offset
+ that is treated as immediate data.
+ d displacement and register. Stores the register as 3 bits
+ and stores the displacement in the entire second word.
+
+ C the CCR. No need to store it; this is just for filtering validity.
+ S the SR. No need to store, just as with CCR.
+ U the USP. No need to store, just as with CCR.
+
+ I Coprocessor ID. Not printed if 1. The Coprocessor ID is always
+ extracted from the 'd' field of word one, which means that an extended
+ coprocessor opcode can be skipped using the 'i' place, if needed.
+
+ s System Control register for the floating point coprocessor.
+ S List of system control registers for floating point coprocessor.
+
+ J Misc register for movec instruction, stored in 'j' format.
+ Possible values:
+ 000 SFC Source Function Code reg
+ 001 DFC Data Function Code reg
+ 002 CACR Cache Control Register
+ 800 USP User Stack Pointer
+ 801 VBR Vector Base reg
+ 802 CAAR Cache Address Register
+ 803 MSP Master Stack Pointer
+ 804 ISP Interrupt Stack Pointer
+
+ L Register list of the type d0-d7/a0-a7 etc.
+ (New! Improved! Can also hold fp0-fp7, as well!)
+ The assembler tries to see if the registers match the insn by
+ looking at where the insn wants them stored.
+
+ l Register list like L, but with all the bits reversed.
+ Used for going the other way. . .
+
+ They are all stored as 6 bits using an address mode and a register number;
+ they differ in which addressing modes they match.
+
+ * all (modes 0-6,7.*)
+ ~ alterable memory (modes 2-6,7.0,7.1)(not 0,1,7.~)
+ % alterable (modes 0-6,7.0,7.1)(not 7.~)
+ ; data (modes 0,2-6,7.*)(not 1)
+ @ data, but not immediate (modes 0,2-6,7.? ? ?)(not 1,7.?) This may really be ;, the 68020 book says it is
+ ! control (modes 2,5,6,7.*-)(not 0,1,3,4,7.4)
+ & alterable control (modes 2,5,6,7.0,7.1)(not 0,1,7.? ? ?)
+ $ alterable data (modes 0,2-6,7.0,7.1)(not 1,7.~)
+ ? alterable control, or data register (modes 0,2,5,6,7.0,7.1)(not 1,3,4,7.~)
+ / control, or data register (modes 0,2,5,6,7.0,7.1,7.2,7.3)(not 1,3,4,7.4)
+*/
+
+/* JF: for the 68851 */
+/*
+ I didn't use much imagination in choosing the
+ following codes, so many of them aren't very
+ mnemonic. -rab
+
+ P pmmu register
+ Possible values:
+ 000 TC Translation Control reg
+ 100 CAL Current Access Level
+ 101 VAL Validate Access Level
+ 110 SCC Stack Change Control
+ 111 AC Access Control
+
+ W wide pmmu registers
+ Possible values:
+ 001 DRP Dma Root Pointer
+ 010 SRP Supervisor Root Pointer
+ 011 CRP Cpu Root Pointer
+
+ f function code register
+ 0 SFC
+ 1 DFC
+
+ V VAL register only
+
+ X BADx, BACx
+ 100 BAD Breakpoint Acknowledge Data
+ 101 BAC Breakpoint Acknowledge Control
+
+ Y PSR
+ Z PCSR
+
+ | memory (modes 2-6, 7.*)
+
+*/
+
+/* Places to put an operand, for non-general operands:
+ s source, low bits of first word.
+ d dest, shifted 9 in first word
+ 1 second word, shifted 12
+ 2 second word, shifted 6
+ 3 second word, shifted 0
+ 4 third word, shifted 12
+ 5 third word, shifted 6
+ 6 third word, shifted 0
+ 7 second word, shifted 7
+ 8 second word, shifted 10
+ D store in both place 1 and place 3; for divul and divsl.
+ b second word, low byte
+ w second word (entire)
+ l second and third word (entire)
+ g branch offset for bra and similar instructions.
+ The place to store depends on the magnitude of offset.
+ t store in both place 7 and place 8; for floating point operations
+ c branch offset for cpBcc operations.
+ The place to store is word two if bit six of word one is zero,
+ and words two and three if bit six of word one is one.
+ i Increment by two, to skip over coprocessor extended operands. Only
+ works with the 'I' format.
+ k Dynamic K-factor field. Bits 6-4 of word 2, used as a register number.
+ Also used for dynamic fmovem instruction.
+ C floating point coprocessor constant - 7 bits. Also used for static
+ K-factors...
+ j Movec register #, stored in 12 low bits of second word.
+
+ Places to put operand, for general operands:
+ d destination, shifted 6 bits in first word
+ b source, at low bit of first word, and immediate uses one byte
+ w source, at low bit of first word, and immediate uses two bytes
+ l source, at low bit of first word, and immediate uses four bytes
+ s source, at low bit of first word.
+ Used sometimes in contexts where immediate is not allowed anyway.
+ f single precision float, low bit of 1st word, immediate uses 4 bytes
+ F double precision float, low bit of 1st word, immediate uses 8 bytes
+ x extended precision float, low bit of 1st word, immediate uses 12 bytes
+ p packed float, low bit of 1st word, immediate uses 12 bytes
+*/
+
+#define one(x) ((x) << 16)
+#define two(x, y) (((x) << 16) + y)
+
+/*
+ *** DANGER WILL ROBINSON ***
+
+ The assembler requires that all instances of the same mnemonic must be
+ consecutive. If they aren't, the assembler will bomb at runtime
+ */
+struct m68k_opcode m68k_opcodes[] =
+{
+{"abcd", one(0140400), one(0170770), "DsDd"},
+{"abcd", one(0140410), one(0170770), "-s-d"},
+
+ /* Add instructions */
+{"addal", one(0150700), one(0170700), "*lAd"},
+{"addaw", one(0150300), one(0170700), "*wAd"},
+{"addib", one(0003000), one(0177700), "#b$b"},
+{"addil", one(0003200), one(0177700), "#l$l"},
+{"addiw", one(0003100), one(0177700), "#w$w"},
+{"addqb", one(0050000), one(0170700), "Qd$b"},
+{"addql", one(0050200), one(0170700), "Qd%l"},
+{"addqw", one(0050100), one(0170700), "Qd%w"},
+
+{"addb", one(0050000), one(0170700), "Qd$b"}, /* addq written as add */
+{"addb", one(0003000), one(0177700), "#b$b"}, /* addi written as add */
+{"addb", one(0150000), one(0170700), ";bDd"}, /* addb <ea>, Dd */
+{"addb", one(0150400), one(0170700), "Dd~b"}, /* addb Dd, <ea> */
+
+{"addw", one(0050100), one(0170700), "Qd%w"}, /* addq written as add */
+{"addw", one(0003100), one(0177700), "#w$w"}, /* addi written as add */
+{"addw", one(0150300), one(0170700), "*wAd"}, /* adda written as add */
+{"addw", one(0150100), one(0170700), "*wDd"}, /* addw <ea>, Dd */
+{"addw", one(0150500), one(0170700), "Dd~w"}, /* addw Dd, <ea> */
+
+{"addl", one(0050200), one(0170700), "Qd%l"}, /* addq written as add */
+{"addl", one(0003200), one(0177700), "#l$l"}, /* addi written as add */
+{"addl", one(0150700), one(0170700), "*lAd"}, /* adda written as add */
+{"addl", one(0150200), one(0170700), "*lDd"}, /* addl <ea>, Dd */
+{"addl", one(0150600), one(0170700), "Dd~l"}, /* addl Dd, <ea> */
+
+{"addxb", one(0150400), one(0170770), "DsDd"},
+{"addxb", one(0150410), one(0170770), "-s-d"},
+{"addxl", one(0150600), one(0170770), "DsDd"},
+{"addxl", one(0150610), one(0170770), "-s-d"},
+{"addxw", one(0150500), one(0170770), "DsDd"},
+{"addxw", one(0150510), one(0170770), "-s-d"},
+
+{"andib", one(0001000), one(0177700), "#b$b"},
+{"andib", one(0001074), one(0177777), "#bCb"}, /* andi to ccr */
+{"andiw", one(0001100), one(0177700), "#w$w"},
+{"andiw", one(0001174), one(0177777), "#wSw"}, /* andi to sr */
+{"andil", one(0001200), one(0177700), "#l$l"},
+
+{"andb", one(0001000), one(0177700), "#b$b"}, /* andi written as or */
+{"andb", one(0001074), one(0177777), "#bCb"}, /* andi to ccr */
+{"andb", one(0140000), one(0170700), ";bDd"}, /* memory to register */
+{"andb", one(0140400), one(0170700), "Dd~b"}, /* register to memory */
+{"andw", one(0001100), one(0177700), "#w$w"}, /* andi written as or */
+{"andw", one(0001174), one(0177777), "#wSw"}, /* andi to sr */
+{"andw", one(0140100), one(0170700), ";wDd"}, /* memory to register */
+{"andw", one(0140500), one(0170700), "Dd~w"}, /* register to memory */
+{"andl", one(0001200), one(0177700), "#l$l"}, /* andi written as or */
+{"andl", one(0140200), one(0170700), ";lDd"}, /* memory to register */
+{"andl", one(0140600), one(0170700), "Dd~l"}, /* register to memory */
+
+{"aslb", one(0160400), one(0170770), "QdDs"},
+{"aslb", one(0160440), one(0170770), "DdDs"},
+{"asll", one(0160600), one(0170770), "QdDs"},
+{"asll", one(0160640), one(0170770), "DdDs"},
+{"aslw", one(0160500), one(0170770), "QdDs"},
+{"aslw", one(0160540), one(0170770), "DdDs"},
+{"aslw", one(0160700), one(0177700), "~s"}, /* Shift memory */
+{"asrb", one(0160000), one(0170770), "QdDs"},
+{"asrb", one(0160040), one(0170770), "DdDs"},
+{"asrl", one(0160200), one(0170770), "QdDs"},
+{"asrl", one(0160240), one(0170770), "DdDs"},
+{"asrw", one(0160100), one(0170770), "QdDs"},
+{"asrw", one(0160140), one(0170770), "DdDs"},
+{"asrw", one(0160300), one(0177700), "~s"}, /* Shift memory */
+
+{"bhi", one(0061000), one(0177400), "Bg"},
+{"bls", one(0061400), one(0177400), "Bg"},
+{"bcc", one(0062000), one(0177400), "Bg"},
+{"bcs", one(0062400), one(0177400), "Bg"},
+{"bne", one(0063000), one(0177400), "Bg"},
+{"beq", one(0063400), one(0177400), "Bg"},
+{"bvc", one(0064000), one(0177400), "Bg"},
+{"bvs", one(0064400), one(0177400), "Bg"},
+{"bpl", one(0065000), one(0177400), "Bg"},
+{"bmi", one(0065400), one(0177400), "Bg"},
+{"bge", one(0066000), one(0177400), "Bg"},
+{"blt", one(0066400), one(0177400), "Bg"},
+{"bgt", one(0067000), one(0177400), "Bg"},
+{"ble", one(0067400), one(0177400), "Bg"},
+
+{"bchg", one(0000500), one(0170700), "Dd$s"},
+{"bchg", one(0004100), one(0177700), "#b$s"},
+{"bclr", one(0000600), one(0170700), "Dd$s"},
+{"bclr", one(0004200), one(0177700), "#b$s"},
+{"bfchg", two(0165300, 0), two(0177700, 0170000), "?sO2O3"},
+{"bfclr", two(0166300, 0), two(0177700, 0170000), "?sO2O3"},
+{"bfexts", two(0165700, 0), two(0177700, 0100000), "/sO2O3D1"},
+{"bfextu", two(0164700, 0), two(0177700, 0100000), "/sO2O3D1"},
+{"bfffo", two(0166700, 0), two(0177700, 0100000), "/sO2O3D1"},
+{"bfins", two(0167700, 0), two(0177700, 0100000), "D1?sO2O3"},
+{"bfset", two(0167300, 0), two(0177700, 0170000), "?sO2O3"},
+{"bftst", two(0164300, 0), two(0177700, 0170000), "/sO2O3"},
+{"bset", one(0000700), one(0170700), "Dd$s"},
+{"bset", one(0004300), one(0177700), "#b$s"},
+{"btst", one(0000400), one(0170700), "Dd@s"},
+{"btst", one(0004000), one(0177700), "#b@s"},
+
+{"bkpt", one(0044110), one(0177770), "Qs"},
+{"bra", one(0060000), one(0177400), "Bg"},
+{"bras", one(0060000), one(0177400), "Bw"},
+{"bsr", one(0060400), one(0177400), "Bg"},
+{"bsrs", one(0060400), one(0177400), "Bw"},
+
+{"callm", one(0003300), one(0177700), "#b!s"},
+{"cas2l", two(0007374, 0), two(0177777, 0107070), "D3D6D2D5R1R4"}, /* JF FOO this is really a 3 word ins */
+{"cas2w", two(0006374, 0), two(0177777, 0107070), "D3D6D2D5R1R4"}, /* JF ditto */
+{"casb", two(0005300, 0), two(0177700, 0177070), "D3D2~s"},
+{"casl", two(0007300, 0), two(0177700, 0177070), "D3D2~s"},
+{"casw", two(0006300, 0), two(0177700, 0177070), "D3D2~s"},
+
+/* {"chk", one(0040600), one(0170700), ";wDd"}, JF FOO this looks wrong */
+{"chk2b", two(0000300, 0004000), two(0177700, 07777), "!sR1"},
+{"chk2l", two(0002300, 0004000), two(0177700, 07777), "!sR1"},
+{"chk2w", two(0001300, 0004000), two(0177700, 07777), "!sR1"},
+{"chkl", one(0040400), one(0170700), ";lDd"},
+{"chkw", one(0040600), one(0170700), ";wDd"},
+{"clrb", one(0041000), one(0177700), "$s"},
+{"clrl", one(0041200), one(0177700), "$s"},
+{"clrw", one(0041100), one(0177700), "$s"},
+
+{"cmp2b", two(0000300, 0), two(0177700, 07777), "!sR1"},
+{"cmp2l", two(0002300, 0), two(0177700, 07777), "!sR1"},
+{"cmp2w", two(0001300, 0), two(0177700, 07777), "!sR1"},
+{"cmpal", one(0130700), one(0170700), "*lAd"},
+{"cmpaw", one(0130300), one(0170700), "*wAd"},
+{"cmpib", one(0006000), one(0177700), "#b;b"},
+{"cmpil", one(0006200), one(0177700), "#l;l"},
+{"cmpiw", one(0006100), one(0177700), "#w;w"},
+{"cmpb", one(0006000), one(0177700), "#b;b"}, /* cmpi written as cmp */
+{"cmpb", one(0130000), one(0170700), ";bDd"},
+{"cmpw", one(0006100), one(0177700), "#w;w"},
+{"cmpw", one(0130100), one(0170700), "*wDd"},
+{"cmpw", one(0130300), one(0170700), "*wAd"}, /* cmpa written as cmp */
+{"cmpl", one(0006200), one(0177700), "#l;l"},
+{"cmpl", one(0130200), one(0170700), "*lDd"},
+{"cmpl", one(0130700), one(0170700), "*lAd"},
+{"cmpmb", one(0130410), one(0170770), "+s+d"},
+{"cmpml", one(0130610), one(0170770), "+s+d"},
+{"cmpmw", one(0130510), one(0170770), "+s+d"},
+
+{"dbcc", one(0052310), one(0177770), "DsBw"},
+{"dbcs", one(0052710), one(0177770), "DsBw"},
+{"dbeq", one(0053710), one(0177770), "DsBw"},
+{"dbf", one(0050710), one(0177770), "DsBw"},
+{"dbge", one(0056310), one(0177770), "DsBw"},
+{"dbgt", one(0057310), one(0177770), "DsBw"},
+{"dbhi", one(0051310), one(0177770), "DsBw"},
+{"dble", one(0057710), one(0177770), "DsBw"},
+{"dbls", one(0051710), one(0177770), "DsBw"},
+{"dblt", one(0056710), one(0177770), "DsBw"},
+{"dbmi", one(0055710), one(0177770), "DsBw"},
+{"dbne", one(0053310), one(0177770), "DsBw"},
+{"dbpl", one(0055310), one(0177770), "DsBw"},
+{"dbra", one(0050710), one(0177770), "DsBw"},
+{"dbt", one(0050310), one(0177770), "DsBw"},
+{"dbvc", one(0054310), one(0177770), "DsBw"},
+{"dbvs", one(0054710), one(0177770), "DsBw"},
+
+{"divsl", two(0046100, 0006000), two(0177700, 0107770), ";lD3D1"},
+{"divsl", two(0046100, 0004000), two(0177700, 0107770), ";lDD"},
+{"divsll", two(0046100, 0004000), two(0177700, 0107770), ";lD3D1"},
+{"divsw", one(0100700), one(0170700), ";wDd"},
+{"divs", one(0100700), one(0170700), ";wDd"},
+{"divul", two(0046100, 0002000), two(0177700, 0107770), ";lD3D1"},
+{"divul", two(0046100, 0000000), two(0177700, 0107770), ";lDD"},
+{"divull", two(0046100, 0000000), two(0177700, 0107770), ";lD3D1"},
+{"divuw", one(0100300), one(0170700), ";wDd"},
+{"divu", one(0100300), one(0170700), ";wDd"},
+{"eorb", one(0005000), one(0177700), "#b$s"}, /* eori written as or */
+{"eorb", one(0005074), one(0177777), "#bCs"}, /* eori to ccr */
+{"eorb", one(0130400), one(0170700), "Dd$s"}, /* register to memory */
+{"eorib", one(0005000), one(0177700), "#b$s"},
+{"eorib", one(0005074), one(0177777), "#bCs"}, /* eori to ccr */
+{"eoril", one(0005200), one(0177700), "#l$s"},
+{"eoriw", one(0005100), one(0177700), "#w$s"},
+{"eoriw", one(0005174), one(0177777), "#wSs"}, /* eori to sr */
+{"eorl", one(0005200), one(0177700), "#l$s"},
+{"eorl", one(0130600), one(0170700), "Dd$s"},
+{"eorw", one(0005100), one(0177700), "#w$s"},
+{"eorw", one(0005174), one(0177777), "#wSs"}, /* eori to sr */
+{"eorw", one(0130500), one(0170700), "Dd$s"},
+
+{"exg", one(0140500), one(0170770), "DdDs"},
+{"exg", one(0140510), one(0170770), "AdAs"},
+{"exg", one(0140610), one(0170770), "DdAs"},
+{"exg", one(0140610), one(0170770), "AsDd"},
+
+{"extw", one(0044200), one(0177770), "Ds"},
+{"extl", one(0044300), one(0177770), "Ds"},
+{"extbl", one(0044700), one(0177770), "Ds"},
+{"extb.l", one(0044700), one(0177770), "Ds"}, /* Not sure we should support this one*/
+
+{"illegal", one(0045374), one(0177777), ""},
+{"jmp", one(0047300), one(0177700), "!s"},
+{"jsr", one(0047200), one(0177700), "!s"},
+{"lea", one(0040700), one(0170700), "!sAd"},
+{"linkw", one(0047120), one(0177770), "As#w"},
+{"linkl", one(0044010), one(0177770), "As#l"},
+{"link", one(0047120), one(0177770), "As#w"},
+{"link", one(0044010), one(0177770), "As#l"},
+
+{"lslb", one(0160410), one(0170770), "QdDs"}, /* lsrb #Q, Ds */
+{"lslb", one(0160450), one(0170770), "DdDs"}, /* lsrb Dd, Ds */
+{"lslw", one(0160510), one(0170770), "QdDs"}, /* lsrb #Q, Ds */
+{"lslw", one(0160550), one(0170770), "DdDs"}, /* lsrb Dd, Ds */
+{"lslw", one(0161700), one(0177700), "~s"}, /* Shift memory */
+{"lsll", one(0160610), one(0170770), "QdDs"}, /* lsrb #Q, Ds */
+{"lsll", one(0160650), one(0170770), "DdDs"}, /* lsrb Dd, Ds */
+
+{"lsrb", one(0160010), one(0170770), "QdDs"} /* lsrb #Q, Ds */,
+{"lsrb", one(0160050), one(0170770), "DdDs"}, /* lsrb Dd, Ds */
+{"lsrl", one(0160210), one(0170770), "QdDs"}, /* lsrb #Q, Ds */
+{"lsrl", one(0160250), one(0170770), "DdDs"}, /* lsrb #Q, Ds */
+{"lsrw", one(0160110), one(0170770), "QdDs"}, /* lsrb #Q, Ds */
+{"lsrw", one(0160150), one(0170770), "DdDs"}, /* lsrb #Q, Ds */
+{"lsrw", one(0161300), one(0177700), "~s"}, /* Shift memory */
+
+{"moveal", one(0020100), one(0170700), "*lAd"},
+{"moveaw", one(0030100), one(0170700), "*wAd"},
+{"moveb", one(0010000), one(0170000), ";b$d"}, /* move */
+{"movel", one(0070000), one(0170400), "MsDd"}, /* moveq written as move */
+{"movel", one(0020000), one(0170000), "*l$d"},
+{"movel", one(0020100), one(0170700), "*lAd"},
+{"movel", one(0047140), one(0177770), "AsUd"}, /* move to USP */
+{"movel", one(0047150), one(0177770), "UdAs"}, /* move from USP */
+
+{"movec", one(0047173), one(0177777), "R1Jj"},
+{"movec", one(0047173), one(0177777), "R1#j"},
+{"movec", one(0047172), one(0177777), "JjR1"},
+{"movec", one(0047172), one(0177777), "#jR1"},
+
+/* JF added these next four for the assembler */
+{"moveml", one(0044300), one(0177700), "Lw&s"}, /* movem reg to mem. */
+{"moveml", one(0044340), one(0177770), "lw-s"}, /* movem reg to autodecrement. */
+{"moveml", one(0046300), one(0177700), "!sLw"}, /* movem mem to reg. */
+{"moveml", one(0046330), one(0177770), "+sLw"}, /* movem autoinc to reg. */
+
+{"moveml", one(0044300), one(0177700), "#w&s"}, /* movem reg to mem. */
+{"moveml", one(0044340), one(0177770), "#w-s"}, /* movem reg to autodecrement. */
+{"moveml", one(0046300), one(0177700), "!s#w"}, /* movem mem to reg. */
+{"moveml", one(0046330), one(0177770), "+s#w"}, /* movem autoinc to reg. */
+
+/* JF added these next four for the assembler */
+{"movemw", one(0044200), one(0177700), "Lw&s"}, /* movem reg to mem. */
+{"movemw", one(0044240), one(0177770), "lw-s"}, /* movem reg to autodecrement. */
+{"movemw", one(0046200), one(0177700), "!sLw"}, /* movem mem to reg. */
+{"movemw", one(0046230), one(0177770), "+sLw"}, /* movem autoinc to reg. */
+
+{"movemw", one(0044200), one(0177700), "#w&s"}, /* movem reg to mem. */
+{"movemw", one(0044240), one(0177770), "#w-s"}, /* movem reg to autodecrement. */
+{"movemw", one(0046200), one(0177700), "!s#w"}, /* movem mem to reg. */
+{"movemw", one(0046230), one(0177770), "+s#w"}, /* movem autoinc to reg. */
+
+{"movepl", one(0000510), one(0170770), "dsDd"}, /* memory to register */
+{"movepl", one(0000710), one(0170770), "Ddds"}, /* register to memory */
+{"movepw", one(0000410), one(0170770), "dsDd"}, /* memory to register */
+{"movepw", one(0000610), one(0170770), "Ddds"}, /* register to memory */
+{"moveq", one(0070000), one(0170400), "MsDd"},
+{"movew", one(0030000), one(0170000), "*w$d"},
+{"movew", one(0030100), one(0170700), "*wAd"}, /* movea, written as move */
+{"movew", one(0040300), one(0177700), "Ss$s"}, /* Move from sr */
+{"movew", one(0041300), one(0177700), "Cs$s"}, /* Move from ccr */
+{"movew", one(0042300), one(0177700), ";wCd"}, /* move to ccr */
+{"movew", one(0043300), one(0177700), ";wSd"}, /* move to sr */
+
+{"movesb", two(0007000, 0), two(0177700, 07777), "~sR1"}, /* moves from memory */
+{"movesb", two(0007000, 04000), two(0177700, 07777), "R1~s"}, /* moves to memory */
+{"movesl", two(0007200, 0), two(0177700, 07777), "~sR1"}, /* moves from memory */
+{"movesl", two(0007200, 04000), two(0177700, 07777), "R1~s"}, /* moves to memory */
+{"movesw", two(0007100, 0), two(0177700, 07777), "~sR1"}, /* moves from memory */
+{"movesw", two(0007100, 04000), two(0177700, 07777), "R1~s"}, /* moves to memory */
+
+{"mulsl", two(0046000, 004000), two(0177700, 0107770), ";lD1"},
+{"mulsl", two(0046000, 006000), two(0177700, 0107770), ";lD3D1"},
+{"mulsw", one(0140700), one(0170700), ";wDd"},
+{"muls", one(0140700), one(0170700), ";wDd"},
+{"mulul", two(0046000, 000000), two(0177700, 0107770), ";lD1"},
+{"mulul", two(0046000, 002000), two(0177700, 0107770), ";lD3D1"},
+{"muluw", one(0140300), one(0170700), ";wDd"},
+{"mulu", one(0140300), one(0170700), ";wDd"},
+{"nbcd", one(0044000), one(0177700), "$s"},
+{"negb", one(0042000), one(0177700), "$s"},
+{"negl", one(0042200), one(0177700), "$s"},
+{"negw", one(0042100), one(0177700), "$s"},
+{"negxb", one(0040000), one(0177700), "$s"},
+{"negxl", one(0040200), one(0177700), "$s"},
+{"negxw", one(0040100), one(0177700), "$s"},
+{"nop", one(0047161), one(0177777), ""},
+{"notb", one(0043000), one(0177700), "$s"},
+{"notl", one(0043200), one(0177700), "$s"},
+{"notw", one(0043100), one(0177700), "$s"},
+
+{"orb", one(0000000), one(0177700), "#b$s"}, /* ori written as or */
+{"orb", one(0000074), one(0177777), "#bCs"}, /* ori to ccr */
+{"orb", one(0100000), one(0170700), ";bDd"}, /* memory to register */
+{"orb", one(0100400), one(0170700), "Dd~s"}, /* register to memory */
+{"orib", one(0000000), one(0177700), "#b$s"},
+{"orib", one(0000074), one(0177777), "#bCs"}, /* ori to ccr */
+{"oril", one(0000200), one(0177700), "#l$s"},
+{"oriw", one(0000100), one(0177700), "#w$s"},
+{"oriw", one(0000174), one(0177777), "#wSs"}, /* ori to sr */
+{"orl", one(0000200), one(0177700), "#l$s"},
+{"orl", one(0100200), one(0170700), ";lDd"}, /* memory to register */
+{"orl", one(0100600), one(0170700), "Dd~s"}, /* register to memory */
+{"orw", one(0000100), one(0177700), "#w$s"},
+{"orw", one(0000174), one(0177777), "#wSs"}, /* ori to sr */
+{"orw", one(0100100), one(0170700), ";wDd"}, /* memory to register */
+{"orw", one(0100500), one(0170700), "Dd~s"}, /* register to memory */
+
+{"pack", one(0100500), one(0170770), "DsDd#w"}, /* pack Ds, Dd, #w */
+{"pack", one(0100510), one(0170770), "-s-d#w"}, /* pack -(As), -(Ad), #w */
+{"pea", one(0044100), one(0177700), "!s"},
+{"reset", one(0047160), one(0177777), ""},
+
+{"rolb", one(0160430), one(0170770), "QdDs"}, /* rorb #Q, Ds */
+{"rolb", one(0160470), one(0170770), "DdDs"}, /* rorb Dd, Ds */
+{"roll", one(0160630), one(0170770), "QdDs"}, /* rorb #Q, Ds */
+{"roll", one(0160670), one(0170770), "DdDs"}, /* rorb Dd, Ds */
+{"rolw", one(0160530), one(0170770), "QdDs"}, /* rorb #Q, Ds */
+{"rolw", one(0160570), one(0170770), "DdDs"}, /* rorb Dd, Ds */
+{"rolw", one(0163700), one(0177700), "~s"}, /* Rotate memory */
+{"rorb", one(0160030), one(0170770), "QdDs"}, /* rorb #Q, Ds */
+{"rorb", one(0160070), one(0170770), "DdDs"}, /* rorb Dd, Ds */
+{"rorl", one(0160230), one(0170770), "QdDs"}, /* rorb #Q, Ds */
+{"rorl", one(0160270), one(0170770), "DdDs"}, /* rorb Dd, Ds */
+{"rorw", one(0160130), one(0170770), "QdDs"}, /* rorb #Q, Ds */
+{"rorw", one(0160170), one(0170770), "DdDs"}, /* rorb Dd, Ds */
+{"rorw", one(0163300), one(0177700), "~s"}, /* Rotate memory */
+
+{"roxlb", one(0160420), one(0170770), "QdDs"}, /* roxrb #Q, Ds */
+{"roxlb", one(0160460), one(0170770), "DdDs"}, /* roxrb Dd, Ds */
+{"roxll", one(0160620), one(0170770), "QdDs"}, /* roxrb #Q, Ds */
+{"roxll", one(0160660), one(0170770), "DdDs"}, /* roxrb Dd, Ds */
+{"roxlw", one(0160520), one(0170770), "QdDs"}, /* roxrb #Q, Ds */
+{"roxlw", one(0160560), one(0170770), "DdDs"}, /* roxrb Dd, Ds */
+{"roxlw", one(0162700), one(0177700), "~s"}, /* Rotate memory */
+{"roxrb", one(0160020), one(0170770), "QdDs"}, /* roxrb #Q, Ds */
+{"roxrb", one(0160060), one(0170770), "DdDs"}, /* roxrb Dd, Ds */
+{"roxrl", one(0160220), one(0170770), "QdDs"}, /* roxrb #Q, Ds */
+{"roxrl", one(0160260), one(0170770), "DdDs"}, /* roxrb Dd, Ds */
+{"roxrw", one(0160120), one(0170770), "QdDs"}, /* roxrb #Q, Ds */
+{"roxrw", one(0160160), one(0170770), "DdDs"}, /* roxrb Dd, Ds */
+{"roxrw", one(0162300), one(0177700), "~s"}, /* Rotate memory */
+
+{"rtd", one(0047164), one(0177777), "#w"},
+{"rte", one(0047163), one(0177777), ""},
+{"rtm", one(0003300), one(0177760), "Rs"},
+{"rtr", one(0047167), one(0177777), ""},
+{"rts", one(0047165), one(0177777), ""},
+
+{"scc", one(0052300), one(0177700), "$s"},
+{"scs", one(0052700), one(0177700), "$s"},
+{"seq", one(0053700), one(0177700), "$s"},
+{"sf", one(0050700), one(0177700), "$s"},
+{"sge", one(0056300), one(0177700), "$s"},
+{"sgt", one(0057300), one(0177700), "$s"},
+{"shi", one(0051300), one(0177700), "$s"},
+{"sle", one(0057700), one(0177700), "$s"},
+{"sls", one(0051700), one(0177700), "$s"},
+{"slt", one(0056700), one(0177700), "$s"},
+{"smi", one(0055700), one(0177700), "$s"},
+{"sne", one(0053300), one(0177700), "$s"},
+{"spl", one(0055300), one(0177700), "$s"},
+{"st", one(0050300), one(0177700), "$s"},
+{"svc", one(0054300), one(0177700), "$s"},
+{"svs", one(0054700), one(0177700), "$s"},
+
+{"sbcd", one(0100400), one(0170770), "DsDd"},
+{"sbcd", one(0100410), one(0170770), "-s-d"},
+{"stop", one(0047162), one(0177777), "#w"},
+
+{"subal", one(0110700), one(0170700), "*lAd"},
+{"subaw", one(0110300), one(0170700), "*wAd"},
+{"subb", one(0050400), one(0170700), "Qd%s"}, /* subq written as sub */
+{"subb", one(0002000), one(0177700), "#b$s"}, /* subi written as sub */
+{"subb", one(0110000), one(0170700), ";bDd"}, /* subb ? ?, Dd */
+{"subb", one(0110400), one(0170700), "Dd~s"}, /* subb Dd, ? ? */
+{"subib", one(0002000), one(0177700), "#b$s"},
+{"subil", one(0002200), one(0177700), "#l$s"},
+{"subiw", one(0002100), one(0177700), "#w$s"},
+{"subl", one(0050600), one(0170700), "Qd%s"},
+{"subl", one(0002200), one(0177700), "#l$s"},
+{"subl", one(0110700), one(0170700), "*lAd"},
+{"subl", one(0110200), one(0170700), "*lDd"},
+{"subl", one(0110600), one(0170700), "Dd~s"},
+{"subqb", one(0050400), one(0170700), "Qd%s"},
+{"subql", one(0050600), one(0170700), "Qd%s"},
+{"subqw", one(0050500), one(0170700), "Qd%s"},
+{"subw", one(0050500), one(0170700), "Qd%s"},
+{"subw", one(0002100), one(0177700), "#w$s"},
+{"subw", one(0110100), one(0170700), "*wDd"},
+{"subw", one(0110300), one(0170700), "*wAd"}, /* suba written as sub */
+{"subw", one(0110500), one(0170700), "Dd~s"},
+{"subxb", one(0110400), one(0170770), "DsDd"}, /* subxb Ds, Dd */
+{"subxb", one(0110410), one(0170770), "-s-d"}, /* subxb -(As), -(Ad) */
+{"subxl", one(0110600), one(0170770), "DsDd"},
+{"subxl", one(0110610), one(0170770), "-s-d"},
+{"subxw", one(0110500), one(0170770), "DsDd"},
+{"subxw", one(0110510), one(0170770), "-s-d"},
+
+{"swap", one(0044100), one(0177770), "Ds"},
+
+{"tas", one(0045300), one(0177700), "$s"},
+{"trap", one(0047100), one(0177760), "Ts"},
+
+{"trapcc", one(0052374), one(0177777), ""},
+{"trapcs", one(0052774), one(0177777), ""},
+{"trapeq", one(0053774), one(0177777), ""},
+{"trapf", one(0050774), one(0177777), ""},
+{"trapge", one(0056374), one(0177777), ""},
+{"trapgt", one(0057374), one(0177777), ""},
+{"traphi", one(0051374), one(0177777), ""},
+{"traple", one(0057774), one(0177777), ""},
+{"trapls", one(0051774), one(0177777), ""},
+{"traplt", one(0056774), one(0177777), ""},
+{"trapmi", one(0055774), one(0177777), ""},
+{"trapne", one(0053374), one(0177777), ""},
+{"trappl", one(0055374), one(0177777), ""},
+{"trapt", one(0050374), one(0177777), ""},
+{"trapvc", one(0054374), one(0177777), ""},
+{"trapvs", one(0054774), one(0177777), ""},
+
+{"trapcc.w", one(0052372), one(0177777), ""},
+{"trapcs.w", one(0052772), one(0177777), ""},
+{"trapeq.w", one(0053772), one(0177777), ""},
+{"trapf.w", one(0050772), one(0177777), ""},
+{"trapge.w", one(0056372), one(0177777), ""},
+{"trapgt.w", one(0057372), one(0177777), ""},
+{"traphi.w", one(0051372), one(0177777), ""},
+{"traple.w", one(0057772), one(0177777), ""},
+{"trapls.w", one(0051772), one(0177777), ""},
+{"traplt.w", one(0056772), one(0177777), ""},
+{"trapmi.w", one(0055772), one(0177777), ""},
+{"trapne.w", one(0053372), one(0177777), ""},
+{"trappl.w", one(0055372), one(0177777), ""},
+{"trapt.w", one(0050372), one(0177777), ""},
+{"trapvc.w", one(0054372), one(0177777), ""},
+{"trapvs.w", one(0054772), one(0177777), ""},
+
+{"trapcc.l", one(0052373), one(0177777), ""},
+{"trapcs.l", one(0052773), one(0177777), ""},
+{"trapeq.l", one(0053773), one(0177777), ""},
+{"trapf.l", one(0050773), one(0177777), ""},
+{"trapge.l", one(0056373), one(0177777), ""},
+{"trapgt.l", one(0057373), one(0177777), ""},
+{"traphi.l", one(0051373), one(0177777), ""},
+{"traple.l", one(0057773), one(0177777), ""},
+{"trapls.l", one(0051773), one(0177777), ""},
+{"traplt.l", one(0056773), one(0177777), ""},
+{"trapmi.l", one(0055773), one(0177777), ""},
+{"trapne.l", one(0053373), one(0177777), ""},
+{"trappl.l", one(0055373), one(0177777), ""},
+{"trapt.l", one(0050373), one(0177777), ""},
+{"trapvc.l", one(0054373), one(0177777), ""},
+{"trapvs.l", one(0054773), one(0177777), ""},
+
+{"trapv", one(0047166), one(0177777), ""},
+
+{"tstb", one(0045000), one(0177700), ";b"},
+{"tstw", one(0045100), one(0177700), "*w"},
+{"tstl", one(0045200), one(0177700), "*l"},
+
+{"unlk", one(0047130), one(0177770), "As"},
+{"unpk", one(0100600), one(0170770), "DsDd#w"},
+{"unpk", one(0100610), one(0170770), "-s-d#w"},
+ /* JF floating pt stuff moved down here */
+
+{"fabsb", two(0xF000, 0x5818), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fabsd", two(0xF000, 0x5418), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fabsl", two(0xF000, 0x4018), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fabsp", two(0xF000, 0x4C18), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fabss", two(0xF000, 0x4418), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fabsw", two(0xF000, 0x5018), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fabsx", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fabsx", two(0xF000, 0x4818), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fabsx", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"facosb", two(0xF000, 0x581C), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"facosd", two(0xF000, 0x541C), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"facosl", two(0xF000, 0x401C), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"facosp", two(0xF000, 0x4C1C), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"facoss", two(0xF000, 0x441C), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"facosw", two(0xF000, 0x501C), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"facosx", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"facosx", two(0xF000, 0x481C), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"facosx", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"faddb", two(0xF000, 0x5822), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"faddd", two(0xF000, 0x5422), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"faddl", two(0xF000, 0x4022), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"faddp", two(0xF000, 0x4C22), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fadds", two(0xF000, 0x4422), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"faddw", two(0xF000, 0x5022), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"faddx", two(0xF000, 0x4822), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+/* {"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiFt"}, JF removed */
+
+{"fasinb", two(0xF000, 0x580C), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fasind", two(0xF000, 0x540C), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fasinl", two(0xF000, 0x400C), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fasinp", two(0xF000, 0x4C0C), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fasins", two(0xF000, 0x440C), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fasinw", two(0xF000, 0x500C), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fasinx", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fasinx", two(0xF000, 0x480C), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fasinx", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fatanb", two(0xF000, 0x580A), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fatand", two(0xF000, 0x540A), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fatanl", two(0xF000, 0x400A), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fatanp", two(0xF000, 0x4C0A), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fatans", two(0xF000, 0x440A), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fatanw", two(0xF000, 0x500A), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fatanx", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fatanx", two(0xF000, 0x480A), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fatanx", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fatanhb", two(0xF000, 0x580D), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fatanhd", two(0xF000, 0x540D), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fatanhl", two(0xF000, 0x400D), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fatanhp", two(0xF000, 0x4C0D), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fatanhs", two(0xF000, 0x440D), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fatanhw", two(0xF000, 0x500D), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fatanhx", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fatanhx", two(0xF000, 0x480D), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fatanhx", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fbeq", one(0xF081), one(0xF1BF), "IdBc"},
+{"fbf", one(0xF080), one(0xF1BF), "IdBc"},
+{"fbge", one(0xF093), one(0xF1BF), "IdBc"},
+{"fbgl", one(0xF096), one(0xF1BF), "IdBc"},
+{"fbgle", one(0xF097), one(0xF1BF), "IdBc"},
+{"fbgt", one(0xF092), one(0xF1BF), "IdBc"},
+{"fble", one(0xF095), one(0xF1BF), "IdBc"},
+{"fblt", one(0xF094), one(0xF1BF), "IdBc"},
+{"fbne", one(0xF08E), one(0xF1BF), "IdBc"},
+{"fbnge", one(0xF09C), one(0xF1BF), "IdBc"},
+{"fbngl", one(0xF099), one(0xF1BF), "IdBc"},
+{"fbngle", one(0xF098), one(0xF1BF), "IdBc"},
+{"fbngt", one(0xF09D), one(0xF1BF), "IdBc"},
+{"fbnle", one(0xF09A), one(0xF1BF), "IdBc"},
+{"fbnlt", one(0xF09B), one(0xF1BF), "IdBc"},
+{"fboge", one(0xF083), one(0xF1BF), "IdBc"},
+{"fbogl", one(0xF086), one(0xF1BF), "IdBc"},
+{"fbogt", one(0xF082), one(0xF1BF), "IdBc"},
+{"fbole", one(0xF085), one(0xF1BF), "IdBc"},
+{"fbolt", one(0xF084), one(0xF1BF), "IdBc"},
+{"fbor", one(0xF087), one(0xF1BF), "IdBc"},
+{"fbseq", one(0xF091), one(0xF1BF), "IdBc"},
+{"fbsf", one(0xF090), one(0xF1BF), "IdBc"},
+{"fbsne", one(0xF09E), one(0xF1BF), "IdBc"},
+{"fbst", one(0xF09F), one(0xF1BF), "IdBc"},
+{"fbt", one(0xF08F), one(0xF1BF), "IdBc"},
+{"fbueq", one(0xF089), one(0xF1BF), "IdBc"},
+{"fbuge", one(0xF08B), one(0xF1BF), "IdBc"},
+{"fbugt", one(0xF08A), one(0xF1BF), "IdBc"},
+{"fbule", one(0xF08D), one(0xF1BF), "IdBc"},
+{"fbult", one(0xF08C), one(0xF1BF), "IdBc"},
+{"fbun", one(0xF088), one(0xF1BF), "IdBc"},
+
+{"fcmpb", two(0xF000, 0x5838), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fcmpd", two(0xF000, 0x5438), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fcmpl", two(0xF000, 0x4038), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fcmpp", two(0xF000, 0x4C38), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fcmps", two(0xF000, 0x4438), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fcmpw", two(0xF000, 0x5038), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fcmpx", two(0xF000, 0x4838), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+/* {"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiFt"}, JF removed */
+
+{"fcosb", two(0xF000, 0x581D), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fcosd", two(0xF000, 0x541D), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fcosl", two(0xF000, 0x401D), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fcosp", two(0xF000, 0x4C1D), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fcoss", two(0xF000, 0x441D), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fcosw", two(0xF000, 0x501D), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fcosx", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fcosx", two(0xF000, 0x481D), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fcosx", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fcoshb", two(0xF000, 0x5819), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fcoshd", two(0xF000, 0x5419), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fcoshl", two(0xF000, 0x4019), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fcoshp", two(0xF000, 0x4C19), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fcoshs", two(0xF000, 0x4419), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fcoshw", two(0xF000, 0x5019), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fcoshx", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fcoshx", two(0xF000, 0x4819), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fcoshx", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fdbeq", two(0xF048, 0x0001), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbf", two(0xF048, 0x0000), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbge", two(0xF048, 0x0013), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbgl", two(0xF048, 0x0016), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbgle", two(0xF048, 0x0017), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbgt", two(0xF048, 0x0012), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdble", two(0xF048, 0x0015), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdblt", two(0xF048, 0x0014), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbne", two(0xF048, 0x000E), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbnge", two(0xF048, 0x001C), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbngl", two(0xF048, 0x0019), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbngle", two(0xF048, 0x0018), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbngt", two(0xF048, 0x001D), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbnle", two(0xF048, 0x001A), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbnlt", two(0xF048, 0x001B), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdboge", two(0xF048, 0x0003), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbogl", two(0xF048, 0x0006), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbogt", two(0xF048, 0x0002), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbole", two(0xF048, 0x0005), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbolt", two(0xF048, 0x0004), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbor", two(0xF048, 0x0007), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbseq", two(0xF048, 0x0011), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbsf", two(0xF048, 0x0010), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbsne", two(0xF048, 0x001E), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbst", two(0xF048, 0x001F), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbt", two(0xF048, 0x000F), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbueq", two(0xF048, 0x0009), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbuge", two(0xF048, 0x000B), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbugt", two(0xF048, 0x000A), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbule", two(0xF048, 0x000D), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbult", two(0xF048, 0x000C), two(0xF1F8, 0xFFFF), "IiDsBw"},
+{"fdbun", two(0xF048, 0x0008), two(0xF1F8, 0xFFFF), "IiDsBw"},
+
+{"fdivb", two(0xF000, 0x5820), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fdivd", two(0xF000, 0x5420), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fdivl", two(0xF000, 0x4020), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fdivp", two(0xF000, 0x4C20), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fdivs", two(0xF000, 0x4420), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fdivw", two(0xF000, 0x5020), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fdivx", two(0xF000, 0x4820), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+/* {"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiFt"}, JF */
+
+{"fetoxb", two(0xF000, 0x5810), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fetoxd", two(0xF000, 0x5410), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fetoxl", two(0xF000, 0x4010), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fetoxp", two(0xF000, 0x4C10), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fetoxs", two(0xF000, 0x4410), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fetoxw", two(0xF000, 0x5010), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fetoxx", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fetoxx", two(0xF000, 0x4810), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fetoxx", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fetoxm1b", two(0xF000, 0x5808), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fetoxm1d", two(0xF000, 0x5408), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fetoxm1l", two(0xF000, 0x4008), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fetoxm1p", two(0xF000, 0x4C08), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fetoxm1s", two(0xF000, 0x4408), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fetoxm1w", two(0xF000, 0x5008), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fetoxm1x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fetoxm1x", two(0xF000, 0x4808), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fetoxm1x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fgetexpb", two(0xF000, 0x581E), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fgetexpd", two(0xF000, 0x541E), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fgetexpl", two(0xF000, 0x401E), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fgetexpp", two(0xF000, 0x4C1E), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fgetexps", two(0xF000, 0x441E), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fgetexpw", two(0xF000, 0x501E), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fgetexpx", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fgetexpx", two(0xF000, 0x481E), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fgetexpx", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fgetmanb", two(0xF000, 0x581F), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fgetmand", two(0xF000, 0x541F), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fgetmanl", two(0xF000, 0x401F), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fgetmanp", two(0xF000, 0x4C1F), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fgetmans", two(0xF000, 0x441F), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fgetmanw", two(0xF000, 0x501F), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fgetmanx", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fgetmanx", two(0xF000, 0x481F), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fgetmanx", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fintb", two(0xF000, 0x5801), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fintd", two(0xF000, 0x5401), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fintl", two(0xF000, 0x4001), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fintp", two(0xF000, 0x4C01), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fints", two(0xF000, 0x4401), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fintw", two(0xF000, 0x5001), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fintx", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fintx", two(0xF000, 0x4801), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fintx", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fintrzb", two(0xF000, 0x5803), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fintrzd", two(0xF000, 0x5403), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fintrzl", two(0xF000, 0x4003), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fintrzp", two(0xF000, 0x4C03), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fintrzs", two(0xF000, 0x4403), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fintrzw", two(0xF000, 0x5003), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fintrzx", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fintrzx", two(0xF000, 0x4803), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fintrzx", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"flog10b", two(0xF000, 0x5815), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"flog10d", two(0xF000, 0x5415), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"flog10l", two(0xF000, 0x4015), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"flog10p", two(0xF000, 0x4C15), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"flog10s", two(0xF000, 0x4415), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"flog10w", two(0xF000, 0x5015), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"flog10x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"flog10x", two(0xF000, 0x4815), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"flog10x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"flog2b", two(0xF000, 0x5816), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"flog2d", two(0xF000, 0x5416), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"flog2l", two(0xF000, 0x4016), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"flog2p", two(0xF000, 0x4C16), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"flog2s", two(0xF000, 0x4416), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"flog2w", two(0xF000, 0x5016), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"flog2x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"flog2x", two(0xF000, 0x4816), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"flog2x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"flognb", two(0xF000, 0x5814), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"flognd", two(0xF000, 0x5414), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"flognl", two(0xF000, 0x4014), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"flognp", two(0xF000, 0x4C14), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"flogns", two(0xF000, 0x4414), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"flognw", two(0xF000, 0x5014), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"flognx", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"flognx", two(0xF000, 0x4814), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"flognx", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"flognp1b", two(0xF000, 0x5806), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"flognp1d", two(0xF000, 0x5406), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"flognp1l", two(0xF000, 0x4006), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"flognp1p", two(0xF000, 0x4C06), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"flognp1s", two(0xF000, 0x4406), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"flognp1w", two(0xF000, 0x5006), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"flognp1x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"flognp1x", two(0xF000, 0x4806), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"flognp1x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fmodb", two(0xF000, 0x5821), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fmodd", two(0xF000, 0x5421), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fmodl", two(0xF000, 0x4021), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fmodp", two(0xF000, 0x4C21), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fmods", two(0xF000, 0x4421), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fmodw", two(0xF000, 0x5021), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fmodx", two(0xF000, 0x4821), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+/* {"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiFt"}, JF */
+
+{"fmoveb", two(0xF000, 0x5800), two(0xF1C0, 0xFC7F), "Ii;bF7"}, /* fmove from <ea> to fp<n> */
+{"fmoveb", two(0xF000, 0x7800), two(0xF1C0, 0xFC7F), "IiF7@b"}, /* fmove from fp<n> to <ea> */
+{"fmoved", two(0xF000, 0x5400), two(0xF1C0, 0xFC7F), "Ii;FF7"}, /* fmove from <ea> to fp<n> */
+{"fmoved", two(0xF000, 0x7400), two(0xF1C0, 0xFC7F), "IiF7@F"}, /* fmove from fp<n> to <ea> */
+{"fmovel", two(0xF000, 0x4000), two(0xF1C0, 0xFC7F), "Ii;lF7"}, /* fmove from <ea> to fp<n> */
+{"fmovel", two(0xF000, 0x6000), two(0xF1C0, 0xFC7F), "IiF7@l"}, /* fmove from fp<n> to <ea> */
+/* Warning: The addressing modes on these are probably not right:
+ esp, Areg direct is only allowed for FPI */
+ /* fmove.l from/to system control registers: */
+{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"},
+{"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ls8"},
+
+/* {"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"},
+{"fmovel", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*ss8"}, */
+
+{"fmovep", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7"}, /* fmove from <ea> to fp<n> */
+{"fmovep", two(0xF000, 0x6C00), two(0xF1C0, 0xFC00), "IiF7@pkC"}, /* fmove.p with k-factors: */
+{"fmovep", two(0xF000, 0x7C00), two(0xF1C0, 0xFC0F), "IiF7@pDk"}, /* fmove.p with k-factors: */
+
+{"fmoves", two(0xF000, 0x4400), two(0xF1C0, 0xFC7F), "Ii;fF7"}, /* fmove from <ea> to fp<n> */
+{"fmoves", two(0xF000, 0x6400), two(0xF1C0, 0xFC7F), "IiF7@f"}, /* fmove from fp<n> to <ea> */
+{"fmovew", two(0xF000, 0x5000), two(0xF1C0, 0xFC7F), "Ii;wF7"}, /* fmove from <ea> to fp<n> */
+{"fmovew", two(0xF000, 0x7000), two(0xF1C0, 0xFC7F), "IiF7@w"}, /* fmove from fp<n> to <ea> */
+{"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiF8F7"}, /* fmove from <ea> to fp<n> */
+{"fmovex", two(0xF000, 0x4800), two(0xF1C0, 0xFC7F), "Ii;xF7"}, /* fmove from <ea> to fp<n> */
+{"fmovex", two(0xF000, 0x6800), two(0xF1C0, 0xFC7F), "IiF7@x"}, /* fmove from fp<n> to <ea> */
+/* JF removed {"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiFt"}, / * fmove from <ea> to fp<n> */
+
+{"fmovecrx", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"}, /* fmovecr.x #ccc, FPn */
+{"fmovecr", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"},
+
+/* Other fmovemx. */
+{"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s"}, /* fmovem.x to autodecrement, static and dynamic */
+{"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s"}, /* fmovem.x to autodecrement, static and dynamic */
+
+{"fmovemx", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s"}, /* fmovem.x to autodecrement, static and dynamic */
+
+{"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s"}, /* fmovem.x to control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s"}, /* fmovem.x to control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3"}, /* fmovem.x from control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk"}, /* fmovem.x from control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s"}, /* fmovem.x to control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3"}, /* fmovem.x from control, static and dynamic: */
+
+{"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3"}, /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3"}, /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovemx", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk"}, /* fmovem.x from autoincrement, static and dynamic: */
+
+{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s"},
+{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Ii#8@s"},
+{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"},
+
+{"fmoveml", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8"},
+{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*s#8"},
+{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8"},
+
+/* fmovemx with register lists */
+{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s"}, /* fmovem.x to autodecrement, static and dynamic */
+{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s"}, /* fmovem.x to control, static and dynamic: */
+{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3"}, /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3"}, /* fmovem.x from control, static and dynamic: */
+
+ /* Alternate mnemonics for GNU as and GNU CC */
+{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s"}, /* fmovem.x to autodecrement, static and dynamic */
+{"fmovem", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s"}, /* fmovem.x to autodecrement, static and dynamic */
+
+{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s"}, /* fmovem.x to control, static and dynamic: */
+{"fmovem", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s"}, /* fmovem.x to control, static and dynamic: */
+
+{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3"}, /* fmovem.x from autoincrement, static and dynamic: */
+{"fmovem", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk"}, /* fmovem.x from autoincrement, static and dynamic: */
+
+{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3"}, /* fmovem.x from control, static and dynamic: */
+{"fmovem", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk"}, /* fmovem.x from control, static and dynamic: */
+
+/* fmoveml a FP-control register */
+{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"},
+{"fmovem", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8"},
+
+/* fmoveml a FP-control reglist */
+{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s"},
+{"fmovem", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8"},
+
+{"fmulb", two(0xF000, 0x5823), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fmuld", two(0xF000, 0x5423), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fmull", two(0xF000, 0x4023), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fmulp", two(0xF000, 0x4C23), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fmuls", two(0xF000, 0x4423), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fmulw", two(0xF000, 0x5023), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fmulx", two(0xF000, 0x4823), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+/* {"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiFt"}, JF */
+
+{"fnegb", two(0xF000, 0x581A), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fnegd", two(0xF000, 0x541A), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fnegl", two(0xF000, 0x401A), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fnegp", two(0xF000, 0x4C1A), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fnegs", two(0xF000, 0x441A), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fnegw", two(0xF000, 0x501A), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fnegx", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fnegx", two(0xF000, 0x481A), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fnegx", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fnop", two(0xF280, 0x0000), two(0xFFFF, 0xFFFF), "Ii"},
+
+{"fremb", two(0xF000, 0x5825), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fremd", two(0xF000, 0x5425), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"freml", two(0xF000, 0x4025), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fremp", two(0xF000, 0x4C25), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"frems", two(0xF000, 0x4425), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fremw", two(0xF000, 0x5025), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fremx", two(0xF000, 0x4825), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+/* {"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiFt"}, JF */
+
+{"frestore", one(0xF140), one(0xF1C0), "Id&s"},
+{"frestore", one(0xF158), one(0xF1F8), "Id+s"},
+{"fsave", one(0xF100), one(0xF1C0), "Id&s"},
+{"fsave", one(0xF120), one(0xF1F8), "Id-s"},
+
+{"fsincosb", two(0xF000, 0x5830), two(0xF1C0, 0xFC78), "Ii;bF7FC"},
+{"fsincosd", two(0xF000, 0x5430), two(0xF1C0, 0xFC78), "Ii;FF7FC"},
+{"fsincosl", two(0xF000, 0x4030), two(0xF1C0, 0xFC78), "Ii;lF7FC"},
+{"fsincosp", two(0xF000, 0x4C30), two(0xF1C0, 0xFC78), "Ii;pF7FC"},
+{"fsincoss", two(0xF000, 0x4430), two(0xF1C0, 0xFC78), "Ii;fF7FC"},
+{"fsincosw", two(0xF000, 0x5030), two(0xF1C0, 0xFC78), "Ii;wF7FC"},
+{"fsincosx", two(0xF000, 0x0030), two(0xF1C0, 0xE078), "IiF8F7FC"},
+{"fsincosx", two(0xF000, 0x4830), two(0xF1C0, 0xFC78), "Ii;xF7FC"},
+
+{"fscaleb", two(0xF000, 0x5826), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fscaled", two(0xF000, 0x5426), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fscalel", two(0xF000, 0x4026), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fscalep", two(0xF000, 0x4C26), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fscales", two(0xF000, 0x4426), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fscalew", two(0xF000, 0x5026), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fscalex", two(0xF000, 0x4826), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+/* {"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiFt"}, JF */
+
+/* $ is necessary to prevent the assembler from using PC-relative.
+ If @ were used, "label: fseq label" could produce "ftrapeq",
+ because "label" became "pc@label". */
+{"fseq", two(0xF040, 0x0001), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsf", two(0xF040, 0x0000), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsge", two(0xF040, 0x0013), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsgl", two(0xF040, 0x0016), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsgle", two(0xF040, 0x0017), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsgt", two(0xF040, 0x0012), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsle", two(0xF040, 0x0015), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fslt", two(0xF040, 0x0014), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsne", two(0xF040, 0x000E), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsnge", two(0xF040, 0x001C), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsngl", two(0xF040, 0x0019), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsngle", two(0xF040, 0x0018), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsngt", two(0xF040, 0x001D), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsnle", two(0xF040, 0x001A), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsnlt", two(0xF040, 0x001B), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsoge", two(0xF040, 0x0003), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsogl", two(0xF040, 0x0006), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsogt", two(0xF040, 0x0002), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsole", two(0xF040, 0x0005), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsolt", two(0xF040, 0x0004), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsor", two(0xF040, 0x0007), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsseq", two(0xF040, 0x0011), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fssf", two(0xF040, 0x0010), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fssne", two(0xF040, 0x001E), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsst", two(0xF040, 0x001F), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fst", two(0xF040, 0x000F), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsueq", two(0xF040, 0x0009), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsuge", two(0xF040, 0x000B), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsugt", two(0xF040, 0x000A), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsule", two(0xF040, 0x000D), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsult", two(0xF040, 0x000C), two(0xF1C0, 0xFFFF), "Ii$s"},
+{"fsun", two(0xF040, 0x0008), two(0xF1C0, 0xFFFF), "Ii$s"},
+
+{"fsgldivb", two(0xF000, 0x5824), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fsgldivd", two(0xF000, 0x5424), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fsgldivl", two(0xF000, 0x4024), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fsgldivp", two(0xF000, 0x4C24), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fsgldivs", two(0xF000, 0x4424), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fsgldivw", two(0xF000, 0x5024), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fsgldivx", two(0xF000, 0x4824), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fsglmulb", two(0xF000, 0x5827), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fsglmuld", two(0xF000, 0x5427), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fsglmull", two(0xF000, 0x4027), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fsglmulp", two(0xF000, 0x4C27), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fsglmuls", two(0xF000, 0x4427), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fsglmulw", two(0xF000, 0x5027), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fsglmulx", two(0xF000, 0x4827), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fsinb", two(0xF000, 0x580E), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fsind", two(0xF000, 0x540E), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fsinl", two(0xF000, 0x400E), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fsinp", two(0xF000, 0x4C0E), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fsins", two(0xF000, 0x440E), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fsinw", two(0xF000, 0x500E), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fsinx", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fsinx", two(0xF000, 0x480E), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fsinx", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fsinhb", two(0xF000, 0x5802), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fsinhd", two(0xF000, 0x5402), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fsinhl", two(0xF000, 0x4002), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fsinhp", two(0xF000, 0x4C02), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fsinhs", two(0xF000, 0x4402), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fsinhw", two(0xF000, 0x5002), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fsinhx", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fsinhx", two(0xF000, 0x4802), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fsinhx", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fsqrtb", two(0xF000, 0x5804), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fsqrtd", two(0xF000, 0x5404), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fsqrtl", two(0xF000, 0x4004), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fsqrtp", two(0xF000, 0x4C04), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fsqrts", two(0xF000, 0x4404), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fsqrtw", two(0xF000, 0x5004), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fsqrtx", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fsqrtx", two(0xF000, 0x4804), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fsqrtx", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"fsubb", two(0xF000, 0x5828), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"fsubd", two(0xF000, 0x5428), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"fsubl", two(0xF000, 0x4028), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"fsubp", two(0xF000, 0x4C28), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"fsubs", two(0xF000, 0x4428), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"fsubw", two(0xF000, 0x5028), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"fsubx", two(0xF000, 0x4828), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"ftanb", two(0xF000, 0x580F), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"ftand", two(0xF000, 0x540F), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"ftanl", two(0xF000, 0x400F), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"ftanp", two(0xF000, 0x4C0F), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"ftans", two(0xF000, 0x440F), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"ftanw", two(0xF000, 0x500F), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"ftanx", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"ftanx", two(0xF000, 0x480F), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"ftanx", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"ftanhb", two(0xF000, 0x5809), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"ftanhd", two(0xF000, 0x5409), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"ftanhl", two(0xF000, 0x4009), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"ftanhp", two(0xF000, 0x4C09), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"ftanhs", two(0xF000, 0x4409), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"ftanhw", two(0xF000, 0x5009), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"ftanhx", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"ftanhx", two(0xF000, 0x4809), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"ftanhx", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"ftentoxb", two(0xF000, 0x5812), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"ftentoxd", two(0xF000, 0x5412), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"ftentoxl", two(0xF000, 0x4012), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"ftentoxp", two(0xF000, 0x4C12), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"ftentoxs", two(0xF000, 0x4412), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"ftentoxw", two(0xF000, 0x5012), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"ftentoxx", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"ftentoxx", two(0xF000, 0x4812), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"ftentoxx", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiFt"},
+
+{"ftrapeq", two(0xF07C, 0x0001), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapf", two(0xF07C, 0x0000), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapge", two(0xF07C, 0x0013), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapgl", two(0xF07C, 0x0016), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapgle", two(0xF07C, 0x0017), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapgt", two(0xF07C, 0x0012), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftraple", two(0xF07C, 0x0015), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftraplt", two(0xF07C, 0x0014), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapne", two(0xF07C, 0x000E), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapnge", two(0xF07C, 0x001C), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapngl", two(0xF07C, 0x0019), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapngle", two(0xF07C, 0x0018), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapngt", two(0xF07C, 0x001D), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapnle", two(0xF07C, 0x001A), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapnlt", two(0xF07C, 0x001B), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapoge", two(0xF07C, 0x0003), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapogl", two(0xF07C, 0x0006), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapogt", two(0xF07C, 0x0002), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapole", two(0xF07C, 0x0005), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapolt", two(0xF07C, 0x0004), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapor", two(0xF07C, 0x0007), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapseq", two(0xF07C, 0x0011), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapsf", two(0xF07C, 0x0010), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapsne", two(0xF07C, 0x001E), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapst", two(0xF07C, 0x001F), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapt", two(0xF07C, 0x000F), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapueq", two(0xF07C, 0x0009), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapuge", two(0xF07C, 0x000B), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapugt", two(0xF07C, 0x000A), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapule", two(0xF07C, 0x000D), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapult", two(0xF07C, 0x000C), two(0xF1FF, 0xFFFF), "Ii"},
+{"ftrapun", two(0xF07C, 0x0008), two(0xF1FF, 0xFFFF), "Ii"},
+
+{"ftrapeqw", two(0xF07A, 0x0001), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapfw", two(0xF07A, 0x0000), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapgew", two(0xF07A, 0x0013), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapglw", two(0xF07A, 0x0016), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapglew", two(0xF07A, 0x0017), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapgtw", two(0xF07A, 0x0012), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftraplew", two(0xF07A, 0x0015), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapltw", two(0xF07A, 0x0014), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapnew", two(0xF07A, 0x000E), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapngew", two(0xF07A, 0x001C), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapnglw", two(0xF07A, 0x0019), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapnglew", two(0xF07A, 0x0018), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapngtw", two(0xF07A, 0x001D), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapnlew", two(0xF07A, 0x001A), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapnltw", two(0xF07A, 0x001B), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapogew", two(0xF07A, 0x0003), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapoglw", two(0xF07A, 0x0006), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapogtw", two(0xF07A, 0x0002), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapolew", two(0xF07A, 0x0005), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapoltw", two(0xF07A, 0x0004), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftraporw", two(0xF07A, 0x0007), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapseqw", two(0xF07A, 0x0011), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapsfw", two(0xF07A, 0x0010), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapsnew", two(0xF07A, 0x001E), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapstw", two(0xF07A, 0x001F), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftraptw", two(0xF07A, 0x000F), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapueqw", two(0xF07A, 0x0009), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapugew", two(0xF07A, 0x000B), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapugtw", two(0xF07A, 0x000A), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapulew", two(0xF07A, 0x000D), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapultw", two(0xF07A, 0x000C), two(0xF1FF, 0xFFFF), "Ii^w"},
+{"ftrapunw", two(0xF07A, 0x0008), two(0xF1FF, 0xFFFF), "Ii^w"},
+
+{"ftrapeql", two(0xF07B, 0x0001), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapfl", two(0xF07B, 0x0000), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapgel", two(0xF07B, 0x0013), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapgll", two(0xF07B, 0x0016), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapglel", two(0xF07B, 0x0017), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapgtl", two(0xF07B, 0x0012), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftraplel", two(0xF07B, 0x0015), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapltl", two(0xF07B, 0x0014), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapnel", two(0xF07B, 0x000E), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapngel", two(0xF07B, 0x001C), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapngll", two(0xF07B, 0x0019), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapnglel", two(0xF07B, 0x0018), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapngtl", two(0xF07B, 0x001D), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapnlel", two(0xF07B, 0x001A), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapnltl", two(0xF07B, 0x001B), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapogel", two(0xF07B, 0x0003), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapogll", two(0xF07B, 0x0006), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapogtl", two(0xF07B, 0x0002), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapolel", two(0xF07B, 0x0005), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapoltl", two(0xF07B, 0x0004), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftraporl", two(0xF07B, 0x0007), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapseql", two(0xF07B, 0x0011), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapsfl", two(0xF07B, 0x0010), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapsnel", two(0xF07B, 0x001E), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapstl", two(0xF07B, 0x001F), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftraptl", two(0xF07B, 0x000F), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapueql", two(0xF07B, 0x0009), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapugel", two(0xF07B, 0x000B), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapugtl", two(0xF07B, 0x000A), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapulel", two(0xF07B, 0x000D), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapultl", two(0xF07B, 0x000C), two(0xF1FF, 0xFFFF), "Ii^l"},
+{"ftrapunl", two(0xF07B, 0x0008), two(0xF1FF, 0xFFFF), "Ii^l"},
+
+{"ftstb", two(0xF000, 0x583A), two(0xF1C0, 0xFC7F), "Ii;b"},
+{"ftstd", two(0xF000, 0x543A), two(0xF1C0, 0xFC7F), "Ii;F"},
+{"ftstl", two(0xF000, 0x403A), two(0xF1C0, 0xFC7F), "Ii;l"},
+{"ftstp", two(0xF000, 0x4C3A), two(0xF1C0, 0xFC7F), "Ii;p"},
+{"ftsts", two(0xF000, 0x443A), two(0xF1C0, 0xFC7F), "Ii;f"},
+{"ftstw", two(0xF000, 0x503A), two(0xF1C0, 0xFC7F), "Ii;w"},
+{"ftstx", two(0xF000, 0x003A), two(0xF1C0, 0xE07F), "IiF8"},
+{"ftstx", two(0xF000, 0x483A), two(0xF1C0, 0xFC7F), "Ii;x"},
+
+{"ftwotoxb", two(0xF000, 0x5811), two(0xF1C0, 0xFC7F), "Ii;bF7"},
+{"ftwotoxd", two(0xF000, 0x5411), two(0xF1C0, 0xFC7F), "Ii;FF7"},
+{"ftwotoxl", two(0xF000, 0x4011), two(0xF1C0, 0xFC7F), "Ii;lF7"},
+{"ftwotoxp", two(0xF000, 0x4C11), two(0xF1C0, 0xFC7F), "Ii;pF7"},
+{"ftwotoxs", two(0xF000, 0x4411), two(0xF1C0, 0xFC7F), "Ii;fF7"},
+{"ftwotoxw", two(0xF000, 0x5011), two(0xF1C0, 0xFC7F), "Ii;wF7"},
+{"ftwotoxx", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiF8F7"},
+{"ftwotoxx", two(0xF000, 0x4811), two(0xF1C0, 0xFC7F), "Ii;xF7"},
+{"ftwotoxx", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiFt"},
+
+
+{"fjeq", one(0xF081), one(0xF1FF), "IdBc"},
+{"fjf", one(0xF080), one(0xF1FF), "IdBc"},
+{"fjge", one(0xF093), one(0xF1FF), "IdBc"},
+{"fjgl", one(0xF096), one(0xF1FF), "IdBc"},
+{"fjgle", one(0xF097), one(0xF1FF), "IdBc"},
+{"fjgt", one(0xF092), one(0xF1FF), "IdBc"},
+{"fjle", one(0xF095), one(0xF1FF), "IdBc"},
+{"fjlt", one(0xF094), one(0xF1FF), "IdBc"},
+{"fjne", one(0xF08E), one(0xF1FF), "IdBc"},
+{"fjnge", one(0xF09C), one(0xF1FF), "IdBc"},
+{"fjngl", one(0xF099), one(0xF1FF), "IdBc"},
+{"fjngle", one(0xF098), one(0xF1FF), "IdBc"},
+{"fjngt", one(0xF09D), one(0xF1FF), "IdBc"},
+{"fjnle", one(0xF09A), one(0xF1FF), "IdBc"},
+{"fjnlt", one(0xF09B), one(0xF1FF), "IdBc"},
+{"fjoge", one(0xF083), one(0xF1FF), "IdBc"},
+{"fjogl", one(0xF086), one(0xF1FF), "IdBc"},
+{"fjogt", one(0xF082), one(0xF1FF), "IdBc"},
+{"fjole", one(0xF085), one(0xF1FF), "IdBc"},
+{"fjolt", one(0xF084), one(0xF1FF), "IdBc"},
+{"fjor", one(0xF087), one(0xF1FF), "IdBc"},
+{"fjseq", one(0xF091), one(0xF1FF), "IdBc"},
+{"fjsf", one(0xF090), one(0xF1FF), "IdBc"},
+{"fjsne", one(0xF09E), one(0xF1FF), "IdBc"},
+{"fjst", one(0xF09F), one(0xF1FF), "IdBc"},
+{"fjt", one(0xF08F), one(0xF1FF), "IdBc"},
+{"fjueq", one(0xF089), one(0xF1FF), "IdBc"},
+{"fjuge", one(0xF08B), one(0xF1FF), "IdBc"},
+{"fjugt", one(0xF08A), one(0xF1FF), "IdBc"},
+{"fjule", one(0xF08D), one(0xF1FF), "IdBc"},
+{"fjult", one(0xF08C), one(0xF1FF), "IdBc"},
+{"fjun", one(0xF088), one(0xF1FF), "IdBc"},
+
+/* The assembler will ignore attempts to force a short offset */
+
+{"bhis", one(0061000), one(0177400), "Bg"},
+{"blss", one(0061400), one(0177400), "Bg"},
+{"bccs", one(0062000), one(0177400), "Bg"},
+{"bcss", one(0062400), one(0177400), "Bg"},
+{"bnes", one(0063000), one(0177400), "Bg"},
+{"beqs", one(0063400), one(0177400), "Bg"},
+{"bvcs", one(0064000), one(0177400), "Bg"},
+{"bvss", one(0064400), one(0177400), "Bg"},
+{"bpls", one(0065000), one(0177400), "Bg"},
+{"bmis", one(0065400), one(0177400), "Bg"},
+{"bges", one(0066000), one(0177400), "Bg"},
+{"blts", one(0066400), one(0177400), "Bg"},
+{"bgts", one(0067000), one(0177400), "Bg"},
+{"bles", one(0067400), one(0177400), "Bg"},
+
+/* Alternate mnemonics for SUN */
+
+{"jbsr", one(0060400), one(0177400), "Bg"},
+{"jbsr", one(0047200), one(0177700), "!s"},
+{"jra", one(0060000), one(0177400), "Bg"},
+{"jra", one(0047300), one(0177700), "!s"},
+
+{"jhi", one(0061000), one(0177400), "Bg"},
+{"jls", one(0061400), one(0177400), "Bg"},
+{"jcc", one(0062000), one(0177400), "Bg"},
+{"jcs", one(0062400), one(0177400), "Bg"},
+{"jne", one(0063000), one(0177400), "Bg"},
+{"jeq", one(0063400), one(0177400), "Bg"},
+{"jvc", one(0064000), one(0177400), "Bg"},
+{"jvs", one(0064400), one(0177400), "Bg"},
+{"jpl", one(0065000), one(0177400), "Bg"},
+{"jmi", one(0065400), one(0177400), "Bg"},
+{"jge", one(0066000), one(0177400), "Bg"},
+{"jlt", one(0066400), one(0177400), "Bg"},
+{"jgt", one(0067000), one(0177400), "Bg"},
+{"jle", one(0067400), one(0177400), "Bg"},
+
+/* Short offsets are ignored */
+
+{"jbsrs", one(0060400), one(0177400), "Bg"},
+{"jras", one(0060000), one(0177400), "Bg"},
+{"jhis", one(0061000), one(0177400), "Bg"},
+{"jlss", one(0061400), one(0177400), "Bg"},
+{"jccs", one(0062000), one(0177400), "Bg"},
+{"jcss", one(0062400), one(0177400), "Bg"},
+{"jnes", one(0063000), one(0177400), "Bg"},
+{"jeqs", one(0063400), one(0177400), "Bg"},
+{"jvcs", one(0064000), one(0177400), "Bg"},
+{"jvss", one(0064400), one(0177400), "Bg"},
+{"jpls", one(0065000), one(0177400), "Bg"},
+{"jmis", one(0065400), one(0177400), "Bg"},
+{"jges", one(0066000), one(0177400), "Bg"},
+{"jlts", one(0066400), one(0177400), "Bg"},
+{"jgts", one(0067000), one(0177400), "Bg"},
+{"jles", one(0067400), one(0177400), "Bg"},
+
+{"movql", one(0070000), one(0170400), "MsDd"},
+{"moveql", one(0070000), one(0170400), "MsDd"},
+{"moval", one(0020100), one(0170700), "*lAd"},
+{"movaw", one(0030100), one(0170700), "*wAd"},
+{"movb", one(0010000), one(0170000), ";b$d"}, /* mov */
+{"movl", one(0070000), one(0170400), "MsDd"}, /* movq written as mov */
+{"movl", one(0020000), one(0170000), "*l$d"},
+{"movl", one(0020100), one(0170700), "*lAd"},
+{"movl", one(0047140), one(0177770), "AsUd"}, /* mov to USP */
+{"movl", one(0047150), one(0177770), "UdAs"}, /* mov from USP */
+{"movc", one(0047173), one(0177777), "R1Jj"},
+{"movc", one(0047173), one(0177777), "R1#j"},
+{"movc", one(0047172), one(0177777), "JjR1"},
+{"movc", one(0047172), one(0177777), "#jR1"},
+{"movml", one(0044300), one(0177700), "#w&s"}, /* movm reg to mem. */
+{"movml", one(0044340), one(0177770), "#w-s"}, /* movm reg to autodecrement. */
+{"movml", one(0046300), one(0177700), "!s#w"}, /* movm mem to reg. */
+{"movml", one(0046330), one(0177770), "+s#w"}, /* movm autoinc to reg. */
+{"movml", one(0044300), one(0177700), "Lw&s"}, /* movm reg to mem. */
+{"movml", one(0044340), one(0177770), "lw-s"}, /* movm reg to autodecrement. */
+{"movml", one(0046300), one(0177700), "!sLw"}, /* movm mem to reg. */
+{"movml", one(0046330), one(0177770), "+sLw"}, /* movm autoinc to reg. */
+{"movmw", one(0044200), one(0177700), "#w&s"}, /* movm reg to mem. */
+{"movmw", one(0044240), one(0177770), "#w-s"}, /* movm reg to autodecrement. */
+{"movmw", one(0046200), one(0177700), "!s#w"}, /* movm mem to reg. */
+{"movmw", one(0046230), one(0177770), "+s#w"}, /* movm autoinc to reg. */
+{"movmw", one(0044200), one(0177700), "Lw&s"}, /* movm reg to mem. */
+{"movmw", one(0044240), one(0177770), "lw-s"}, /* movm reg to autodecrement. */
+{"movmw", one(0046200), one(0177700), "!sLw"}, /* movm mem to reg. */
+{"movmw", one(0046230), one(0177770), "+sLw"}, /* movm autoinc to reg. */
+{"movpl", one(0000510), one(0170770), "dsDd"}, /* memory to register */
+{"movpl", one(0000710), one(0170770), "Ddds"}, /* register to memory */
+{"movpw", one(0000410), one(0170770), "dsDd"}, /* memory to register */
+{"movpw", one(0000610), one(0170770), "Ddds"}, /* register to memory */
+{"movq", one(0070000), one(0170400), "MsDd"},
+{"movw", one(0030000), one(0170000), "*w$d"},
+{"movw", one(0030100), one(0170700), "*wAd"}, /* mova, written as mov */
+{"movw", one(0040300), one(0177700), "Ss$s"}, /* Move from sr */
+{"movw", one(0041300), one(0177700), "Cs$s"}, /* Move from ccr */
+{"movw", one(0042300), one(0177700), ";wCd"}, /* mov to ccr */
+{"movw", one(0043300), one(0177700), ";wSd"}, /* mov to sr */
+
+{"movsb", two(0007000, 0), two(0177700, 07777), "~sR1"},
+{"movsb", two(0007000, 04000), two(0177700, 07777), "R1~s"},
+{"movsl", two(0007200, 0), two(0177700, 07777), "~sR1"},
+{"movsl", two(0007200, 04000), two(0177700, 07777), "R1~s"},
+{"movsw", two(0007100, 0), two(0177700, 07777), "~sR1"},
+{"movsw", two(0007100, 04000), two(0177700, 07777), "R1~s"},
+
+#ifdef m68851
+ /* name */ /* opcode */ /* match */ /* args */
+
+{"pbac", one(0xf0c7), one(0xffbf), "Bc"},
+{"pbacw", one(0xf087), one(0xffbf), "Bc"},
+{"pbas", one(0xf0c6), one(0xffbf), "Bc"},
+{"pbasw", one(0xf086), one(0xffbf), "Bc"},
+{"pbbc", one(0xf0c1), one(0xffbf), "Bc"},
+{"pbbcw", one(0xf081), one(0xffbf), "Bc"},
+{"pbbs", one(0xf0c0), one(0xffbf), "Bc"},
+{"pbbsw", one(0xf080), one(0xffbf), "Bc"},
+{"pbcc", one(0xf0cf), one(0xffbf), "Bc"},
+{"pbccw", one(0xf08f), one(0xffbf), "Bc"},
+{"pbcs", one(0xf0ce), one(0xffbf), "Bc"},
+{"pbcsw", one(0xf08e), one(0xffbf), "Bc"},
+{"pbgc", one(0xf0cd), one(0xffbf), "Bc"},
+{"pbgcw", one(0xf08d), one(0xffbf), "Bc"},
+{"pbgs", one(0xf0cc), one(0xffbf), "Bc"},
+{"pbgsw", one(0xf08c), one(0xffbf), "Bc"},
+{"pbic", one(0xf0cb), one(0xffbf), "Bc"},
+{"pbicw", one(0xf08b), one(0xffbf), "Bc"},
+{"pbis", one(0xf0ca), one(0xffbf), "Bc"},
+{"pbisw", one(0xf08a), one(0xffbf), "Bc"},
+{"pblc", one(0xf0c3), one(0xffbf), "Bc"},
+{"pblcw", one(0xf083), one(0xffbf), "Bc"},
+{"pbls", one(0xf0c2), one(0xffbf), "Bc"},
+{"pblsw", one(0xf082), one(0xffbf), "Bc"},
+{"pbsc", one(0xf0c5), one(0xffbf), "Bc"},
+{"pbscw", one(0xf085), one(0xffbf), "Bc"},
+{"pbss", one(0xf0c4), one(0xffbf), "Bc"},
+{"pbssw", one(0xf084), one(0xffbf), "Bc"},
+{"pbwc", one(0xf0c9), one(0xffbf), "Bc"},
+{"pbwcw", one(0xf089), one(0xffbf), "Bc"},
+{"pbws", one(0xf0c8), one(0xffbf), "Bc"},
+{"pbwsw", one(0xf088), one(0xffbf), "Bc"},
+
+
+{"pdbac", two(0xf048, 0x0007), two(0xfff8, 0xffff), "DsBw"},
+{"pdbas", two(0xf048, 0x0006), two(0xfff8, 0xffff), "DsBw"},
+{"pdbbc", two(0xf048, 0x0001), two(0xfff8, 0xffff), "DsBw"},
+{"pdbbs", two(0xf048, 0x0000), two(0xfff8, 0xffff), "DsBw"},
+{"pdbcc", two(0xf048, 0x000f), two(0xfff8, 0xffff), "DsBw"},
+{"pdbcs", two(0xf048, 0x000e), two(0xfff8, 0xffff), "DsBw"},
+{"pdbgc", two(0xf048, 0x000d), two(0xfff8, 0xffff), "DsBw"},
+{"pdbgs", two(0xf048, 0x000c), two(0xfff8, 0xffff), "DsBw"},
+{"pdbic", two(0xf048, 0x000b), two(0xfff8, 0xffff), "DsBw"},
+{"pdbis", two(0xf048, 0x000a), two(0xfff8, 0xffff), "DsBw"},
+{"pdblc", two(0xf048, 0x0003), two(0xfff8, 0xffff), "DsBw"},
+{"pdbls", two(0xf048, 0x0002), two(0xfff8, 0xffff), "DsBw"},
+{"pdbsc", two(0xf048, 0x0005), two(0xfff8, 0xffff), "DsBw"},
+{"pdbss", two(0xf048, 0x0004), two(0xfff8, 0xffff), "DsBw"},
+{"pdbwc", two(0xf048, 0x0009), two(0xfff8, 0xffff), "DsBw"},
+{"pdbws", two(0xf048, 0x0008), two(0xfff8, 0xffff), "DsBw"},
+
+{"pflusha", two(0xf000, 0x2400), two(0xffff, 0xffff), "" },
+
+{"pflush", two(0xf000, 0x3010), two(0xffc0, 0xfe10), "T3T9" },
+{"pflush", two(0xf000, 0x3810), two(0xffc0, 0xfe10), "T3T9&s" },
+{"pflush", two(0xf000, 0x3008), two(0xffc0, 0xfe18), "D3T9" },
+{"pflush", two(0xf000, 0x3808), two(0xffc0, 0xfe18), "D3T9&s" },
+{"pflush", two(0xf000, 0x3000), two(0xffc0, 0xfe1e), "f3T9" },
+{"pflush", two(0xf000, 0x3800), two(0xffc0, 0xfe1e), "f3T9&s" },
+
+{"pflushs", two(0xf000, 0x3410), two(0xfff8, 0xfe10), "T3T9" },
+{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe00), "T3T9&s" },
+{"pflushs", two(0xf000, 0x3408), two(0xfff8, 0xfe18), "D3T9" },
+{"pflushs", two(0xf000, 0x3c08), two(0xfff8, 0xfe18), "D3T9&s" },
+{"pflushs", two(0xf000, 0x3400), two(0xfff8, 0xfe1e), "f3T9" },
+{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe1e), "f3T9&s"},
+
+{"pflushr", two(0xf000, 0xa000), two(0xffc0, 0xffff), "|s" },
+
+{"ploadr", two(0xf000, 0x2210), two(0xffc0, 0xfff0), "T3&s" },
+{"ploadr", two(0xf000, 0x2208), two(0xffc0, 0xfff8), "D3&s" },
+{"ploadr", two(0xf000, 0x2200), two(0xffc0, 0xfffe), "f3&s" },
+{"ploadw", two(0xf000, 0x2010), two(0xffc0, 0xfff0), "T3&s" },
+{"ploadw", two(0xf000, 0x2008), two(0xffc0, 0xfff8), "D3&s" },
+{"ploadw", two(0xf000, 0x2000), two(0xffc0, 0xfffe), "f3&s" },
+
+/* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "*sP8" },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "P8%s" },
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "|sW8" },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "W8~s" },
+
+/* BADx, BACx */
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xe3e3), "*sX3" },
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xe3e3), "X3%s" },
+
+/* PSR, PCSR */
+/* {"pmove", two(0xf000, 0x6100), two(oxffc0, oxffff), "*sZ8" }, */
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xffff), "*sY8" },
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xffff), "Y8%s" },
+{"pmove", two(0xf000, 0x6600), two(0xffc0, 0xffff), "Z8%s" },
+
+{"prestore", one(0xf140), one(0xffc0), "&s"},
+{"prestore", one(0xf158), one(0xfff8), "+s"},
+{"psave", one(0xf100), one(0xffc0), "&s"},
+{"psave", one(0xf100), one(0xffc0), "+s"},
+
+{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "@s"},
+{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "@s"},
+{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "@s"},
+{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "@s"},
+{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "@s"},
+{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "@s"},
+{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "@s"},
+{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "@s"},
+{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "@s"},
+{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "@s"},
+{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "@s"},
+{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "@s"},
+{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "@s"},
+{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "@s"},
+{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "@s"},
+{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "@s"},
+
+{"ptestr", two(0xf000, 0x8210), two(0xffc0, 0xe3f0), "T3&sQ8" },
+{"ptestr", two(0xf000, 0x8310), two(0xffc0, 0xe310), "T3&sQ8A9" },
+{"ptestr", two(0xf000, 0x8208), two(0xffc0, 0xe3f8), "D3&sQ8" },
+{"ptestr", two(0xf000, 0x8308), two(0xffc0, 0xe318), "D3&sQ8A9" },
+{"ptestr", two(0xf000, 0x8200), two(0xffc0, 0xe3fe), "f3&sQ8" },
+{"ptestr", two(0xf000, 0x8300), two(0xffc0, 0xe31e), "f3&sQ8A9" },
+
+{"ptestw", two(0xf000, 0x8010), two(0xffc0, 0xe3f0), "T3&sQ8" },
+{"ptestw", two(0xf000, 0x8110), two(0xffc0, 0xe310), "T3&sQ8A9" },
+{"ptestw", two(0xf000, 0x8008), two(0xffc0, 0xe3f8), "D3&sQ8" },
+{"ptestw", two(0xf000, 0x8108), two(0xffc0, 0xe318), "D3&sQ8A9" },
+{"ptestw", two(0xf000, 0x8000), two(0xffc0, 0xe3fe), "f3&sQ8" },
+{"ptestw", two(0xf000, 0x8100), two(0xffc0, 0xe31e), "f3&sQ8A9" },
+
+{"ptrapacw", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w"},
+{"ptrapacl", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l"},
+{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), ""},
+
+{"ptrapasw", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w"},
+{"ptrapasl", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l"},
+{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), ""},
+
+{"ptrapbcw", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w"},
+{"ptrapbcl", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l"},
+{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), ""},
+
+{"ptrapbsw", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w"},
+{"ptrapbsl", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l"},
+{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), ""},
+
+{"ptrapccw", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w"},
+{"ptrapccl", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l"},
+{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), ""},
+
+{"ptrapcsw", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w"},
+{"ptrapcsl", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l"},
+{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), ""},
+
+{"ptrapgcw", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w"},
+{"ptrapgcl", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l"},
+{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), ""},
+
+{"ptrapgsw", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w"},
+{"ptrapgsl", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l"},
+{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), ""},
+
+{"ptrapicw", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w"},
+{"ptrapicl", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l"},
+{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), ""},
+
+{"ptrapisw", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w"},
+{"ptrapisl", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l"},
+{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), ""},
+
+{"ptraplcw", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w"},
+{"ptraplcl", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l"},
+{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), ""},
+
+{"ptraplsw", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w"},
+{"ptraplsl", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l"},
+{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), ""},
+
+{"ptrapscw", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w"},
+{"ptrapscl", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l"},
+{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), ""},
+
+{"ptrapssw", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w"},
+{"ptrapssl", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l"},
+{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), ""},
+
+{"ptrapwcw", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w"},
+{"ptrapwcl", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l"},
+{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), ""},
+
+{"ptrapwsw", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w"},
+{"ptrapwsl", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l"},
+{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), ""},
+
+{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s"},
+{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s" },
+
+#endif /* m68851 */
+
+};
+
+int numopcodes=sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);
+
+struct m68k_opcode *endop = m68k_opcodes+sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);
--- /dev/null
+/* Print m68k instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "m68k-opcode.h"
+#include "gdbcore.h"
+
+/* 68k instructions are never longer than this many bytes. */
+#define MAXLEN 22
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
+
+extern char *reg_names[];
+char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
+ "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
+
+static unsigned char *print_insn_arg ();
+static unsigned char *print_indexed ();
+static void print_base ();
+static int fetch_arg ();
+
+#define NEXTBYTE(p) (p += 2, ((char *)p)[-1])
+
+#define NEXTWORD(p) \
+ (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
+
+#define NEXTLONG(p) \
+ (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+#define NEXTSINGLE(p) \
+ (p += 4, *((float *)(p - 4)))
+
+#define NEXTDOUBLE(p) \
+ (p += 8, *((double *)(p - 8)))
+
+#define NEXTEXTEND(p) \
+ (p += 12, 0.0) /* Need a function to convert from extended to double
+ precision... */
+
+#define NEXTPACKED(p) \
+ (p += 12, 0.0) /* Need a function to convert from packed to double
+ precision. Actually, it's easier to print a
+ packed number than a double anyway, so maybe
+ there should be a special case to handle this... */
+\f
+/* Print the m68k instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register unsigned char *p;
+ register char *d;
+ register int bestmask;
+ int best;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ bestmask = 0;
+ best = -1;
+ for (i = 0; i < NOPCODES; i++)
+ {
+ register unsigned int opcode = m68k_opcodes[i].opcode;
+ register unsigned int match = m68k_opcodes[i].match;
+ if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
+ && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
+ && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
+ && ((0xff & buffer[3] & match) == (0xff & opcode)))
+ {
+ /* Don't use for printout the variants of divul and divsl
+ that have the same register number in two places.
+ The more general variants will match instead. */
+ for (d = m68k_opcodes[i].args; *d; d += 2)
+ if (d[1] == 'D')
+ break;
+
+ /* Don't use for printout the variants of most floating
+ point coprocessor instructions which use the same
+ register number in two places, as above. */
+ if (*d == 0)
+ for (d = m68k_opcodes[i].args; *d; d += 2)
+ if (d[1] == 't')
+ break;
+
+ if (*d == 0 && match > bestmask)
+ {
+ best = i;
+ bestmask = match;
+ }
+ }
+ }
+
+ /* Handle undefined instructions. */
+ if (best < 0)
+ {
+ fprintf_filtered (stream, "0%o", (buffer[0] << 8) + buffer[1]);
+ return 2;
+ }
+
+ fprintf_filtered (stream, "%s", m68k_opcodes[best].name);
+
+ /* Point at first word of argument data,
+ and at descriptor for first argument. */
+ p = buffer + 2;
+
+ /* Why do this this way? -MelloN */
+ for (d = m68k_opcodes[best].args; *d; d += 2)
+ {
+ if (d[0] == '#')
+ {
+ if (d[1] == 'l' && p - buffer < 6)
+ p = buffer + 6;
+ else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
+ p = buffer + 4;
+ }
+ if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
+ p = buffer + 4;
+ if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
+ p = buffer + 6;
+ if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
+ p = buffer + 4;
+ }
+
+ d = m68k_opcodes[best].args;
+
+ if (*d)
+ fputs_filtered (" ", stream);
+
+ while (*d)
+ {
+ p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream);
+ d += 2;
+ if (*d && *(d - 2) != 'I' && *d != 'k')
+ fputs_filtered (",", stream);
+ }
+ return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, buffer, p, addr, stream)
+ char *d;
+ unsigned char *buffer;
+ register unsigned char *p;
+ CORE_ADDR addr; /* PC for this arg to be relative to */
+ FILE *stream;
+{
+ register int val;
+ register int place = d[1];
+ int regno;
+ register char *regname;
+ register unsigned char *p1;
+ register double flval;
+ int flt_p;
+
+ switch (*d)
+ {
+ case 'C':
+ fprintf_filtered (stream, "ccr");
+ break;
+
+ case 'S':
+ fprintf_filtered (stream, "sr");
+ break;
+
+ case 'U':
+ fprintf_filtered (stream, "usp");
+ break;
+
+ case 'J':
+ {
+ static struct { char *name; int value; } names[]
+ = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
+ {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
+ {"msp", 0x803}, {"isp", 0x804}};
+
+ val = fetch_arg (buffer, place, 12);
+ for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
+ if (names[regno].value == val)
+ {
+ fprintf_filtered (stream, names[regno].name);
+ break;
+ }
+ if (regno < 0)
+ fprintf_filtered (stream, "%d", val);
+ }
+ break;
+
+ case 'Q':
+ val = fetch_arg (buffer, place, 3);
+ /* 0 means 8, except for the bkpt instruction... */
+ if (val == 0 && d[1] != 's')
+ val = 8;
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'M':
+ val = fetch_arg (buffer, place, 8);
+ if (val & 0x80)
+ val = val - 0x100;
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'T':
+ val = fetch_arg (buffer, place, 4);
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'D':
+ fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
+ break;
+
+ case 'A':
+ fprintf_filtered (stream, "%s",
+ reg_names[fetch_arg (buffer, place, 3) + 010]);
+ break;
+
+ case 'R':
+ fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
+ break;
+
+ case 'F':
+ fprintf_filtered (stream, "fp%d", fetch_arg (buffer, place, 3));
+ break;
+
+ case 'O':
+ val = fetch_arg (buffer, place, 6);
+ if (val & 0x20)
+ fprintf_filtered (stream, "%s", reg_names [val & 7]);
+ else
+ fprintf_filtered (stream, "%d", val);
+ break;
+
+ case '+':
+ fprintf_filtered (stream, "%s@+",
+ reg_names[fetch_arg (buffer, place, 3) + 8]);
+ break;
+
+ case '-':
+ fprintf_filtered (stream, "%s@-",
+ reg_names[fetch_arg (buffer, place, 3) + 8]);
+ break;
+
+ case 'k':
+ if (place == 'k')
+ fprintf_filtered (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
+ else if (place == 'C')
+ {
+ val = fetch_arg (buffer, place, 7);
+ if ( val > 63 ) /* This is a signed constant. */
+ val -= 128;
+ fprintf_filtered (stream, "{#%d}", val);
+ }
+ else
+ error ("Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+ break;
+
+ case '#':
+ case '^':
+ p1 = buffer + (*d == '#' ? 2 : 4);
+ if (place == 's')
+ val = fetch_arg (buffer, place, 4);
+ else if (place == 'C')
+ val = fetch_arg (buffer, place, 7);
+ else if (place == '8')
+ val = fetch_arg (buffer, place, 3);
+ else if (place == '3')
+ val = fetch_arg (buffer, place, 8);
+ else if (place == 'b')
+ val = NEXTBYTE (p1);
+ else if (place == 'w')
+ val = NEXTWORD (p1);
+ else if (place == 'l')
+ val = NEXTLONG (p1);
+ else
+ error ("Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ case 'B':
+ if (place == 'b')
+ val = NEXTBYTE (p);
+ else if (place == 'w')
+ val = NEXTWORD (p);
+ else if (place == 'l')
+ val = NEXTLONG (p);
+ else if (place == 'g')
+ {
+ val = ((char *)buffer)[1];
+ if (val == 0)
+ val = NEXTWORD (p);
+ else if (val == -1)
+ val = NEXTLONG (p);
+ }
+ else if (place == 'c')
+ {
+ if (buffer[1] & 0x40) /* If bit six is one, long offset */
+ val = NEXTLONG (p);
+ else
+ val = NEXTWORD (p);
+ }
+ else
+ error ("Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+
+ print_address (addr + val, stream);
+ break;
+
+ case 'd':
+ val = NEXTWORD (p);
+ fprintf_filtered (stream, "%s@(%d)",
+ reg_names[fetch_arg (buffer, place, 3)], val);
+ break;
+
+ case 's':
+ fprintf_filtered (stream, "%s",
+ fpcr_names[fetch_arg (buffer, place, 3)]);
+ break;
+
+ case 'I':
+ val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
+ if (val != 1) /* Unusual coprocessor ID? */
+ fprintf_filtered (stream, "(cpid=%d) ", val);
+ if (place == 'i')
+ p += 2; /* Skip coprocessor extended operands */
+ break;
+
+ case '*':
+ case '~':
+ case '%':
+ case ';':
+ case '@':
+ case '!':
+ case '$':
+ case '?':
+ case '/':
+ case '&':
+
+ if (place == 'd')
+ {
+ val = fetch_arg (buffer, 'x', 6);
+ val = ((val & 7) << 3) + ((val >> 3) & 7);
+ }
+ else
+ val = fetch_arg (buffer, 's', 6);
+
+ /* Get register number assuming address register. */
+ regno = (val & 7) + 8;
+ regname = reg_names[regno];
+ switch (val >> 3)
+ {
+ case 0:
+ fprintf_filtered (stream, "%s", reg_names[val]);
+ break;
+
+ case 1:
+ fprintf_filtered (stream, "%s", regname);
+ break;
+
+ case 2:
+ fprintf_filtered (stream, "%s@", regname);
+ break;
+
+ case 3:
+ fprintf_filtered (stream, "%s@+", regname);
+ break;
+
+ case 4:
+ fprintf_filtered (stream, "%s@-", regname);
+ break;
+
+ case 5:
+ val = NEXTWORD (p);
+ fprintf_filtered (stream, "%s@(%d)", regname, val);
+ break;
+
+ case 6:
+ p = print_indexed (regno, p, addr, stream);
+ break;
+
+ case 7:
+ switch (val & 7)
+ {
+ case 0:
+ val = NEXTWORD (p);
+ fprintf_filtered (stream, "@#");
+ print_address (val, stream);
+ break;
+
+ case 1:
+ val = NEXTLONG (p);
+ fprintf_filtered (stream, "@#");
+ print_address (val, stream);
+ break;
+
+ case 2:
+ val = NEXTWORD (p);
+ print_address (addr + val, stream);
+ break;
+
+ case 3:
+ p = print_indexed (-1, p, addr, stream);
+ break;
+
+ case 4:
+ flt_p = 1; /* Assume it's a float... */
+ switch( place )
+ {
+ case 'b':
+ val = NEXTBYTE (p);
+ flt_p = 0;
+ break;
+
+ case 'w':
+ val = NEXTWORD (p);
+ flt_p = 0;
+ break;
+
+ case 'l':
+ val = NEXTLONG (p);
+ flt_p = 0;
+ break;
+
+ case 'f':
+ flval = NEXTSINGLE(p);
+ break;
+
+ case 'F':
+ flval = NEXTDOUBLE(p);
+ break;
+
+ case 'x':
+ flval = NEXTEXTEND(p);
+ break;
+
+ case 'p':
+ flval = NEXTPACKED(p);
+ break;
+
+ default:
+ error ("Invalid arg format in opcode table: \"%c%c\".",
+ *d, place);
+ }
+ if ( flt_p ) /* Print a float? */
+ fprintf_filtered (stream, "#%g", flval);
+ else
+ fprintf_filtered (stream, "#%d", val);
+ break;
+
+ default:
+ fprintf_filtered (stream, "<invalid address mode 0%o>", val);
+ }
+ }
+ break;
+
+ case 'L':
+ case 'l':
+ if (place == 'w')
+ {
+ char doneany;
+ p1 = buffer + 2;
+ val = NEXTWORD (p1);
+ /* Move the pointer ahead if this point is farther ahead
+ than the last. */
+ p = p1 > p ? p1 : p;
+ if (val == 0)
+ {
+ fputs_filtered ("#0", stream);
+ break;
+ }
+ if (*d == 'l')
+ {
+ register int newval = 0;
+ for (regno = 0; regno < 16; ++regno)
+ if (val & (0x8000 >> regno))
+ newval |= 1 << regno;
+ val = newval;
+ }
+ val &= 0xffff;
+ doneany = 0;
+ for (regno = 0; regno < 16; ++regno)
+ if (val & (1 << regno))
+ {
+ int first_regno;
+ if (doneany)
+ fputs_filtered ("/", stream);
+ doneany = 1;
+ fprintf_filtered (stream, "%s", reg_names[regno]);
+ first_regno = regno;
+ while (val & (1 << (regno + 1)))
+ ++regno;
+ if (regno > first_regno)
+ fprintf_filtered (stream, "-%s", reg_names[regno]);
+ }
+ }
+ else if (place == '3')
+ {
+ /* `fmovem' insn. */
+ char doneany;
+ val = fetch_arg (buffer, place, 8);
+ if (val == 0)
+ {
+ fputs_filtered ("#0", stream);
+ break;
+ }
+ if (*d == 'l')
+ {
+ register int newval = 0;
+ for (regno = 0; regno < 8; ++regno)
+ if (val & (0x80 >> regno))
+ newval |= 1 << regno;
+ val = newval;
+ }
+ val &= 0xff;
+ doneany = 0;
+ for (regno = 0; regno < 8; ++regno)
+ if (val & (1 << regno))
+ {
+ int first_regno;
+ if (doneany)
+ fputs_filtered ("/", stream);
+ doneany = 1;
+ fprintf_filtered (stream, "fp%d", regno);
+ first_regno = regno;
+ while (val & (1 << (regno + 1)))
+ ++regno;
+ if (regno > first_regno)
+ fprintf_filtered (stream, "-fp%d", regno);
+ }
+ }
+ else
+ abort ();
+ break;
+
+ default:
+ error ("Invalid arg format in opcode table: \"%c\".", *d);
+ }
+
+ return (unsigned char *) p;
+}
+
+/* Fetch BITS bits from a position in the instruction specified by CODE.
+ CODE is a "place to put an argument", or 'x' for a destination
+ that is a general address (mode and register).
+ BUFFER contains the instruction. */
+
+static int
+fetch_arg (buffer, code, bits)
+ unsigned char *buffer;
+ char code;
+ int bits;
+{
+ register int val;
+ switch (code)
+ {
+ case 's':
+ val = buffer[1];
+ break;
+
+ case 'd': /* Destination, for register or quick. */
+ val = (buffer[0] << 8) + buffer[1];
+ val >>= 9;
+ break;
+
+ case 'x': /* Destination, for general arg */
+ val = (buffer[0] << 8) + buffer[1];
+ val >>= 6;
+ break;
+
+ case 'k':
+ val = (buffer[3] >> 4);
+ break;
+
+ case 'C':
+ val = buffer[3];
+ break;
+
+ case '1':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 12;
+ break;
+
+ case '2':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 6;
+ break;
+
+ case '3':
+ case 'j':
+ val = (buffer[2] << 8) + buffer[3];
+ break;
+
+ case '4':
+ val = (buffer[4] << 8) + buffer[5];
+ val >>= 12;
+ break;
+
+ case '5':
+ val = (buffer[4] << 8) + buffer[5];
+ val >>= 6;
+ break;
+
+ case '6':
+ val = (buffer[4] << 8) + buffer[5];
+ break;
+
+ case '7':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 7;
+ break;
+
+ case '8':
+ val = (buffer[2] << 8) + buffer[3];
+ val >>= 10;
+ break;
+
+ default:
+ abort ();
+ }
+
+ switch (bits)
+ {
+ case 3:
+ return val & 7;
+ case 4:
+ return val & 017;
+ case 5:
+ return val & 037;
+ case 6:
+ return val & 077;
+ case 7:
+ return val & 0177;
+ case 8:
+ return val & 0377;
+ case 12:
+ return val & 07777;
+ default:
+ abort ();
+ }
+}
+
+/* Print an indexed argument. The base register is BASEREG (-1 for pc).
+ P points to extension word, in buffer.
+ ADDR is the nominal core address of that extension word. */
+
+static unsigned char *
+print_indexed (basereg, p, addr, stream)
+ int basereg;
+ unsigned char *p;
+ FILE *stream;
+ CORE_ADDR addr;
+{
+ register int word;
+ static char *scales[] = {"", "*2", "*4", "*8"};
+ register int base_disp;
+ register int outer_disp;
+ char buf[40];
+
+ word = NEXTWORD (p);
+
+ /* Generate the text for the index register.
+ Where this will be output is not yet determined. */
+ sprintf (buf, "[%s.%c%s]",
+ reg_names[(word >> 12) & 0xf],
+ (word & 0x800) ? 'l' : 'w',
+ scales[(word >> 9) & 3]);
+
+ /* Handle the 68000 style of indexing. */
+
+ if ((word & 0x100) == 0)
+ {
+ print_base (basereg,
+ ((word & 0x80) ? word | 0xff00 : word & 0xff)
+ + ((basereg == -1) ? addr : 0),
+ stream);
+ fputs_filtered (buf, stream);
+ return p;
+ }
+
+ /* Handle the generalized kind. */
+ /* First, compute the displacement to add to the base register. */
+
+ if (word & 0200)
+ basereg = -2;
+ if (word & 0100)
+ buf[0] = 0;
+ base_disp = 0;
+ switch ((word >> 4) & 3)
+ {
+ case 2:
+ base_disp = NEXTWORD (p);
+ break;
+ case 3:
+ base_disp = NEXTLONG (p);
+ }
+ if (basereg == -1)
+ base_disp += addr;
+
+ /* Handle single-level case (not indirect) */
+
+ if ((word & 7) == 0)
+ {
+ print_base (basereg, base_disp, stream);
+ fputs_filtered (buf, stream);
+ return p;
+ }
+
+ /* Two level. Compute displacement to add after indirection. */
+
+ outer_disp = 0;
+ switch (word & 3)
+ {
+ case 2:
+ outer_disp = NEXTWORD (p);
+ break;
+ case 3:
+ outer_disp = NEXTLONG (p);
+ }
+
+ fprintf_filtered (stream, "%d(", outer_disp);
+ print_base (basereg, base_disp, stream);
+
+ /* If postindexed, print the closeparen before the index. */
+ if (word & 4)
+ fprintf_filtered (stream, ")%s", buf);
+ /* If preindexed, print the closeparen after the index. */
+ else
+ fprintf_filtered (stream, "%s)", buf);
+
+ return p;
+}
+
+/* Print a base register REGNO and displacement DISP, on STREAM.
+ REGNO = -1 for pc, -2 for none (suppressed). */
+
+static void
+print_base (regno, disp, stream)
+ int regno;
+ int disp;
+ FILE *stream;
+{
+ if (regno == -2)
+ fprintf_filtered (stream, "%d", disp);
+ else if (regno == -1)
+ fprintf_filtered (stream, "0x%x", disp);
+ else
+ fprintf_filtered (stream, "%d(%s)", disp, reg_names[regno]);
+}
--- /dev/null
+/* Standard debugging hooks for `malloc'.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#include "ansidecl.h"
+#include <stdlib.h>
+#include "gmalloc.h"
+
+/* Old hook values. */
+static void EXFUN((*old_free_hook), (PTR ptr));
+static PTR EXFUN((*old_malloc_hook), (size_t size));
+static PTR EXFUN((*old_realloc_hook), (PTR ptr, size_t size));
+
+/* Function to call when something awful happens. */
+static void EXFUN((*abortfunc), (void)) = abort;
+
+/* Arbitrary magical numbers. */
+#define MAGICWORD 0xfedabeeb
+#define MAGICBYTE ((char) 0xd7)
+
+struct hdr
+ {
+ size_t size; /* Exact size requested by user. */
+ unsigned int magic; /* Magic number to check header integrity. */
+ };
+
+static void
+DEFUN(checkhdr, (hdr), CONST struct hdr *hdr)
+{
+ if (hdr->magic != MAGICWORD || ((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+ (*abortfunc)();
+}
+
+static void
+DEFUN(freehook, (ptr), PTR ptr)
+{
+ struct hdr *hdr = ((struct hdr *) ptr) - 1;
+ checkhdr(hdr);
+ hdr->magic = 0;
+ __free_hook = old_free_hook;
+ free(hdr);
+ __free_hook = freehook;
+}
+
+static PTR
+DEFUN(mallochook, (size), size_t size)
+{
+ struct hdr *hdr;
+
+ __malloc_hook = old_malloc_hook;
+ hdr = (struct hdr *) malloc(sizeof(struct hdr) + size + 1);
+ __malloc_hook = mallochook;
+ if (hdr == NULL)
+ return NULL;
+
+ hdr->size = size;
+ hdr->magic = MAGICWORD;
+ ((char *) &hdr[1])[size] = MAGICBYTE;
+ return (PTR) (hdr + 1);
+}
+
+static PTR
+DEFUN(reallochook, (ptr, size), PTR ptr AND size_t size)
+{
+ struct hdr *hdr = ((struct hdr *) ptr) - 1;
+
+ checkhdr(hdr);
+ __free_hook = old_free_hook;
+ __malloc_hook = old_malloc_hook;
+ __realloc_hook = old_realloc_hook;
+ hdr = (struct hdr *) realloc((PTR) hdr, sizeof(struct hdr) + size + 1);
+ __free_hook = freehook;
+ __malloc_hook = mallochook;
+ __realloc_hook = reallochook;
+ if (hdr == NULL)
+ return NULL;
+
+ hdr->size = size;
+ ((char *) &hdr[1])[size] = MAGICBYTE;
+ return (PTR) (hdr + 1);
+}
+
+void
+DEFUN(mcheck, (func), void EXFUN((*func), (void)))
+{
+ static int mcheck_used = 0;
+
+ if (func)
+ abortfunc = func;
+
+ /* These hooks may not be safely inserted if malloc is already in use. */
+ if (!__malloc_initialized && !mcheck_used)
+ {
+ old_free_hook = __free_hook;
+ __free_hook = freehook;
+ old_malloc_hook = __malloc_hook;
+ __malloc_hook = mallochook;
+ old_realloc_hook = __realloc_hook;
+ __realloc_hook = reallochook;
+ mcheck_used = 1;
+ }
+}
--- /dev/null
+/* Mips opcde list for GDB, the GNU debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ Contributed by Nobuyuki Hikichi(hikichi@sra.junet)
+ Made to work for little-endian machines, and debugged
+ by Per Bothner (bothner@cs.wisc.edu).
+ Many fixes contributed by Frank Yellin (fy@lucid.com).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef BITS_BIG_ENDIAN
+#define BIT_FIELDS_2(a,b) a;b;
+#define BIT_FIELDS_4(a,b,c,d) a;b;c;d;
+#define BIT_FIELDS_6(a,b,c,d,e,f) a;b;c;d;e;f;
+#else
+#define BIT_FIELDS_2(a,b) b;a;
+#define BIT_FIELDS_4(a,b,c,d) d;c;b;a;
+#define BIT_FIELDS_6(a,b,c,d,e,f) f;e;d;c;b;a;
+#endif
+
+struct op_i_fmt
+{
+BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned immediate : 16)
+};
+
+struct op_j_fmt
+{
+BIT_FIELDS_2(
+ unsigned op : 6,
+ unsigned target : 26)
+};
+
+struct op_r_fmt
+{
+BIT_FIELDS_6(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned rd : 5,
+ unsigned shamt : 5,
+ unsigned funct : 6)
+};
+
+
+struct fop_i_fmt
+{
+BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned immediate : 16)
+};
+
+struct op_b_fmt
+{
+BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ short delta : 16)
+};
+
+struct fop_r_fmt
+{
+BIT_FIELDS_6(
+ unsigned op : 6,
+ unsigned fmt : 5,
+ unsigned ft : 5,
+ unsigned fs : 5,
+ unsigned fd : 5,
+ unsigned funct : 6)
+};
+
+struct mips_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long match;
+ char *args;
+ int bdelay; /* Nonzero if delayed branch. */
+};
+
+/* args format;
+
+ "s" rs: source register specifier
+ "t" rt: target register
+ "i" immediate
+ "a" target address
+ "c" branch condition
+ "d" rd: destination register specifier
+ "h" shamt: shift amount
+ "f" funct: function field
+
+ for fpu
+ "S" fs source 1 register
+ "T" ft source 2 register
+ "D" distination register
+*/
+
+#define one(x) (x << 26)
+#define op_func(x, y) ((x << 26) | y)
+#define op_cond(x, y) ((x << 26) | (y << 16))
+#define op_rs_func(x, y, z) ((x << 26) | (y << 21) | z)
+#define op_rs_b11(x, y, z) ((x << 26) | (y << 21) | z)
+#define op_o16(x, y) ((x << 26) | (y << 16))
+#define op_bc(x, y, z) ((x << 26) | (y << 21) | (z << 16))
+
+struct mips_opcode mips_opcodes[] =
+{
+/* These first opcodes are special cases of the ones in the comments */
+ {"nop", 0, 0xffffffff, /*li*/ "", 0},
+ {"li", op_bc(9,0,0), op_bc(0x3f,31,0), /*addiu*/ "t,j", 0},
+ {"b", one(4), 0xffff0000, /*beq*/ "b", 1},
+ {"move", op_func(0, 33), op_cond(0x3f,31)|0x7ff,/*addu*/ "d,s", 0},
+
+ {"sll", op_func(0, 0), op_func(0x3f, 0x3f), "d,t,h", 0},
+ {"srl", op_func(0, 2), op_func(0x3f, 0x3f), "d,t,h", 0},
+ {"sra", op_func(0, 3), op_func(0x3f, 0x3f), "d,t,h", 0},
+ {"sllv", op_func(0, 4), op_func(0x3f, 0x7ff), "d,t,s", 0},
+ {"srlv", op_func(0, 6), op_func(0x3f, 0x7ff), "d,t,s", 0},
+ {"srav", op_func(0, 7), op_func(0x3f, 0x7ff), "d,t,s", 0},
+ {"jr", op_func(0, 8), op_func(0x3f, 0x1fffff), "s", 1},
+ {"jalr", op_func(0, 9), op_func(0x3f, 0x1f07ff), "d,s", 1},
+ {"syscall", op_func(0, 12), op_func(0x3f, 0x3f), "", 0},
+ {"break", op_func(0, 13), op_func(0x3f, 0x3f), "", 0},
+ {"mfhi", op_func(0, 16), op_func(0x3f, 0x03ff07ff), "d", 0},
+ {"mthi", op_func(0, 17), op_func(0x3f, 0x1fffff), "s", 0},
+ {"mflo", op_func(0, 18), op_func(0x3f, 0x03ff07ff), "d", 0},
+ {"mtlo", op_func(0, 19), op_func(0x3f, 0x1fffff), "s", 0},
+ {"mult", op_func(0, 24), op_func(0x3f, 0xffff), "s,t", 0},
+ {"multu", op_func(0, 25), op_func(0x3f, 0xffff), "s,t", 0},
+ {"div", op_func(0, 26), op_func(0x3f, 0xffff), "s,t", 0},
+ {"divu", op_func(0, 27), op_func(0x3f, 0xffff), "s,t", 0},
+ {"add", op_func(0, 32), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"addu", op_func(0, 33), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"sub", op_func(0, 34), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"subu", op_func(0, 35), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"and", op_func(0, 36), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"or", op_func(0, 37), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"xor", op_func(0, 38), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"nor", op_func(0, 39), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"slt", op_func(0, 42), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"sltu", op_func(0, 43), op_func(0x3f, 0x7ff), "d,s,t", 0},
+
+ {"bltz", op_cond (1, 0), op_cond(0x3f, 0x1f), "s,b", 1},
+ {"bgez", op_cond (1, 1), op_cond(0x3f, 0x1f), "s,b", 1},
+ {"bltzal", op_cond (1, 16),op_cond(0x3f, 0x1f), "s,b", 1},
+ {"bgezal", op_cond (1, 17),op_cond(0x3f, 0x1f), "s,b", 1},
+
+
+ {"j", one(2), one(0x3f), "a", 1},
+ {"jal", one(3), one(0x3f), "a", 1},
+ {"beq", one(4), one(0x3f), "s,t,b", 1},
+ {"bne", one(5), one(0x3f), "s,t,b", 1},
+ {"blez", one(6), one(0x3f) | 0x1f0000, "s,b", 1},
+ {"bgtz", one(7), one(0x3f) | 0x1f0000, "s,b", 1},
+ {"addi", one(8), one(0x3f), "t,s,j", 0},
+ {"addiu", one(9), one(0x3f), "t,s,j", 0},
+ {"slti", one(10), one(0x3f), "t,s,j", 0},
+ {"sltiu", one(11), one(0x3f), "t,s,j", 0},
+ {"andi", one(12), one(0x3f), "t,s,i", 0},
+ {"ori", one(13), one(0x3f), "t,s,i", 0},
+ {"xori", one(14), one(0x3f), "t,s,i", 0},
+ /* rs field is don't care field? */
+ {"lui", one(15), one(0x3f), "t,i", 0},
+
+/* co processor 0 instruction */
+ {"mfc0", op_rs_b11 (16, 0, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"cfc0", op_rs_b11 (16, 2, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"mtc0", op_rs_b11 (16, 4, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"ctc0", op_rs_b11 (16, 6, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+
+ {"bc0f", op_o16(16, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc0f", op_o16(16, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc0t", op_o16(16, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc0t", op_o16(16, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+ {"tlbr", op_rs_func(16, 0x10, 1), ~0, "", 0},
+ {"tlbwi", op_rs_func(16, 0x10, 2), ~0, "", 0},
+ {"tlbwr", op_rs_func(16, 0x10, 6), ~0, "", 0},
+ {"tlbp", op_rs_func(16, 0x10, 8), ~0, "", 0},
+ {"rfe", op_rs_func(16, 0x10, 16), ~0, "", 0},
+
+ {"mfc1", op_rs_b11 (17, 0, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+ {"cfc1", op_rs_b11 (17, 2, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+ {"mtc1", op_rs_b11 (17, 4, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+ {"ctc1", op_rs_b11 (17, 6, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+
+ {"bc1f", op_o16(17, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc1f", op_o16(17, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc1t", op_o16(17, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc1t", op_o16(17, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+/* fpu instruction */
+ {"add.s", op_rs_func(17, 0x10, 0),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"add.d", op_rs_func(17, 0x11, 0),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"sub.s", op_rs_func(17, 0x10, 1),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"sub.d", op_rs_func(17, 0x11, 1),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"mul.s", op_rs_func(17, 0x10, 2),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"mul.d", op_rs_func(17, 0x11, 2),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"div.s", op_rs_func(17, 0x10, 3),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"div.d", op_rs_func(17, 0x11, 3),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"abs.s", op_rs_func(17, 0x10, 5),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"abs.d", op_rs_func(17, 0x11, 5),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"mov.s", op_rs_func(17, 0x10, 6),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"mov.d", op_rs_func(17, 0x11, 6),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"neg.s", op_rs_func(17, 0x10, 7),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"neg.d", op_rs_func(17, 0x11, 7),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.s.s", op_rs_func(17, 0x10, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.s.d", op_rs_func(17, 0x11, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.s.w", op_rs_func(17, 0x14, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.d.s", op_rs_func(17, 0x10, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.d.d", op_rs_func(17, 0x11, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.d.w", op_rs_func(17, 0x14, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.w.s", op_rs_func(17, 0x10, 36),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.w.d", op_rs_func(17, 0x11, 36),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"c.f.s", op_rs_func(17, 0x10, 48),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.f.d", op_rs_func(17, 0x11, 48),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.un.s", op_rs_func(17, 0x10, 49),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.un.d", op_rs_func(17, 0x11, 49),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.eq.s", op_rs_func(17, 0x10, 50),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.eq.d", op_rs_func(17, 0x11, 50),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ueq.s", op_rs_func(17, 0x10, 51),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ueq.d", op_rs_func(17, 0x11, 51),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.olt.s", op_rs_func(17, 0x10, 52),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.olt.d", op_rs_func(17, 0x11, 52),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ult.s", op_rs_func(17, 0x10, 53),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ult.d", op_rs_func(17, 0x11, 53),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ole.s", op_rs_func(17, 0x10, 54),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ole.d", op_rs_func(17, 0x11, 54),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ule.s", op_rs_func(17, 0x10, 55),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ule.d", op_rs_func(17, 0x11, 55),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.sf.s", op_rs_func(17, 0x10, 56),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.sf.d", op_rs_func(17, 0x11, 56),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngle.s", op_rs_func(17, 0x10, 57),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngle.d", op_rs_func(17, 0x11, 57),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.seq.s", op_rs_func(17, 0x10, 58),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.seq.d", op_rs_func(17, 0x11, 58),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngl.s", op_rs_func(17, 0x10, 59),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngl.d", op_rs_func(17, 0x11, 59),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.lt.s", op_rs_func(17, 0x10, 60),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.lt.d", op_rs_func(17, 0x11, 60),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.nge.s", op_rs_func(17, 0x10, 61),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.nge.d", op_rs_func(17, 0x11, 61),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.le.s", op_rs_func(17, 0x10, 62),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.le.d", op_rs_func(17, 0x11, 62),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngt.s", op_rs_func(17, 0x10, 63),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngt.d", op_rs_func(17, 0x11, 63),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+
+/* co processor 2 instruction */
+ {"mfc2", op_rs_b11 (18, 0, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"cfc2", op_rs_b11 (18, 2, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"mtc2", op_rs_b11 (18, 4, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"ctc2", op_rs_b11 (18, 6, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"bc2f", op_o16(18, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc2f", op_o16(18, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc2f", op_o16(18, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc2t", op_o16(18, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+/* co processor 3 instruction */
+ {"mtc3", op_rs_b11 (19, 0, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"cfc3", op_rs_b11 (19, 2, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"mtc3", op_rs_b11 (19, 4, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"ctc3", op_rs_b11 (19, 6, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"bc3f", op_o16(19, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc3f", op_o16(19, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc3t", op_o16(19, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc3t", op_o16(19, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+ {"lb", one(32), one(0x3f), "t,j(s)", 0},
+ {"lh", one(33), one(0x3f), "t,j(s)", 0},
+ {"lwl", one(34), one(0x3f), "t,j(s)", 0},
+ {"lw", one(35), one(0x3f), "t,j(s)", 0},
+ {"lbu", one(36), one(0x3f), "t,j(s)", 0},
+ {"lhu", one(37), one(0x3f), "t,j(s)", 0},
+ {"lwr", one(38), one(0x3f), "t,j(s)", 0},
+ {"sb", one(40), one(0x3f), "t,j(s)", 0},
+ {"sh", one(41), one(0x3f), "t,j(s)", 0},
+ {"swl", one(42), one(0x3f), "t,j(s)", 0},
+ {"swr", one(46), one(0x3f), "t,j(s)", 0},
+ {"sw", one(43), one(0x3f), "t,j(s)", 0},
+ {"lwc0", one(48), one(0x3f), "t,j(s)", 0},
+/* for fpu */
+ {"lwc1", one(49), one(0x3f), "T,j(s)", 0},
+ {"lwc2", one(50), one(0x3f), "t,j(s)", 0},
+ {"lwc3", one(51), one(0x3f), "t,j(s)", 0},
+ {"swc0", one(56), one(0x3f), "t,j(s)", 0},
+/* for fpu */
+ {"swc1", one(57), one(0x3f), "T,j(s)", 0},
+ {"swc2", one(58), one(0x3f), "t,j(s)", 0},
+ {"swc3", one(59), one(0x3f), "t,j(s)", 0},
+};
--- /dev/null
+/* Print mips instructions for GDB, the GNU debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp)
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "mips-opcode.h"
+
+/* Mips instructions are never longer than this many bytes. */
+#define MAXLEN 4
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof mips_opcodes / sizeof mips_opcodes[0])
+
+#define MKLONG(p) *(unsigned long*)p
+
+extern char *reg_names[];
+
+\f
+/* subroutine */
+static unsigned char *
+print_insn_arg (d, l, stream, pc)
+ char *d;
+ register unsigned long int *l;
+ FILE *stream;
+ CORE_ADDR pc;
+{
+ switch (*d)
+ {
+ case ',':
+ case '(':
+ case ')':
+ fputc (*d, stream);
+ break;
+
+ case 's':
+ fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rs]);
+ break;
+
+ case 't':
+ fprintf (stream, "$%s", reg_names[((struct op_i_fmt *) l)->rt]);
+ break;
+
+ case 'i':
+ fprintf (stream, "%d", ((struct op_i_fmt *) l)->immediate);
+ break;
+
+ case 'j': /* same as i, but sign-extended */
+ fprintf (stream, "%d", ((struct op_b_fmt *) l)->delta);
+ break;
+
+ case 'a':
+ print_address ((pc & 0xF0000000) | (((struct op_j_fmt *)l)->target << 2),
+ stream);
+ break;
+
+ case 'b':
+ print_address ((((struct op_b_fmt *) l)->delta << 2) + pc + 4, stream);
+ break;
+
+ case 'd':
+ fprintf (stream, "%s", reg_names[((struct op_r_fmt *) l)->rd]);
+ break;
+
+ case 'h':
+ fprintf (stream, "0x%x", ((struct op_r_fmt *) l)->shamt);
+ break;
+
+ case 'S':
+ fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fs);
+ break;
+
+ case 'T':
+ fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->ft);
+ break;
+
+ case 'D':
+ fprintf (stream, "$f%d", ((struct fop_r_fmt *) l)->fd);
+ break;
+
+ default:
+ fprintf (stream, "# internal error, undefined modifier(%c)", *d);
+ break;
+ }
+}
+\f
+/* Print the mips instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes, which
+ is always 4. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register char *d;
+ unsigned long int l;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ for (i = 0; i < NOPCODES; i++)
+ {
+ register unsigned int opcode = mips_opcodes[i].opcode;
+ register unsigned int match = mips_opcodes[i].match;
+ if ((*(unsigned int*)buffer & match) == opcode)
+ break;
+ }
+
+ l = MKLONG (buffer);
+ /* Handle undefined instructions. */
+ if (i == NOPCODES)
+ {
+ fprintf (stream, "0x%x",l);
+ return 4;
+ }
+
+ fprintf (stream, "%s", mips_opcodes[i].name);
+
+ if (!(d = mips_opcodes[i].args))
+ return 4;
+
+ fputc (' ', stream);
+
+ while (*d)
+ print_insn_arg (d++, &l, stream, memaddr);
+
+ return 4;
+}
--- /dev/null
+/* Low level MIPS interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+ Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+ and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <mips/inst.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h> Can we live without this? */
+
+#include "gdbcore.h"
+
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* Get all registers from the inferior */
+
+void
+fetch_inferior_registers ()
+{
+ register int regno;
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ registers_fetched ();
+
+ for (regno = 1; regno < NUM_REGS; regno++)
+ {
+ regaddr = register_addr (regno, 1);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ if (regno == 0)
+ return;
+
+ if (regno > 0)
+ {
+ regaddr = register_addr (regno, 1);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+ {
+ for (regno = 1; regno < NUM_REGS; regno++)
+ {
+ if (regno == 32 || regno == 35 || regno == 36 || regno == 71)
+ continue;
+ regaddr = register_addr (regno, 1);
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ }
+}
+
+void
+fetch_core_registers ()
+{
+ register int regno;
+ int val;
+
+ for (regno = 1; regno < NUM_REGS; regno++) {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = bfd_seek (core_bfd, register_addr (regno, 0));
+ if (val < 0 || (val = bfd_read (core_bfd, buf, sizeof buf)) < 0) {
+ char buffer[50];
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+ supply_register (regno, buf);
+ }
+}
--- /dev/null
+#!/bin/sh
+
+# create an initialization procedure from a list of .o files
+
+echo '/* Do not modify this file. It is created automatically by "munch". */'
+echo 'void initialize_all_files () {'
+
+# make it easy to use a different nm, e.g. for cross-developing
+MUNCH_NM=${MUNCH_NM-nm}
+if test "`$MUNCH_NM main.o | egrep 'T _?main$'`" = "" ; then
+ # System V style nm
+ shift;
+ $MUNCH_NM $* | egrep '^(.*[^a-zA-Z_]_|_)_?initialize_.*\.text' | \
+ sed -e 's/^.*\(_initialize_[a-zA-Z0-9_]*\)[^a-zA-Z0-9_].*$/ {extern void \1 (); \1 ();}/'
+else
+ # BSD style nm
+ $MUNCH_NM -p $* | egrep 'T *_?_initialize_' | \
+ sed -e 's/^.*T *_*\(.*\)/ {extern void _\1 (); _\1 ();}/'
+fi
+
+echo '}'
--- /dev/null
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef __GNUC__
+/* Bad implement execle(3). It's depend for "/bin/cc".
+
+ main()
+ {
+ printf("execle:\n");
+ execle(FILE, ARGS, envp);
+ exit(1);
+ }
+
+ GCC:
+ link a6,#0
+ pea LC5 ; call printf
+ jbsr _printf
+ ; ; (not popd stack)
+ pea _envp ; call execle
+ clrl sp@-
+ pea LC4
+ pea LC4
+ pea LC4
+ pea LC3
+ pea LC6
+ jbsr _execle
+ addw #32,sp ; delayed pop !!
+
+ /bin/cc:
+ link.l fp,#L23
+ movem.l #L24,(sp)
+ pea L26 ; call printf
+ jbsr _printf
+ addq.l #4,sp ; <--- popd stack !!
+ pea _envp ; call execle
+ clr.l -(sp)
+ pea L32
+
+ */
+
+execle(name, args)
+ char *name, *args;
+{
+ register char **env = &args;
+ while (*env++)
+ ;
+ execve(name, (char **)&args, (char **)*env);
+}
+#endif
--- /dev/null
+/* Target-machine dependent code for the NINDY monitor running on the Intel 960
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Miscellaneous NINDY-dependent routines.
+ Some replace macros normally defined in "tm.h". */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "frame.h"
+
+/* 'start_frame' is a variable in the NINDY runtime startup routine
+ that contains the frame pointer of the 'start' routine (the routine
+ that calls 'main'). By reading its contents out of remote memory,
+ we can tell where the frame chain ends: backtraces should halt before
+ they display this frame. */
+
+int
+nindy_frame_chain_valid (chain, curframe)
+ unsigned int chain;
+ FRAME curframe;
+{
+ struct symbol *sym;
+ int i;
+
+ /* crtnindy.o is an assembler module that is assumed to be linked
+ * first in an i80960 executable. It contains the true entry point;
+ * it performs startup up initialization and then calls 'main'.
+ *
+ * 'sf' is the name of a variable in crtnindy.o that is set
+ * during startup to the address of the first frame.
+ *
+ * 'a' is the address of that variable in 80960 memory.
+ */
+ static char sf[] = "start_frame";
+ CORE_ADDR a;
+
+
+ chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
+ contain return status info in them. */
+ if ( chain == 0 ){
+ return 0;
+ }
+
+ sym = lookup_symbol(sf, 0, VAR_NAMESPACE, (int *)NULL,
+ (struct symtab **)NULL);
+ if ( sym != 0 ){
+ a = sym->value.value;
+ } else {
+ for ( i = 0; strcmp(misc_function_vector[i].name,sf); i++ ){
+ if ( i >= misc_function_count ){
+ return 0;
+ }
+ }
+ a = misc_function_vector[i].address;
+ }
+
+ return ( chain != read_memory_integer(a,4) );
+}
--- /dev/null
+/* Print GOULD NPL instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct gld_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long mask;
+ char *args;
+ int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and at most four. The length of the
+ instruction is based on the opcode.
+
+ The mask component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing characters
+ that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+ r Register in first field
+ R Register in second field
+ b Base register in first field
+ B Base register in second field
+ v Vector register in first field
+ V Vector register in first field
+ A Optional address register (base register)
+ X Optional index register
+ I Immediate data (16bits signed)
+ O Offset field (16bits signed)
+ h Offset field (15bits signed)
+ d Offset field (14bits signed)
+ S Shift count field
+
+ any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "lb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lbs", 0xec080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lnh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ld", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lnd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "li", 0xf8000000, 0xfc7f0000, "r,I", 4 },
+{ "lpa", 0x50080000, 0xfc080000, "r,xOA,X", 4 },
+{ "la", 0x50000000, 0xfc080000, "r,xOA,X", 4 },
+{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lbp", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lhp", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lwp", 0x90000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ldp", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
+{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
+{ "lf", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lfbr", 0xbc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
+{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stfbr", 0xdc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "zmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "zmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stbp", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sthp", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stwp", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stdp", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lil", 0xf80b0000, 0xfc7f0000, "r,D", 4 },
+{ "lwsl1", 0xec000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwsl2", 0xfc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwsl3", 0xfc080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "lvb", 0xb0080000, 0xfc080000, "v,xOA,X", 4 },
+{ "lvh", 0xb0000001, 0xfc080001, "v,xOA,X", 4 },
+{ "lvw", 0xb0000000, 0xfc080000, "v,xOA,X", 4 },
+{ "lvd", 0xb0000002, 0xfc080002, "v,xOA,X", 4 },
+{ "liv", 0x3c040000, 0xfc0f0000, "v,R", 2 },
+{ "livf", 0x3c080000, 0xfc0f0000, "v,R", 2 },
+{ "stvb", 0xd0080000, 0xfc080000, "v,xOA,X", 4 },
+{ "stvh", 0xd0000001, 0xfc080001, "v,xOA,X", 4 },
+{ "stvw", 0xd0000000, 0xfc080000, "v,xOA,X", 4 },
+{ "stvd", 0xd0000002, 0xfc080002, "v,xOA,X", 4 },
+
+{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
+{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
+{ "trnd", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
+{ "trabs", 0x2c010000, 0xfc0f0000, "r,R", 2 },
+{ "trabsd", 0x2c090000, 0xfc0f0000, "r,R", 2 },
+{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
+{ "xcr", 0x28040000, 0xfc0f0000, "r,R", 2 },
+{ "cxcr", 0x2c060000, 0xfc0f0000, "r,R", 2 },
+{ "cxcrd", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
+{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
+{ "trbr", 0x28030000, 0xfc0f0000, "b,R", 2 },
+{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
+{ "tbrbr", 0x28010000, 0xfc0f0000, "b,B", 2 },
+
+{ "trvv", 0x28050000, 0xfc0f0000, "v,V", 2 },
+{ "trvvn", 0x2c050000, 0xfc0f0000, "v,V", 2 },
+{ "trvvnd", 0x2c0d0000, 0xfc0f0000, "v,V", 2 },
+{ "trvab", 0x2c070000, 0xfc0f0000, "v,V", 2 },
+{ "trvabd", 0x2c0f0000, 0xfc0f0000, "v,V", 2 },
+{ "cmpv", 0x14060000, 0xfc0f0000, "v,V", 2 },
+{ "expv", 0x14070000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvlt", 0x10030000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvle", 0x10040000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvgt", 0x14030000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvge", 0x14040000, 0xfc0f0000, "v,V", 2 },
+{ "mrvveq", 0x10050000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvne", 0x10050000, 0xfc0f0000, "v,V", 2 },
+{ "mrvrlt", 0x100d0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrle", 0x100e0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrgt", 0x140d0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrge", 0x140e0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvreq", 0x100f0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrne", 0x140f0000, 0xfc0f0000, "v,R", 2 },
+{ "trvr", 0x140b0000, 0xfc0f0000, "r,V", 2 },
+{ "trrv", 0x140c0000, 0xfc0f0000, "v,R", 2 },
+
+{ "bu", 0x40000000, 0xff880000, "xOA,X", 4 },
+{ "bns", 0x70080000, 0xff880000, "xOA,X", 4 },
+{ "bnco", 0x70880000, 0xff880000, "xOA,X", 4 },
+{ "bge", 0x71080000, 0xff880000, "xOA,X", 4 },
+{ "bne", 0x71880000, 0xff880000, "xOA,X", 4 },
+{ "bunge", 0x72080000, 0xff880000, "xOA,X", 4 },
+{ "bunle", 0x72880000, 0xff880000, "xOA,X", 4 },
+{ "bgt", 0x73080000, 0xff880000, "xOA,X", 4 },
+{ "bnany", 0x73880000, 0xff880000, "xOA,X", 4 },
+{ "bs" , 0x70000000, 0xff880000, "xOA,X", 4 },
+{ "bco", 0x70800000, 0xff880000, "xOA,X", 4 },
+{ "blt", 0x71000000, 0xff880000, "xOA,X", 4 },
+{ "beq", 0x71800000, 0xff880000, "xOA,X", 4 },
+{ "buge", 0x72000000, 0xff880000, "xOA,X", 4 },
+{ "bult", 0x72800000, 0xff880000, "xOA,X", 4 },
+{ "ble", 0x73000000, 0xff880000, "xOA,X", 4 },
+{ "bany", 0x73800000, 0xff880000, "xOA,X", 4 },
+{ "brlnk", 0x44000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bib", 0x48000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bih", 0x48080000, 0xfc080000, "r,xOA,X", 4 },
+{ "biw", 0x4c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bid", 0x4c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivb", 0x60000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivh", 0x60080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivw", 0x64000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivd", 0x64080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsb", 0x68000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsh", 0x68080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsw", 0x6c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsd", 0x6c080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "camb", 0x80080000, 0xfc080000, "r,xOA,X", 4 },
+{ "camh", 0x80000001, 0xfc080001, "r,xOA,X", 4 },
+{ "camw", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
+{ "camd", 0x80000002, 0xfc080002, "r,xOA,X", 4 },
+{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
+{ "card", 0x14000000, 0xfc0f0000, "r,R", 2 },
+{ "ci", 0xf8050000, 0xfc7f0000, "r,I", 4 },
+{ "chkbnd", 0x5c080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "cavv", 0x10010000, 0xfc0f0000, "v,V", 2 },
+{ "cavr", 0x10020000, 0xfc0f0000, "v,R", 2 },
+{ "cavvd", 0x10090000, 0xfc0f0000, "v,V", 2 },
+{ "cavrd", 0x100b0000, 0xfc0f0000, "v,R", 2 },
+
+{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
+{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
+{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
+{ "ani", 0xf8080000, 0xfc7f0000, "r,I", 4 },
+{ "ormb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "ormw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
+{ "oi", 0xf8090000, 0xfc7f0000, "r,I", 4 },
+{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
+{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
+{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
+{ "eoi", 0xf80a0000, 0xfc7f0000, "r,I", 4 },
+
+{ "anvv", 0x04010000, 0xfc0f0000, "v,V", 2 },
+{ "anvr", 0x04020000, 0xfc0f0000, "v,R", 2 },
+{ "orvv", 0x08010000, 0xfc0f0000, "v,V", 2 },
+{ "orvr", 0x08020000, 0xfc0f0000, "v,R", 2 },
+{ "eovv", 0x0c010000, 0xfc0f0000, "v,V", 2 },
+{ "eovr", 0x0c020000, 0xfc0f0000, "v,R", 2 },
+
+{ "sacz", 0x100c0000, 0xfc0f0000, "r,R", 2 },
+{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
+{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
+{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
+{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
+{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
+{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
+{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
+{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
+{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
+{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
+{ "sda", 0x3c030000, 0xfc0f0000, "r,R", 2 },
+{ "sdl", 0x3c020000, 0xfc0f0000, "r,R", 2 },
+{ "sdc", 0x3c010000, 0xfc0f0000, "r,R", 2 },
+{ "sdad", 0x3c0b0000, 0xfc0f0000, "r,R", 2 },
+{ "sdld", 0x3c0a0000, 0xfc0f0000, "r,R", 2 },
+
+{ "svda", 0x3c070000, 0xfc0f0000, "v,R", 2 },
+{ "svdl", 0x3c060000, 0xfc0f0000, "v,R", 2 },
+{ "svdc", 0x3c050000, 0xfc0f0000, "v,R", 2 },
+{ "svdad", 0x3c0e0000, 0xfc0f0000, "v,R", 2 },
+{ "svdld", 0x3c0d0000, 0xfc0f0000, "v,R", 2 },
+
+{ "sbm", 0xac080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zbm", 0xac000000, 0xfc080000, "f,xOA,X", 4 },
+{ "tbm", 0xa8080000, 0xfc080000, "f,xOA,X", 4 },
+{ "incmb", 0xa0000000, 0xfc080000, "xOA,X", 4 },
+{ "incmh", 0xa0080000, 0xfc080000, "xOA,X", 4 },
+{ "incmw", 0xa4000000, 0xfc080000, "xOA,X", 4 },
+{ "incmd", 0xa4080000, 0xfc080000, "xOA,X", 4 },
+{ "sbmd", 0x7c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zbmd", 0x7c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "tbmd", 0x78080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "ssm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zsm", 0x9c000000, 0xfc080000, "f,xOA,X", 4 },
+{ "tsm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
+
+{ "admb", 0xc8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "admh", 0xc8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "admw", 0xc8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "admd", 0xc8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
+{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "adi", 0xf8010000, 0xfc0f0000, "r,I", 4 },
+{ "sumb", 0xcc080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumh", 0xcc000001, 0xfc080001, "r,xOA,X", 4 },
+{ "sumw", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumd", 0xcc000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
+{ "sui", 0xf8020000, 0xfc0f0000, "r,I", 4 },
+{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
+{ "mprd", 0x3c0f0000, 0xfc0f0000, "r,R", 2 },
+{ "mpi", 0xf8030000, 0xfc0f0000, "r,I", 4 },
+{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
+{ "dvi", 0xf8040000, 0xfc0f0000, "r,I", 4 },
+{ "exs", 0x38080000, 0xfc0f0000, "r,R", 2 },
+
+{ "advv", 0x30000000, 0xfc0f0000, "v,V", 2 },
+{ "advvd", 0x30080000, 0xfc0f0000, "v,V", 2 },
+{ "adrv", 0x34000000, 0xfc0f0000, "v,R", 2 },
+{ "adrvd", 0x34080000, 0xfc0f0000, "v,R", 2 },
+{ "suvv", 0x30010000, 0xfc0f0000, "v,V", 2 },
+{ "suvvd", 0x30090000, 0xfc0f0000, "v,V", 2 },
+{ "surv", 0x34010000, 0xfc0f0000, "v,R", 2 },
+{ "survd", 0x34090000, 0xfc0f0000, "v,R", 2 },
+{ "mpvv", 0x30020000, 0xfc0f0000, "v,V", 2 },
+{ "mprv", 0x34020000, 0xfc0f0000, "v,R", 2 },
+
+{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
+{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
+{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
+{ "surfw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "surfd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
+{ "surfd", 0x380b0000, 0xfc0f0000, "r,R", 2 },
+{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
+{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
+{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
+{ "rfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "rfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "rrfw", 0x0c0e0000, 0xfc0f0000, "r", 2 },
+{ "rrfd", 0x0c0f0000, 0xfc0f0000, "r", 2 },
+
+{ "advvfw", 0x30040000, 0xfc0f0000, "v,V", 2 },
+{ "advvfd", 0x300c0000, 0xfc0f0000, "v,V", 2 },
+{ "adrvfw", 0x34040000, 0xfc0f0000, "v,R", 2 },
+{ "adrvfd", 0x340c0000, 0xfc0f0000, "v,R", 2 },
+{ "suvvfw", 0x30050000, 0xfc0f0000, "v,V", 2 },
+{ "suvvfd", 0x300d0000, 0xfc0f0000, "v,V", 2 },
+{ "survfw", 0x34050000, 0xfc0f0000, "v,R", 2 },
+{ "survfd", 0x340d0000, 0xfc0f0000, "v,R", 2 },
+{ "mpvvfw", 0x30060000, 0xfc0f0000, "v,V", 2 },
+{ "mpvvfd", 0x300e0000, 0xfc0f0000, "v,V", 2 },
+{ "mprvfw", 0x34060000, 0xfc0f0000, "v,R", 2 },
+{ "mprvfd", 0x340e0000, 0xfc0f0000, "v,R", 2 },
+{ "rvfw", 0x30070000, 0xfc0f0000, "v", 2 },
+{ "rvfd", 0x300f0000, 0xfc0f0000, "v", 2 },
+
+{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
+{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
+{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
+{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
+{ "cfpds", 0x3c090000, 0xfc0f0000, "r,R", 2 },
+
+{ "fltvw", 0x080d0000, 0xfc0f0000, "v,V", 2 },
+{ "fltvd", 0x080f0000, 0xfc0f0000, "v,V", 2 },
+{ "fixvw", 0x080c0000, 0xfc0f0000, "v,V", 2 },
+{ "fixvd", 0x080e0000, 0xfc0f0000, "v,V", 2 },
+{ "cfpvds", 0x0c0d0000, 0xfc0f0000, "v,V", 2 },
+
+{ "orvrn", 0x000a0000, 0xfc0f0000, "r,V", 2 },
+{ "andvrn", 0x00080000, 0xfc0f0000, "r,V", 2 },
+{ "frsteq", 0x04090000, 0xfc0f0000, "r,V", 2 },
+{ "sigma", 0x0c080000, 0xfc0f0000, "r,V", 2 },
+{ "sigmad", 0x0c0a0000, 0xfc0f0000, "r,V", 2 },
+{ "sigmf", 0x08080000, 0xfc0f0000, "r,V", 2 },
+{ "sigmfd", 0x080a0000, 0xfc0f0000, "r,V", 2 },
+{ "prodf", 0x04080000, 0xfc0f0000, "r,V", 2 },
+{ "prodfd", 0x040a0000, 0xfc0f0000, "r,V", 2 },
+{ "maxv", 0x10080000, 0xfc0f0000, "r,V", 2 },
+{ "maxvd", 0x100a0000, 0xfc0f0000, "r,V", 2 },
+{ "minv", 0x14080000, 0xfc0f0000, "r,V", 2 },
+{ "minvd", 0x140a0000, 0xfc0f0000, "r,V", 2 },
+
+{ "lpsd", 0xf0000000, 0xfc080000, "xOA,X", 4 },
+{ "ldc", 0xf0080000, 0xfc080000, "xOA,X", 4 },
+{ "spm", 0x040c0000, 0xfc0f0000, "r", 2 },
+{ "rpm", 0x040d0000, 0xfc0f0000, "r", 2 },
+{ "tritr", 0x00070000, 0xfc0f0000, "r", 2 },
+{ "trrit", 0x00060000, 0xfc0f0000, "r", 2 },
+{ "rpswt", 0x04080000, 0xfc0f0000, "r", 2 },
+{ "exr", 0xf8070000, 0xfc0f0000, "", 4 },
+{ "halt", 0x00000000, 0xfc0f0000, "", 2 },
+{ "wait", 0x00010000, 0xfc0f0000, "", 2 },
+{ "nop", 0x00020000, 0xfc0f0000, "", 2 },
+{ "eiae", 0x00030000, 0xfc0f0000, "", 2 },
+{ "efae", 0x000d0000, 0xfc0f0000, "", 2 },
+{ "diae", 0x000e0000, 0xfc0f0000, "", 2 },
+{ "dfae", 0x000f0000, 0xfc0f0000, "", 2 },
+{ "spvc", 0xf8060000, 0xfc0f0000, "r,T,N", 4 },
+{ "rdsts", 0x00090000, 0xfc0f0000, "r", 2 },
+{ "setcpu", 0x000c0000, 0xfc0f0000, "r", 2 },
+{ "cmc", 0x000b0000, 0xfc0f0000, "r", 2 },
+{ "trrcu", 0x00040000, 0xfc0f0000, "r", 2 },
+{ "attnio", 0x00050000, 0xfc0f0000, "", 2 },
+{ "fudit", 0x28080000, 0xfc0f0000, "", 2 },
+{ "break", 0x28090000, 0xfc0f0000, "", 2 },
+{ "frzss", 0x280a0000, 0xfc0f0000, "", 2 },
+{ "ripi", 0x04040000, 0xfc0f0000, "r,R", 2 },
+{ "xcp", 0x04050000, 0xfc0f0000, "r", 2 },
+{ "block", 0x04060000, 0xfc0f0000, "", 2 },
+{ "unblock", 0x04070000, 0xfc0f0000, "", 2 },
+{ "trsc", 0x08060000, 0xfc0f0000, "r,R", 2 },
+{ "tscr", 0x08070000, 0xfc0f0000, "r,R", 2 },
+{ "fq", 0x04080000, 0xfc0f0000, "r", 2 },
+{ "flupte", 0x2c080000, 0xfc0f0000, "r", 2 },
+{ "rviu", 0x040f0000, 0xfc0f0000, "", 2 },
+{ "ldel", 0x280c0000, 0xfc0f0000, "r,R", 2 },
+{ "ldu", 0x280d0000, 0xfc0f0000, "r,R", 2 },
+{ "stdecc", 0x280b0000, 0xfc0f0000, "r,R", 2 },
+{ "trpc", 0x08040000, 0xfc0f0000, "r", 2 },
+{ "tpcr", 0x08050000, 0xfc0f0000, "r", 2 },
+{ "ghalt", 0x0c050000, 0xfc0f0000, "r", 2 },
+{ "grun", 0x0c040000, 0xfc0f0000, "", 2 },
+{ "tmpr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
+{ "trmp", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
+
+{ "trrve", 0x28060000, 0xfc0f0000, "r", 2 },
+{ "trver", 0x28070000, 0xfc0f0000, "r", 2 },
+{ "trvlr", 0x280f0000, 0xfc0f0000, "r", 2 },
+
+{ "linkfl", 0x18000000, 0xfc0f0000, "r,R", 2 },
+{ "linkbl", 0x18020000, 0xfc0f0000, "r,R", 2 },
+{ "linkfp", 0x18010000, 0xfc0f0000, "r,R", 2 },
+{ "linkbp", 0x18030000, 0xfc0f0000, "r,R", 2 },
+{ "linkpl", 0x18040000, 0xfc0f0000, "r,R", 2 },
+{ "ulinkl", 0x18080000, 0xfc0f0000, "r,R", 2 },
+{ "ulinkp", 0x18090000, 0xfc0f0000, "r,R", 2 },
+{ "ulinktl", 0x180a0000, 0xfc0f0000, "r,R", 2 },
+{ "ulinktp", 0x180b0000, 0xfc0f0000, "r,R", 2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+ sizeof(gld_opcodes[0]);
--- /dev/null
+/* ns32k-opcode.h */
+
+#ifndef ns32k_opcodeT
+#define ns32k_opcodeT int
+#endif /* no ns32k_opcodeT */
+
+struct not_wot /* ns32k opcode table: wot to do with this */
+ /* particular opcode */
+{
+ int obits; /* number of opcode bits */
+ int ibits; /* number of instruction bits */
+ ns32k_opcodeT code; /* op-code (may be > 8 bits!) */
+ char *args; /* how to compile said opcode */
+};
+
+struct not /* ns32k opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct not_wot detail; /* rest of opcode table [datum] */
+};
+
+/* Instructions look like this:
+
+ basic instruction--1, 2, or 3 bytes
+ index byte for operand A, if operand A is indexed--1 byte
+ index byte for operand B, if operand B is indexed--1 byte
+ addressing extension for operand A
+ addressing extension for operand B
+ implied operands
+
+ Operand A is the operand listed first in the following opcode table.
+ Operand B is the operand listed second in the following opcode table.
+ All instructions have at most 2 general operands, so this is enough.
+ The implied operands are associated with operands other than A and B.
+
+ Each operand has a digit and a letter.
+
+ The digit gives the position in the assembly language. The letter,
+ one of the following, tells us what kind of operand it is. */
+
+/* F : 32 bit float
+ * L : 64 bit float
+ * B : byte
+ * W : word
+ * D : double-word
+ * Q : quad-word
+ * d : displacement
+ * q : quick
+ * i : immediate (8 bits)
+ * r : register number (3 bits)
+ * p : displacement - pc relative addressing
+*/
+static struct not
+notstrs[] =
+{
+ { "absf", 14,24, 0x35be, "1F2F" },
+ { "absl", 14,24, 0x34be, "1L2L" },
+ { "absb", 14,24, 0x304e, "1B2B" },
+ { "absw", 14,24, 0x314e, "1W2W" },
+ { "absd", 14,24, 0x334e, "1D2D" },
+ { "acbb", 7,16, 0x4c, "2B1q3p" },
+ { "acbw", 7,16, 0x4d, "2W1q3p" },
+ { "acbd", 7,16, 0x4f, "2D1q3p" },
+ { "addf", 14,24, 0x01be, "1F2F" },
+ { "addl", 14,24, 0x00be, "1L2L" },
+ { "addb", 6,16, 0x00, "1B2B" },
+ { "addw", 6,16, 0x01, "1W2W" },
+ { "addd", 6,16, 0x03, "1D2D" },
+ { "addcb", 6,16, 0x10, "1B2B" },
+ { "addcw", 6,16, 0x11, "1W2W" },
+ { "addcd", 6,16, 0x13, "1D2D" },
+ { "addpb", 14,24, 0x3c4e, "1B2B" },
+ { "addpw", 14,24, 0x3d4e, "1W2W" },
+ { "addpd", 14,24, 0x3f4e, "1D2D" },
+ { "addqb", 7,16, 0x0c, "2B1q" },
+ { "addqw", 7,16, 0x0d, "2W1q" },
+ { "addqd", 7,16, 0x0f, "2D1q" },
+ { "addr", 6,16, 0x27, "1D2D" },
+ { "adjspb", 11,16, 0x057c, "1B" },
+ { "adjspw", 11,16, 0x057d, "1W" },
+ { "adjspd", 11,16, 0x057f, "1D" },
+ { "andb", 6,16, 0x28, "1B2B" },
+ { "andw", 6,16, 0x29, "1W2W" },
+ { "andd", 6,16, 0x2b, "1D2D" },
+ { "ashb", 14,24, 0x044e, "1B2B" },
+ { "ashw", 14,24, 0x054e, "1B2W" },
+ { "ashd", 14,24, 0x074e, "1B2D" },
+ { "beq", 8,8, 0x0a, "1p" },
+ { "bne", 8,8, 0x1a, "1p" },
+ { "bcs", 8,8, 0x2a, "1p" },
+ { "bcc", 8,8, 0x3a, "1p" },
+ { "bhi", 8,8, 0x4a, "1p" },
+ { "bls", 8,8, 0x5a, "1p" },
+ { "bgt", 8,8, 0x6a, "1p" },
+ { "ble", 8,8, 0x7a, "1p" },
+ { "bfs", 8,8, 0x8a, "1p" },
+ { "bfc", 8,8, 0x9a, "1p" },
+ { "blo", 8,8, 0xaa, "1p" },
+ { "bhs", 8,8, 0xba, "1p" },
+ { "blt", 8,8, 0xca, "1p" },
+ { "bge", 8,8, 0xda, "1p" },
+ { "bicb", 6,16, 0x08, "1B2B" },
+ { "bicw", 6,16, 0x09, "1W2W" },
+ { "bicd", 6,16, 0x0b, "1D2D" },
+ { "bicpsrb", 11,16, 0x17c, "1B" },
+ { "bicpsrw", 11,16, 0x17d, "1W" },
+ { "bispsrb", 11,16, 0x37c, "1B" },
+ { "bispsrw", 11,16, 0x37d, "1W" },
+ { "bpt", 8,8, 0xf2, "" },
+ { "br", 8,8, 0xea, "1p" },
+ { "bsr", 8,8, 0x02, "1p" },
+ { "caseb", 11,16, 0x77c, "1B" },
+ { "casew", 11,16, 0x77d, "1W" },
+ { "cased", 11,16, 0x77f, "1D" },
+ { "cbitb", 14,24, 0x084e, "1B2D" },
+ { "cbitw", 14,24, 0x094e, "1W2D" },
+ { "cbitd", 14,24, 0x0b4e, "1D2D" },
+ { "cbitib", 14,24, 0x0c4e, "1B2D" },
+ { "cbitiw", 14,24, 0x0d4e, "1W2D" },
+ { "cbitid", 14,24, 0x0f4e, "1D2D" },
+ { "checkb", 11,24, 0x0ee, "2A3B1r" },
+ { "checkw", 11,24, 0x1ee, "2A3B1r" },
+ { "checkd", 11,24, 0x3ee, "2A3D1r" },
+ { "cmpf", 14,24, 0x09be, "1F2F" },
+ { "cmpl", 14,24, 0x08be, "1L2L" },
+ { "cmpb", 6,16, 0x04, "1B2B" },
+ { "cmpw", 6,16, 0x05, "1W2W" },
+ { "cmpd", 6,16, 0x07, "1D2D" },
+ { "cmpmb", 14,24, 0x04ce, "1D2D3d" },
+ { "cmpmw", 14,24, 0x05ce, "1D2D3d" },
+ { "cmpmd", 14,24, 0x07ce, "1D2D3d" },
+ { "cmpqb", 7,16, 0x1c, "2B1q" },
+ { "cmpqw", 7,16, 0x1d, "2W1q" },
+ { "cmpqd", 7,16, 0x1f, "2D1q" },
+ { "cmpsb", 16,16, 0x040e, "1i" },
+ { "cmpsw", 16,16, 0x050e, "1i" },
+ { "cmpsd", 16,16, 0x070e, "1i" },
+ { "cmpst", 16,16, 0x840e, "1i" },
+ { "comb", 14,24, 0x344e, "1B2B" },
+ { "comw", 14,24, 0x354e, "1W2W" },
+ { "comd", 14,24, 0x374e, "1D2D" },
+ { "cvtp", 11,24, 0x036e, "2D3D1r" },
+ { "cxp", 8,8, 0x22, "1p" },
+ { "cxpd", 11,16, 0x07f, "1D" },
+ { "deib", 14,24, 0x2cce, "1B2W" },
+ { "deiw", 14,24, 0x2dce, "1W2D" },
+ { "deid", 14,24, 0x2fce, "1D2Q" },
+ { "dia", 8,8, 0xc2, "" },
+ { "divf", 14,24, 0x21be, "1F2F" },
+ { "divl", 14,24, 0x20be, "1L2L" },
+ { "divb", 14,24, 0x3cce, "1B2B" },
+ { "divw", 14,24, 0x3dce, "1W2W" },
+ { "divd", 14,24, 0x3fce, "1D2D" },
+ { "enter", 8,8, 0x82, "1i2d" },
+ { "exit", 8,8, 0x92, "1i" },
+ { "extb", 11,24, 0x02e, "2D3B1r4d" },
+ { "extw", 11,24, 0x12e, "2D3W1r4d" },
+ { "extd", 11,24, 0x32e, "2D3D1r4d" },
+ { "extsb", 14,24, 0x0cce, "1D2B3i" },
+ { "extsw", 14,24, 0x0dce, "1D2W3i" },
+ { "extsd", 14,24, 0x0fce, "1D2D3i" },
+ { "ffsb", 14,24, 0x046e, "1B2B" },
+ { "ffsw", 14,24, 0x056e, "1W2B" },
+ { "ffsd", 14,24, 0x076e, "1D2B" },
+ { "flag", 8,8, 0xd2, "" },
+ { "floorfb", 14,24, 0x3c3e, "1F2B" },
+ { "floorfw", 14,24, 0x3d3e, "1F2W" },
+ { "floorfd", 14,24, 0x3f3e, "1F2D" },
+ { "floorlb", 14,24, 0x383e, "1L2B" },
+ { "floorlw", 14,24, 0x393e, "1L2W" },
+ { "floorld", 14,24, 0x3b3e, "1L2D" },
+ { "ibitb", 14,24, 0x384e, "1B2D" },
+ { "ibitw", 14,24, 0x394e, "1W2D" },
+ { "ibitd", 14,24, 0x3b4e, "1D2D" },
+ { "indexb", 11,24, 0x42e, "2B3B1r" },
+ { "indexw", 11,24, 0x52e, "2W3W1r" },
+ { "indexd", 11,24, 0x72e, "2D3D1r" },
+ { "insb", 11,24, 0x0ae, "2B3B1r4d" },
+ { "insw", 11,24, 0x1ae, "2W3W1r4d" },
+ { "insd", 11,24, 0x3ae, "2D3D1r4d" },
+ { "inssb", 14,24, 0x08ce, "1B2D3i" },
+ { "inssw", 14,24, 0x09ce, "1W2D3i" },
+ { "inssd", 14,24, 0x0bce, "1D2D3i" },
+ { "jsr", 11,16, 0x67f, "1A" },
+ { "jump", 11,16, 0x27f, "1A" },
+ { "lfsr", 19,24, 0x00f3e,"1D" },
+ { "lmr", 15,24, 0x0b1e, "2D1q" },
+ { "lprb", 7,16, 0x6c, "2B1q" },
+ { "lprw", 7,16, 0x6d, "2W1q" },
+ { "lprd", 7,16, 0x6f, "2D1q" },
+ { "lshb", 14,24, 0x144e, "1B2B" },
+ { "lshw", 14,24, 0x154e, "1B2W" },
+ { "lshd", 14,24, 0x174e, "1B2D" },
+ { "meib", 14,24, 0x24ce, "1B2W" },
+ { "meiw", 14,24, 0x25ce, "1W2D" },
+ { "meid", 14,24, 0x27ce, "1D2Q" },
+ { "modb", 14,24, 0x38ce, "1B2B" },
+ { "modw", 14,24, 0x39ce, "1W2W" },
+ { "modd", 14,24, 0x3bce, "1D2D" },
+ { "movf", 14,24, 0x05be, "1F2F" },
+ { "movl", 14,24, 0x04be, "1L2L" },
+ { "movb", 6,16, 0x14, "1B2B" },
+ { "movw", 6,16, 0x15, "1W2W" },
+ { "movd", 6,16, 0x17, "1D2D" },
+ { "movbf", 14,24, 0x043e, "1B2F" },
+ { "movwf", 14,24, 0x053e, "1W2F" },
+ { "movdf", 14,24, 0x073e, "1D2F" },
+ { "movbl", 14,24, 0x003e, "1B2L" },
+ { "movwl", 14,24, 0x013e, "1W2L" },
+ { "movdl", 14,24, 0x033e, "1D2L" },
+ { "movfl", 14,24, 0x1b3e, "1F2L" },
+ { "movlf", 14,24, 0x163e, "1L2F" },
+ { "movmb", 14,24, 0x00ce, "1D2D3d" },
+ { "movmw", 14,24, 0x00de, "1D2D3d" },
+ { "movmd", 14,24, 0x00fe, "1D2D3d" },
+ { "movqb", 7,16, 0x5c, "2B1q" },
+ { "movqw", 7,16, 0x5d, "2B1q" },
+ { "movqd", 7,16, 0x5f, "2B1q" },
+ { "movsb", 16,16, 0x000e, "1i" },
+ { "movsw", 16,16, 0x010e, "1i" },
+ { "movsd", 16,16, 0x030e, "1i" },
+ { "movst", 16,16, 0x800e, "1i" },
+ { "movsub", 14,24, 0x0cae, "1A1A" },
+ { "movsuw", 14,24, 0x0dae, "1A1A" },
+ { "movsud", 14,24, 0x0fae, "1A1A" },
+ { "movusb", 14,24, 0x1cae, "1A1A" },
+ { "movusw", 14,24, 0x1dae, "1A1A" },
+ { "movusd", 14,24, 0x1fae, "1A1A" },
+ { "movxbd", 14,24, 0x1cce, "1B2D" },
+ { "movxwd", 14,24, 0x1dce, "1W2D" },
+ { "movxbw", 14,24, 0x10ce, "1B2W" },
+ { "movzbd", 14,24, 0x18ce, "1B2D" },
+ { "movzwd", 14,24, 0x19ce, "1W2D" },
+ { "movzbw", 14,24, 0x14ce, "1B2W" },
+ { "mulf", 14,24, 0x31be, "1F2F" },
+ { "mull", 14,24, 0x30be, "1L2L" },
+ { "mulb", 14,24, 0x20ce, "1B2B" },
+ { "mulw", 14,24, 0x21ce, "1W2W" },
+ { "muld", 14,24, 0x23ce, "1D2D" },
+ { "negf", 14,24, 0x15be, "1F2F" },
+ { "negl", 14,24, 0x14be, "1L2L" },
+ { "negb", 14,24, 0x204e, "1B2B" },
+ { "negw", 14,24, 0x214e, "1W2W" },
+ { "negd", 14,24, 0x234e, "1D2D" },
+ { "nop", 8,8, 0xa2, "" },
+ { "notb", 14,24, 0x244e, "1B2B" },
+ { "notw", 14,24, 0x254e, "1W2W" },
+ { "notd", 14,24, 0x274e, "1D2D" },
+ { "orb", 6,16, 0x18, "1B1B" },
+ { "orw", 6,16, 0x19, "1W1W" },
+ { "ord", 6,16, 0x1b, "1D2D" },
+ { "quob", 14,24, 0x30ce, "1B2B" },
+ { "quow", 14,24, 0x31ce, "1W2W" },
+ { "quod", 14,24, 0x33ce, "1D2D" },
+ { "rdval", 19,24, 0x0031e,"1A" },
+ { "remb", 14,24, 0x34ce, "1B2B" },
+ { "remw", 14,24, 0x35ce, "1W2W" },
+ { "remd", 14,24, 0x37ce, "1D2D" },
+ { "restore", 8,8, 0x72, "1i" },
+ { "ret", 8,8, 0x12, "1d" },
+ { "reti", 8,8, 0x52, "" },
+ { "rett", 8,8, 0x42, "" },
+ { "rotb", 14,24, 0x004e, "1B2B" },
+ { "rotw", 14,24, 0x014e, "1B2W" },
+ { "rotd", 14,24, 0x034e, "1B2D" },
+ { "roundfb", 14,24, 0x243e, "1F2B" },
+ { "roundfw", 14,24, 0x253e, "1F2W" },
+ { "roundfd", 14,24, 0x273e, "1F2D" },
+ { "roundlb", 14,24, 0x203e, "1L2B" },
+ { "roundlw", 14,24, 0x213e, "1L2W" },
+ { "roundld", 14,24, 0x233e, "1L2D" },
+ { "rxp", 8,8, 0x32, "1d" },
+ { "sCONDb", 7,16, 0x3c, "2B1q" },
+ { "sCONDw", 7,16, 0x3d, "2D1q" },
+ { "sCONDd", 7,16, 0x3f, "2D1q" },
+ { "save", 8,8, 0x62, "1i" },
+ { "sbitb", 14,24, 0x184e, "1B2A" },
+ { "sbitw", 14,24, 0x194e, "1W2A" },
+ { "sbitd", 14,24, 0x1b4e, "1D2A" },
+ { "sbitib", 14,24, 0x1c4e, "1B2A" },
+ { "sbitiw", 14,24, 0x1d4e, "1W2A" },
+ { "sbitid", 14,24, 0x1f4e, "1D2A" },
+ { "setcfg", 15,24, 0x0b0e, "5D1q" },
+ { "sfsr", 14,24, 0x673e, "5D1D" },
+ { "skpsb", 16,16, 0x0c0e, "1i" },
+ { "skpsw", 16,16, 0x0d0e, "1i" },
+ { "skpsd", 16,16, 0x0f0e, "1i" },
+ { "skpst", 16,16, 0x8c0e, "1i" },
+ { "smr", 15,24, 0x0f1e, "2D1q" },
+ { "sprb", 7,16, 0x2c, "2B1q" },
+ { "sprw", 7,16, 0x2d, "2W1q" },
+ { "sprd", 7,16, 0x2f, "2D1q" },
+ { "subf", 14,24, 0x11be, "1F2F" },
+ { "subl", 14,24, 0x10be, "1L2L" },
+ { "subb", 6,16, 0x20, "1B2B" },
+ { "subw", 6,16, 0x21, "1W2W" },
+ { "subd", 6,16, 0x23, "1D2D" },
+ { "subcb", 6,16, 0x30, "1B2B" },
+ { "subcw", 6,16, 0x31, "1W2W" },
+ { "subcd", 6,16, 0x33, "1D2D" },
+ { "subpb", 14,24, 0x2c4e, "1B2B" },
+ { "subpw", 14,24, 0x2d4e, "1W2W" },
+ { "subpd", 14,24, 0x2f4e, "1D2D" },
+#ifndef NS32K_SVC_IMMED_OPERANDS
+ { "svc", 8,8, 0xe2, "2i1i" }, /* not really, but unix uses it */
+#else
+ { "svc", 8,8, 0xe2, "" }, /* not really, but unix uses it */
+#endif
+ { "tbitb", 6,16, 0x34, "1B2A" },
+ { "tbitw", 6,16, 0x35, "1W2A" },
+ { "tbitd", 6,16, 0x37, "1D2A" },
+ { "truncfb", 14,24, 0x2c3e, "1F2B" },
+ { "truncfw", 14,24, 0x2d3e, "1F2W" },
+ { "truncfd", 14,24, 0x2f3e, "1F2D" },
+ { "trunclb", 14,24, 0x283e, "1L2B" },
+ { "trunclw", 14,24, 0x293e, "1L2W" },
+ { "truncld", 14,24, 0x2b3e, "1L2D" },
+ { "wait", 8,8, 0xb2, "" },
+ { "wrval", 19,24, 0x0071e,"1A" },
+ { "xorb", 6,16, 0x38, "1B2B" },
+ { "xorw", 6,16, 0x39, "1W2W" },
+ { "xord", 6,16, 0x3b, "1D2D" },
+}; /* notstrs */
+
+/* end: ns32k.opcode.h */
+
+#define MAX_ARGS 4
+#define ARG_LEN 50
--- /dev/null
+/* Print 32000 instructions for GDB, the GNU debugger.
+ Copyright (C) 1986,1988 Free Software Foundation, Inc.
+
+GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY. No author or distributor accepts responsibility to anyone
+for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.
+Refer to the GDB General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute GDB,
+but only under the conditions described in the GDB General Public
+License. A copy of this license is supposed to have been given to you
+along with GDB so you can know your rights and responsibilities. It
+should be in a file named COPYING. Among other things, the copyright
+notice and this notice must be preserved on all copies.
+
+In other words, go ahead and share GDB, but don't try to stop
+anyone else from sharing it farther. Help stamp out software hoarding!
+*/
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "ns32k-opcode.h"
+#include "gdbcore.h"
+
+/* 32000 instructions are never longer than this. */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof notstrs / sizeof notstrs[0])
+
+extern char *reg_names[];
+
+#define NEXT_IS_ADDR '|'
+
+/*
+ * extract "count" bits starting "offset" bits
+ * into buffer
+ */
+
+int
+bit_extract (buffer, offset, count)
+ char *buffer;
+ int offset;
+ int count;
+{
+ int result;
+ int mask;
+ int bit;
+
+ buffer += offset >> 3;
+ offset &= 7;
+ bit = 1;
+ result = 0;
+ while (count--)
+ {
+ if ((*buffer & (1 << offset)))
+ result |= bit;
+ if (++offset == 8)
+ {
+ offset = 0;
+ buffer++;
+ }
+ bit <<= 1;
+ }
+ return result;
+}
+
+float
+fbit_extract (buffer, offset, count)
+{
+ union {
+ int ival;
+ float fval;
+ } foo;
+
+ foo.ival = bit_extract (buffer, offset, 32);
+ return foo.fval;
+}
+
+double
+dbit_extract (buffer, offset, count)
+{
+ union {
+ struct {int low, high; } ival;
+ double dval;
+ } foo;
+
+ foo.ival.low = bit_extract (buffer, offset, 32);
+ foo.ival.high = bit_extract (buffer, offset+32, 32);
+ return foo.dval;
+}
+
+sign_extend (value, bits)
+{
+ value = value & ((1 << bits) - 1);
+ return (value & (1 << (bits-1))
+ ? value | (~((1 << bits) - 1))
+ : value);
+}
+
+flip_bytes (ptr, count)
+ char *ptr;
+ int count;
+{
+ char tmp;
+
+ while (count > 0)
+ {
+ tmp = *ptr;
+ ptr[0] = ptr[count-1];
+ ptr[count-1] = tmp;
+ ptr++;
+ count -= 2;
+ }
+}
+\f
+/* Given a character C, does it represent a general addressing mode? */
+#define Is_gen(c) \
+ ((c) == 'F' || (c) == 'L' || (c) == 'B' \
+ || (c) == 'W' || (c) == 'D' || (c) == 'A')
+
+/* Adressing modes. */
+#define Adrmod_index_byte 0x1c
+#define Adrmod_index_word 0x1d
+#define Adrmod_index_doubleword 0x1e
+#define Adrmod_index_quadword 0x1f
+
+/* Is MODE an indexed addressing mode? */
+#define Adrmod_is_index(mode) \
+ (mode == Adrmod_index_byte \
+ || mode == Adrmod_index_word \
+ || mode == Adrmod_index_doubleword \
+ || mode == Adrmod_index_quadword)
+
+\f
+/* Print the 32000 instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register unsigned char *p;
+ register char *d;
+ unsigned short first_word;
+ int gen, disp;
+ int ioffset; /* bits into instruction */
+ int aoffset; /* bits into arguments */
+ char arg_bufs[MAX_ARGS+1][ARG_LEN];
+ int argnum;
+ int maxarg;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ first_word = *(unsigned short *) buffer;
+ for (i = 0; i < NOPCODES; i++)
+ if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
+ == notstrs[i].detail.code)
+ break;
+
+ /* Handle undefined instructions. */
+ if (i == NOPCODES)
+ {
+ fprintf (stream, "0%o", buffer[0]);
+ return 1;
+ }
+
+ fprintf (stream, "%s", notstrs[i].name);
+
+ ioffset = notstrs[i].detail.ibits;
+ aoffset = notstrs[i].detail.ibits;
+ d = notstrs[i].detail.args;
+
+ if (*d)
+ {
+ /* Offset in bits of the first thing beyond each index byte.
+ Element 0 is for operand A and element 1 is for operand B.
+ The rest are irrelevant, but we put them here so we don't
+ index outside the array. */
+ int index_offset[MAX_ARGS];
+
+ /* 0 for operand A, 1 for operand B, greater for other args. */
+ int whicharg = 0;
+
+ fputc ('\t', stream);
+
+ maxarg = 0;
+
+ /* First we have to find and keep track of the index bytes,
+ if we are using scaled indexed addressing mode, since the index
+ bytes occur right after the basic instruction, not as part
+ of the addressing extension. */
+ if (Is_gen(d[1]))
+ {
+ int addr_mode = bit_extract (buffer, ioffset - 5, 5);
+
+ if (Adrmod_is_index (addr_mode))
+ {
+ aoffset += 8;
+ index_offset[0] = aoffset;
+ }
+ }
+ if (d[2] && Is_gen(d[3]))
+ {
+ int addr_mode = bit_extract (buffer, ioffset - 10, 5);
+
+ if (Adrmod_is_index (addr_mode))
+ {
+ aoffset += 8;
+ index_offset[1] = aoffset;
+ }
+ }
+
+ while (*d)
+ {
+ argnum = *d - '1';
+ d++;
+ if (argnum > maxarg && argnum < MAX_ARGS)
+ maxarg = argnum;
+ ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
+ memaddr, arg_bufs[argnum],
+ index_offset[whicharg]);
+ d++;
+ whicharg++;
+ }
+ for (argnum = 0; argnum <= maxarg; argnum++)
+ {
+ CORE_ADDR addr;
+ char *ch, *index ();
+ for (ch = arg_bufs[argnum]; *ch;)
+ {
+ if (*ch == NEXT_IS_ADDR)
+ {
+ ++ch;
+ addr = atoi (ch);
+ print_address (addr, stream);
+ while (*ch && *ch != NEXT_IS_ADDR)
+ ++ch;
+ if (*ch)
+ ++ch;
+ }
+ else
+ putc (*ch++, stream);
+ }
+ if (argnum < maxarg)
+ fprintf (stream, ", ");
+ }
+ }
+ return aoffset / 8;
+}
+
+/* Print an instruction operand of category given by d. IOFFSET is
+ the bit position below which small (<1 byte) parts of the operand can
+ be found (usually in the basic instruction, but for indexed
+ addressing it can be in the index byte). AOFFSETP is a pointer to the
+ bit position of the addressing extension. BUFFER contains the
+ instruction. ADDR is where BUFFER was read from. Put the disassembled
+ version of the operand in RESULT. INDEX_OFFSET is the bit position
+ of the index byte (it contains garbage if this operand is not a
+ general operand using scaled indexed addressing mode). */
+
+print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
+ char d;
+ int ioffset, *aoffsetp;
+ char *buffer;
+ CORE_ADDR addr;
+ char *result;
+ int index_offset;
+{
+ int addr_mode;
+ float Fvalue;
+ double Lvalue;
+ int Ivalue;
+ int disp1, disp2;
+ int index;
+
+ switch (d)
+ {
+ case 'F':
+ case 'L':
+ case 'B':
+ case 'W':
+ case 'D':
+ case 'A':
+ addr_mode = bit_extract (buffer, ioffset-5, 5);
+ ioffset -= 5;
+ switch (addr_mode)
+ {
+ case 0x0: case 0x1: case 0x2: case 0x3:
+ case 0x4: case 0x5: case 0x6: case 0x7:
+ switch (d)
+ {
+ case 'F':
+ case 'L':
+ sprintf (result, "f%d", addr_mode);
+ break;
+ default:
+ sprintf (result, "r%d", addr_mode);
+ }
+ break;
+ case 0x8: case 0x9: case 0xa: case 0xb:
+ case 0xc: case 0xd: case 0xe: case 0xf:
+ disp1 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ disp1 = get_displacement (buffer, aoffsetp);
+ disp2 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "%d(%d(%s))", disp2, disp1,
+ addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
+ break;
+ case 0x13:
+ sprintf (result, "reserved");
+ break;
+ case 0x14:
+ switch (d)
+ {
+ case 'B':
+ Ivalue = bit_extract (buffer, *aoffsetp, 8);
+ Ivalue = sign_extend (Ivalue, 8);
+ *aoffsetp += 8;
+ sprintf (result, "$%d", Ivalue);
+ break;
+ case 'W':
+ Ivalue = bit_extract (buffer, *aoffsetp, 16);
+ flip_bytes (&Ivalue, 2);
+ *aoffsetp += 16;
+ Ivalue = sign_extend (Ivalue, 16);
+ sprintf (result, "$%d", Ivalue);
+ break;
+ case 'D':
+ Ivalue = bit_extract (buffer, *aoffsetp, 32);
+ flip_bytes (&Ivalue, 4);
+ *aoffsetp += 32;
+ sprintf (result, "$%d", Ivalue);
+ break;
+ case 'A':
+ Ivalue = bit_extract (buffer, *aoffsetp, 32);
+ flip_bytes (&Ivalue, 4);
+ *aoffsetp += 32;
+ sprintf (result, "$|%d|", Ivalue);
+ break;
+ case 'F':
+ Fvalue = fbit_extract (buffer, *aoffsetp, 32);
+ flip_bytes (&Fvalue, 4);
+ *aoffsetp += 32;
+ sprintf (result, "$%g", Fvalue);
+ break;
+ case 'L':
+ Lvalue = dbit_extract (buffer, *aoffsetp, 64);
+ flip_bytes (&Lvalue, 8);
+ *aoffsetp += 64;
+ sprintf (result, "$%g", Lvalue);
+ break;
+ }
+ break;
+ case 0x15:
+ disp1 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "@|%d|", disp1);
+ break;
+ case 0x16:
+ disp1 = get_displacement (buffer, aoffsetp);
+ disp2 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "EXT(%d) + %d", disp1, disp2);
+ break;
+ case 0x17:
+ sprintf (result, "tos");
+ break;
+ case 0x18:
+ disp1 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "%d(fp)", disp1);
+ break;
+ case 0x19:
+ disp1 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "%d(sp)", disp1);
+ break;
+ case 0x1a:
+ disp1 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "%d(sb)", disp1);
+ break;
+ case 0x1b:
+ disp1 = get_displacement (buffer, aoffsetp);
+ sprintf (result, "|%d|", addr + disp1);
+ break;
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
+ index = bit_extract (buffer, index_offset - 8, 3);
+ print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
+ result, 0);
+ {
+ static char *ind[] = {"b", "w", "d", "q"};
+ char *off;
+
+ off = result + strlen (result);
+ sprintf (off, "[r%d:%s]", index,
+ ind[addr_mode & 3]);
+ }
+ break;
+ }
+ break;
+ case 'q':
+ Ivalue = bit_extract (buffer, ioffset-4, 4);
+ Ivalue = sign_extend (Ivalue, 4);
+ sprintf (result, "%d", Ivalue);
+ ioffset -= 4;
+ break;
+ case 'r':
+ Ivalue = bit_extract (buffer, ioffset-3, 3);
+ sprintf (result, "r%d", Ivalue&7);
+ ioffset -= 3;
+ break;
+ case 'd':
+ sprintf (result, "%d", get_displacement (buffer, aoffsetp));
+ break;
+ case 'p':
+ sprintf (result, "%c%d%c", NEXT_IS_ADDR,
+ addr + get_displacement (buffer, aoffsetp),
+ NEXT_IS_ADDR);
+ break;
+ case 'i':
+ Ivalue = bit_extract (buffer, *aoffsetp, 8);
+ *aoffsetp += 8;
+ sprintf (result, "0x%x", Ivalue);
+ break;
+ }
+ return ioffset;
+}
+
+get_displacement (buffer, aoffsetp)
+ char *buffer;
+ int *aoffsetp;
+{
+ int Ivalue;
+
+ Ivalue = bit_extract (buffer, *aoffsetp, 8);
+ switch (Ivalue & 0xc0)
+ {
+ case 0x00:
+ case 0x40:
+ Ivalue = sign_extend (Ivalue, 7);
+ *aoffsetp += 8;
+ break;
+ case 0x80:
+ Ivalue = bit_extract (buffer, *aoffsetp, 16);
+ flip_bytes (&Ivalue, 2);
+ Ivalue = sign_extend (Ivalue, 14);
+ *aoffsetp += 16;
+ break;
+ case 0xc0:
+ Ivalue = bit_extract (buffer, *aoffsetp, 32);
+ flip_bytes (&Ivalue, 4);
+ Ivalue = sign_extend (Ivalue, 30);
+ *aoffsetp += 32;
+ break;
+ }
+ return Ivalue;
+}
+\f
+/* Return the number of locals in the current frame given a pc
+ pointing to the enter instruction. This is used in the macro
+ FRAME_FIND_SAVED_REGS. */
+
+ns32k_localcount (enter_pc)
+ CORE_ADDR enter_pc;
+{
+ unsigned char localtype;
+ int localcount;
+
+ localtype = read_memory_integer (enter_pc+2, 1);
+ if ((localtype & 0x80) == 0)
+ localcount = localtype;
+ else if ((localtype & 0xc0) == 0x80)
+ localcount = (((localtype & 0x3f) << 8)
+ | (read_memory_integer (enter_pc+3, 1) & 0xff));
+ else
+ localcount = (((localtype & 0x3f) << 24)
+ | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
+ | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
+ | (read_memory_integer (enter_pc+5, 1) & 0xff));
+ return localcount;
+}
+
+/*
+ * Get the address of the enter opcode for the function
+ * containing PC, if there is an enter for the function,
+ * and if the pc is between the enter and exit.
+ * Returns positive address if pc is between enter/exit,
+ * 1 if pc before enter or after exit, 0 otherwise.
+ */
+
+CORE_ADDR
+ns32k_get_enter_addr (pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR enter_addr;
+ unsigned char op;
+
+ if (ABOUT_TO_RETURN (pc))
+ return 1; /* after exit */
+
+ enter_addr = get_pc_function_start (pc);
+
+ if (pc == enter_addr)
+ return 1; /* before enter */
+
+ op = read_memory_integer (enter_addr, 1);
+
+ if (op != 0x82)
+ return 0; /* function has no enter/exit */
+
+ return enter_addr; /* pc is between enter and exit */
+}
--- /dev/null
+/* obstack.c - subroutines used implicitly by object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 1, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "obstack.h"
+
+#ifdef __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment. */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+ But in fact it might be less smart and round addresses to as much as
+ DEFAULT_ROUNDING. So we prepare for it to do that. */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+ On some machines, copying successive ints does not work;
+ in such a case, redefine COPYING_UNIT to `long' (if that works)
+ or `char' as a last resort. */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+/* The non-GNU-C macros copy the obstack into this global variable
+ to avoid multiple evaluation. */
+
+struct obstack *_obstack;
+\f
+/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
+ Objects start on multiples of ALIGNMENT (0 means use default).
+ CHUNKFUN is the function to use to allocate chunks,
+ and FREEFUN the function to free them. */
+
+void
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+ struct obstack *h;
+ int size;
+ int alignment;
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+{
+ register struct _obstack_chunk* chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+
+ chunk = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (h->chunk_size);
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+}
+
+/* Allocate a new current chunk for the obstack *H
+ on the assumption that LENGTH bytes need to be added
+ to the current object, or a new object of length LENGTH allocated.
+ Copies any partial object from the end of the old chunk
+ to the beginning of the new one.
+
+ The function must be "int" so it can be used in non-ANSI C
+ compilers in a : expression. */
+
+int
+_obstack_newchunk (h, length)
+ struct obstack *h;
+ int length;
+{
+ register struct _obstack_chunk* old_chunk = h->chunk;
+ register struct _obstack_chunk* new_chunk;
+ register long new_size;
+ register int obj_size = h->next_free - h->object_base;
+ register int i;
+ int already;
+
+ /* Compute size for new chunk. */
+ new_size = (obj_size + length) + (obj_size >> 3) + 100;
+ if (new_size < h->chunk_size)
+ new_size = h->chunk_size;
+
+ /* Allocate and initialize the new chunk. */
+ new_chunk = h->chunk = (struct _obstack_chunk *)(*h->chunkfun) (new_size);
+ new_chunk->prev = old_chunk;
+ new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+ /* Move the existing object to the new chunk.
+ Word at a time is fast and is safe if the object
+ is sufficiently aligned. */
+ if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+ {
+ for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+ i >= 0; i--)
+ ((COPYING_UNIT *)new_chunk->contents)[i]
+ = ((COPYING_UNIT *)h->object_base)[i];
+ /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+ but that can cross a page boundary on a machine
+ which does not do strict alignment for COPYING_UNITS. */
+ already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+ }
+ else
+ already = 0;
+ /* Copy remaining bytes one by one. */
+ for (i = already; i < obj_size; i++)
+ new_chunk->contents[i] = h->object_base[i];
+
+ h->object_base = new_chunk->contents;
+ h->next_free = h->object_base + obj_size;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+ This is here for debugging.
+ If you use it in a program, you are probably losing. */
+
+int
+_obstack_allocated_p (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp -> prev;
+ lp = plp;
+ }
+ return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+ more recently than OBJ. If OBJ is zero, free everything in H. */
+
+#ifdef __STDC__
+#undef obstack_free
+void
+obstack_free (struct obstack *h, POINTER obj)
+#else
+int
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+#endif
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp -> prev;
+ (*h->freefun) ((POINTER) lp);
+ lp = plp;
+ }
+ if (lp)
+ {
+ (h)->object_base = (h)->next_free = (char *)(obj);
+ (h)->chunk_limit = lp->limit;
+ (h)->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+/* Let same .o link with output of gcc and other compilers. */
+
+#ifdef __STDC__
+int
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ obstack_free (h, obj);
+}
+#endif
+\f
+/* #if 0 */
+/* These are now turned off because the applications do not use it
+ and it uses bcopy via obstack_grow, which causes trouble on sysV. */
+
+/* Now define the functional versions of the obstack macros.
+ Define them to simply use the corresponding macros to do the job. */
+
+#ifdef __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+ they won't pass through the macro names in parentheses. */
+
+/* The function names appear in parentheses in order to prevent
+ the macro-definitions of the names from being expanded there. */
+
+POINTER (obstack_base) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_room (obstack);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+/* #endif 0 */
--- /dev/null
+/* obstack.h - object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 1, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects. Each object starts life
+small, and may grow to maturity. (Consider building a word syllable
+by syllable.) An object can move while it is growing. Once it has
+been "finished" it never changes address again. So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
+by calling `obstack_chunk_free'. You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables. Unless you are "fascist pig with a read-only mind"
+[Gosper's immortal quote from HAKMEM item 154, out of context] you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols. At the time you are reading a symbol you don't know
+how long it is. One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer. This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently. Use one obstack for all symbol
+names. As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it. Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses. When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk. When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies. No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk. We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object. This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+ We allocate large chunks.
+ We carve out one object at a time from the current chunk.
+ Once carved, an object never moves.
+ We are free to append data of any size to the currently
+ growing object.
+ Exactly one object is growing in an obstack at any one time.
+ You can run one obstack per control block.
+ You may have as many control blocks as you dare.
+ Because of the way we do it, you can `unwind' a obstack
+ back to a previous state. (You may remove objects much
+ as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once. */
+
+#ifndef __OBSTACKS__
+#define __OBSTACKS__
+\f
+/* We use subtraction of (char *)0 instead of casting to int
+ because on word-addressable machines a simple cast to int
+ may ignore the byte-within-word field of the pointer. */
+
+#ifndef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((P) - (char *)0)
+#endif
+
+#ifndef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((P) + (char *)0)
+#endif
+
+struct _obstack_chunk /* Lives at front of each chunk. */
+{
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
+};
+
+struct obstack /* control current object in current chunk */
+{
+ long chunk_size; /* preferred size to allocate chunks in */
+ struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
+ int temp; /* Temporary for some macros. */
+ int alignment_mask; /* Mask of alignment for each object. */
+#ifdef __STDC__
+ void *(*chunkfun) (); /* User's fcn to allocate a chunk. */
+#else
+ char *(*chunkfun) (); /* User's fcn to allocate a chunk. */
+#endif
+ void (*freefun) (); /* User's function to free a chunk. */
+};
+\f
+#ifdef __STDC__
+
+/* Do the function-declarations after the structs
+ but before defining the macros. */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, void *data, int size);
+void obstack_grow0 (struct obstack *obstack, void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+ so we do not declare them. */
+\f
+/* Pointer to beginning of object being allocated or to be allocated next.
+ Note that this might not be the final address of the object
+ because a new chunk might be needed to hold the final size. */
+
+#define obstack_base(h) ((h)->object_base)
+
+/* Size for allocating ordinary chunks. */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk. */
+
+#define obstack_next_free(h) ((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object. */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+\f
+#if defined (__GNUC__) && defined (__STDC__)
+
+/* For GNU C, if not -traditional,
+ we can define these macros to compute all args only once
+ without using a global variable.
+ Also, we can avoid using the `temp' slot, to make faster code. */
+
+#define obstack_object_size(OBSTACK) \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->next_free - __o->object_base); })
+
+#define obstack_room(OBSTACK) \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->chunk_limit - __o->next_free); })
+
+#define obstack_grow(OBSTACK,where,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, __len) : 0); \
+ bcopy (where, __o->next_free, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_grow0(OBSTACK,where,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len + 1 > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, __len + 1) : 0), \
+ bcopy (where, __o->next_free, __len), \
+ __o->next_free += __len, \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+#define obstack_1grow(OBSTACK,datum) \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + 1 > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, 1) : 0), \
+ *(__o->next_free)++ = (datum); \
+ (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers or ints,
+ and that the data added so far to the current object
+ shares that much alignment. */
+
+#define obstack_ptr_grow(OBSTACK,datum) \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, sizeof (void *)) : 0), \
+ *(*(void ***)&__o->next_free)++ = ((void *)datum); \
+ (void) 0; })
+
+#define obstack_int_grow(OBSTACK,datum) \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (int) > __o->chunk_limit) \
+ ? _obstack_newchunk (__o, sizeof (int)) : 0), \
+ *(*(int **)&__o->next_free)++ = ((int)datum); \
+ (void) 0; })
+
+#define obstack_ptr_grow_fast(h,aptr) (*(*(void ***)&(h)->next_free)++ = (void *)aptr)
+#define obstack_int_grow_fast(h,aint) (*(*(int **)&(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(OBSTACK,length) \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->chunk_limit - __o->next_free < __len) \
+ ? _obstack_newchunk (__o, __len) : 0); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_alloc(OBSTACK,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy(OBSTACK,where,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy0(OBSTACK,where,length) \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_finish(OBSTACK) \
+({ struct obstack *__o = (OBSTACK); \
+ void *value = (void *) __o->object_base; \
+ __o->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT (__o->next_free)+__o->alignment_mask)\
+ & ~ (__o->alignment_mask)); \
+ ((__o->next_free - (char *)__o->chunk \
+ > __o->chunk_limit - (char *)__o->chunk) \
+ ? (__o->next_free = __o->chunk_limit) : 0); \
+ __o->object_base = __o->next_free; \
+ value; })
+
+#define obstack_free(OBSTACK, OBJ) \
+({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (OBJ); \
+ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ __o->next_free = __o->object_base = __obj; \
+ else (obstack_free) (__o, __obj); })
+\f
+#else /* not __GNUC__ or not __STDC__ */
+
+#define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+#define obstack_room(h) \
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+#define obstack_grow(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), (h)->temp) : 0), \
+ bcopy (where, (h)->next_free, (h)->temp), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_grow0(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), (h)->temp + 1) : 0), \
+ bcopy (where, (h)->next_free, (h)->temp), \
+ (h)->next_free += (h)->temp, \
+ *((h)->next_free)++ = 0)
+
+#define obstack_1grow(h,datum) \
+( (((h)->next_free + 1 > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), 1) : 0), \
+ *((h)->next_free)++ = (datum))
+
+#define obstack_ptr_grow(h,datum) \
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), sizeof (char *)) : 0), \
+ *(*(char ***)&(h)->next_free)++ = ((char *)datum))
+
+#define obstack_int_grow(h,datum) \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ ? _obstack_newchunk ((h), sizeof (int)) : 0), \
+ *(*(int **)&(h)->next_free)++ = ((int)datum))
+
+#define obstack_ptr_grow_fast(h,aptr) (*(*(char ***)&(h)->next_free)++ = (char *)aptr)
+#define obstack_int_grow_fast(h,aint) (*(*(int **)&(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(h,length) \
+( (h)->temp = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp) \
+ ? _obstack_newchunk ((h), (h)->temp) : 0), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_alloc(h,length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+#define obstack_copy(h,where,length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_copy0(h,where,length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_finish(h) \
+( (h)->temp = __PTR_TO_INT ((h)->object_base), \
+ (h)->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
+ & ~ ((h)->alignment_mask)), \
+ (((h)->next_free - (char *)(h)->chunk \
+ > (h)->chunk_limit - (char *)(h)->chunk) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ __INT_TO_PTR ((h)->temp))
+
+#ifdef __STDC__
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
+#else
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp >= 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (int) _obstack_free ((h), (h)->temp + (char *) (h)->chunk)))
+#endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+/* Declare the external functions we use; they are in obstack.c. */
+
+#ifdef __STDC__
+ extern int _obstack_newchunk (struct obstack *h, int length);
+ extern int _obstack_free (struct obstack *h, void *obj);
+ extern void _obstack_begin (struct obstack *h, int size, int alignment,
+ void *(*chunkfun) (), void (*freefun) ());
+#else
+ extern int _obstack_newchunk ();
+ extern int _obstack_free ();
+ extern void _obstack_begin ();
+#endif
+
+#endif /* not __OBSTACKS__ */
+
--- /dev/null
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (PARAM_H)
+#define PARAM_H 1
+
+/* DO NOT #include "tm.h" -- a particular tm file has been inc'd by caller */
+
+#include "xm.h"
+
+/* TARGET_BYTE_ORDER and HOST_BYTE_ORDER should be defined to one of these. */
+#if !defined (BIG_ENDIAN)
+#define BIG_ENDIAN 4321
+#endif
+
+#if !defined (LITTLE_ENDIAN)
+#define LITTLE_ENDIAN 1234
+#endif
+
+/* The bit byte-order has to do just with numbering of bits in
+ debugging symbols and such. Conceptually, it's quite separate
+ from byte/word byte order. */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BITS_BIG_ENDIAN 1
+#endif
+
+#if TARGET_BYTE_ORDER == LITTLE_ENDIAN
+/*#define BITS_BIG_ENDIAN */
+#endif
+
+/* Swap LEN bytes at BUFFER between target and host byte-order. */
+#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
+#define SWAP_TARGET_AND_HOST(buffer,len)
+#else /* Target and host byte order differ. */
+#define SWAP_TARGET_AND_HOST(buffer,len) \
+ { \
+ char tmp; \
+ char *p = (char *)(buffer); \
+ char *q = ((char *)(buffer)) + len - 1; \
+ for (; p < q; p++, q--) \
+ { \
+ tmp = *q; \
+ *q = *p; \
+ *p = tmp; \
+ } \
+ }
+#endif /* Target and host byte order differ. */
+
+/* On some machines there are bits in addresses which are not really
+ part of the address, but are used by the kernel, the hardware, etc.
+ for special purposes. ADDR_BITS_REMOVE takes out any such bits
+ so we get a "real" address such as one would find in a symbol
+ table. ADDR_BITS_SET sets those bits the way the system wants
+ them. */
+#if !defined (ADDR_BITS_REMOVE)
+#define ADDR_BITS_REMOVE(addr) (addr)
+#define ADDR_BITS_SET(addr) (addr)
+#endif /* No ADDR_BITS_REMOVE. */
+
+#endif /* param.h not already included. */
--- /dev/null
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* The standard thing is to include param.h. However, files that are
+ specific to a particular target can include that tm-xxx.h file and
+ param-no-tm.h. Any future inclusions of param.h will be protected
+ against by the #if !defined stuff below. */
+
+#if !defined (PARAM_H)
+#include "tm.h"
+#endif
+
+#include "param-no-tm.h"
+
+#define PARAM_H 1
--- /dev/null
+/* Print GOULD PN (PowerNode) instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct gld_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long mask;
+ char *args;
+ int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and at most four. The length of the
+ instruction is based on the opcode.
+
+ The mask component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing characters
+ that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+ r Register in first field
+ R Register in second field
+ b Base register in first field
+ B Base register in second field
+ v Vector register in first field
+ V Vector register in first field
+ A Optional address register (base register)
+ X Optional index register
+ I Immediate data (16bits signed)
+ O Offset field (16bits signed)
+ h Offset field (15bits signed)
+ d Offset field (14bits signed)
+ S Shift count field
+
+ any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "abm", 0xa0080000, 0xfc080000, "f,xOA,X", 4 },
+{ "abr", 0x18080000, 0xfc0c0000, "r,f", 2 },
+{ "aci", 0xfc770000, 0xfc7f8000, "r,I", 4 },
+{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
+{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "adi", 0xc8010000, 0xfc7f0000, "r,I", 4 },
+{ "admb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "admd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "admh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "admw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
+{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
+{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
+{ "adrm", 0x38080000, 0xfc0f0000, "r,R", 2 },
+{ "ai", 0xfc030000, 0xfc07ffff, "I", 4 },
+{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
+{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
+{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
+{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
+{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bcf", 0xf0000000, 0xfc080000, "I,xOA,X", 4 },
+{ "bct", 0xec000000, 0xfc080000, "I,xOA,X", 4 },
+{ "bei", 0x00060000, 0xffff0000, "", 2 },
+{ "bft", 0xf0000000, 0xff880000, "xOA,X", 4 },
+{ "bib", 0xf4000000, 0xfc780000, "r,xOA", 4 },
+{ "bid", 0xf4600000, 0xfc780000, "r,xOA", 4 },
+{ "bih", 0xf4200000, 0xfc780000, "r,xOA", 4 },
+{ "biw", 0xf4400000, 0xfc780000, "r,xOA", 4 },
+{ "bl", 0xf8800000, 0xff880000, "xOA,X", 4 },
+{ "bsub", 0x5c080000, 0xff8f0000, "", 2 },
+{ "bsubm", 0x28080000, 0xfc080000, "", 4 },
+{ "bu", 0xec000000, 0xff880000, "xOA,X", 4 },
+{ "call", 0x28080000, 0xfc0f0000, "", 2 },
+{ "callm", 0x5c080000, 0xff880000, "", 4 },
+{ "camb", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
+{ "camd", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
+{ "camh", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
+{ "camw", 0x90000000, 0xfc080000, "r.xOA,X", 4 },
+{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
+{ "cd", 0xfc060000, 0xfc070000, "r,f", 4 },
+{ "cea", 0x000f0000, 0xffff0000, "", 2 },
+{ "ci", 0xc8050000, 0xfc7f0000, "r,I", 4 },
+{ "cmc", 0x040a0000, 0xfc7f0000, "r", 2 },
+{ "cmmb", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
+{ "cmmd", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
+{ "cmmh", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
+{ "cmmw", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
+{ "cmr", 0x14000000, 0xfc0f0000, "r,R", 2 },
+{ "daci", 0xfc7f0000, 0xfc7f8000, "r,I", 4 },
+{ "dae", 0x000e0000, 0xffff0000, "", 2 },
+{ "dai", 0xfc040000, 0xfc07ffff, "I", 4 },
+{ "dci", 0xfc6f0000, 0xfc7f8000, "r,I", 4 },
+{ "di", 0xfc010000, 0xfc07ffff, "I", 4 },
+{ "dvfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "dvfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvi", 0xc8040000, 0xfc7f0000, "r,I", 4 },
+{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
+{ "dvrfd", 0x380c0000, 0xfc0f0000, "r,R", 4 },
+{ "dvrfw", 0x38040000, 0xfc0f0000, "r,xOA,X", 4 },
+{ "eae", 0x00080000, 0xffff0000, "", 2 },
+{ "eci", 0xfc670000, 0xfc7f8080, "r,I", 4 },
+{ "ecwcs", 0xfc4f0000, 0xfc7f8000, "", 4 },
+{ "ei", 0xfc000000, 0xfc07ffff, "I", 4 },
+{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
+{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
+{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
+{ "eorm", 0x0c080000, 0xfc0f0000, "r,R", 2 },
+{ "es", 0x00040000, 0xfc7f0000, "r", 2 },
+{ "exm", 0xa8000000, 0xff880000, "xOA,X", 4 },
+{ "exr", 0xc8070000, 0xfc7f0000, "r", 2 },
+{ "exrr", 0xc8070002, 0xfc7f0002, "r", 2 },
+{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
+{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
+{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
+{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
+{ "grio", 0xfc3f0000, 0xfc7f8000, "r,I", 4 },
+{ "halt", 0x00000000, 0xffff0000, "", 2 },
+{ "hio", 0xfc370000, 0xfc7f8000, "r,I", 4 },
+{ "jwcs", 0xfa080000, 0xff880000, "xOA,X", 4 },
+{ "la", 0x50000000, 0xfc000000, "r,xOA,X", 4 },
+{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lb", 0xac080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lcs", 0x00030000, 0xfc7f0000, "r", 2 },
+{ "ld", 0xac000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lear", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lf", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lfbr", 0xcc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lh", 0xac000001, 0xfc080001, "r,xOA,X", 4 },
+{ "li", 0xc8000000, 0xfc7f0000, "r,I", 4 },
+{ "lmap", 0x2c070000, 0xfc7f0000, "r", 2 },
+{ "lmb", 0xb0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lmd", 0xb0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lmh", 0xb0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lmw", 0xb0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnd", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lnh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lnw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lpsd", 0xf9800000, 0xff880000, "r,xOA,X", 4 },
+{ "lpsdcm", 0xfa800000, 0xff880000, "r,xOA,X", 4 },
+{ "lw", 0xac000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
+{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
+{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpi", 0xc8030000, 0xfc7f0000, "r,I", 4 },
+{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
+{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
+{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
+{ "nop", 0x00020000, 0xffff0000, "", 2 },
+{ "ormb", 0x88080000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormd", 0x88000002, 0xfc080002, "r,xOA,X", 4 },
+{ "ormh", 0x88000001, 0xfc080001, "r,xOA,X", 4 },
+{ "ormw", 0x88000000, 0xfc080000, "r,xOA,X", 4 },
+{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
+{ "orrm", 0x08080000, 0xfc0f0000, "r,R", 2 },
+{ "rdsts", 0x00090000, 0xfc7f0000, "r", 2 },
+{ "return", 0x280e0000, 0xfc7f0000, "", 2 },
+{ "ri", 0xfc020000, 0xfc07ffff, "I", 4 },
+{ "rnd", 0x00050000, 0xfc7f0000, "r", 2 },
+{ "rpswt", 0x040b0000, 0xfc7f0000, "r", 2 },
+{ "rschnl", 0xfc2f0000, 0xfc7f8000, "r,I", 4 },
+{ "rsctl", 0xfc470000, 0xfc7f8000, "r,I", 4 },
+{ "rwcs", 0x000b0000, 0xfc0f0000, "r,R", 2 },
+{ "sacz", 0x10080000, 0xfc0f0000, "r,R", 2 },
+{ "sbm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
+{ "sbr", 0x18000000, 0xfc0c0000, "r,f", 4 },
+{ "sea", 0x000d0000, 0xffff0000, "", 2 },
+{ "setcpu", 0x2c090000, 0xfc7f0000, "r", 2 },
+{ "sio", 0xfc170000, 0xfc7f8000, "r,I", 4 },
+{ "sipu", 0x000a0000, 0xffff0000, "", 2 },
+{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
+{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
+{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
+{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
+{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
+{ "smc", 0x04070000, 0xfc070000, "", 2 },
+{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
+{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
+{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
+{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
+{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
+{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stfbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "stmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stpio", 0xfc270000, 0xfc7f8000, "r,I", 4 },
+{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
+{ "sufd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sufw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sui", 0xc8020000, 0xfc7f0000, "r,I", 4 },
+{ "sumb", 0xbc080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumd", 0xbc000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sumh", 0xbc000001, 0xfc080001, "r,xOA,X", 4 },
+{ "sumw", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
+{ "surfd", 0x380b0000, 0xfc0f0000, "r,xOA,X", 4 },
+{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
+{ "surm", 0x3c080000, 0xfc0f0000, "r,R", 2 },
+{ "svc", 0xc8060000, 0xffff0000, "", 4 },
+{ "tbm", 0xa4080000, 0xfc080000, "f,xOA,X", 4 },
+{ "tbr", 0x180c0000, 0xfc0c0000, "r,f", 2 },
+{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
+{ "tccr", 0x28040000, 0xfc7f0000, "", 2 },
+{ "td", 0xfc050000, 0xfc070000, "r,f", 4 },
+{ "tio", 0xfc1f0000, 0xfc7f8000, "r,I", 4 },
+{ "tmapr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
+{ "tpcbr", 0x280c0000, 0xfc7f0000, "r", 2 },
+{ "trbr", 0x2c010000, 0xfc0f0000, "b,R", 2 },
+{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
+{ "trcc", 0x28050000, 0xfc7f0000, "", 2 },
+{ "trcm", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
+{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
+{ "trnm", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
+{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
+{ "trrm", 0x2c080000, 0xfc0f0000, "r,R", 2 },
+{ "trsc", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
+{ "trsw", 0x28000000, 0xfc7f0000, "r", 2 },
+{ "tscr", 0x2c0f0000, 0xfc0f0000, "r,R", 2 },
+{ "uei", 0x00070000, 0xffff0000, "", 2 },
+{ "wait", 0x00010000, 0xffff0000, "", 2 },
+{ "wcwcs", 0xfc5f0000, 0xfc7f8000, "", 4 },
+{ "wwcs", 0x000c0000, 0xfc0f0000, "r,R", 2 },
+{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
+{ "xcr", 0x2c050000, 0xfc0f0000, "r,R", 2 },
+{ "xcrm", 0x2c0d0000, 0xfc0f0000, "r,R", 2 },
+{ "zbm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zbr", 0x18040000, 0xfc0c0000, "r,f", 2 },
+{ "zmb", 0xf8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmd", 0xf8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "zmh", 0xf8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "zmw", 0xf8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "zr", 0x0c000000, 0xfc0f0000, "r", 2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+ sizeof(gld_opcodes[0]);
--- /dev/null
+/* pyramid.opcode.h -- gdb initial attempt. */
+
+/* pyramid opcode table: wot to do with this
+ particular opcode */
+
+struct pyr_datum
+{
+ char nargs;
+ char * args; /* how to compile said opcode */
+ unsigned long mask; /* Bit vector: which operand modes are valid
+ for this opcode */
+ unsigned char code; /* op-code (always 6(?) bits */
+};
+
+typedef struct pyr_insn_format {
+ unsigned int mode :4;
+ unsigned int operator :8;
+ unsigned int index_scale :2;
+ unsigned int index_reg :6;
+ unsigned int operand_1 :6;
+ unsigned int operand_2:6;
+} pyr_insn_format;
+
+
+/* We store four bytes of opcode for all opcodes.
+ Pyramid is sufficiently RISCy that:
+ - insns are always an integral number of words;
+ - the length of any insn can be told from the first word of
+ the insn. (ie, if there are zero, one, or two words of
+ immediate operand/offset).
+
+
+ The args component is a string containing two characters for each
+ operand of the instruction. The first specifies the kind of operand;
+ the second, the place it is stored. */
+
+/* Kinds of operands:
+ mask assembler syntax description
+ 0x0001: movw Rn,Rn register to register
+ 0x0002: movw K,Rn quick immediate to register
+ 0x0004: movw I,Rn long immediate to register
+ 0x0008: movw (Rn),Rn register indirect to register
+ movw (Rn)[x],Rn register indirect to register
+ 0x0010: movw I(Rn),Rn offset register indirect to register
+ movw I(Rn)[x],Rn offset register indirect, indexed, to register
+
+ 0x0020: movw Rn,(Rn) register to register indirect
+ 0x0040: movw K,(Rn) quick immediate to register indirect
+ 0x0080: movw I,(Rn) long immediate to register indirect
+ 0x0100: movw (Rn),(Rn) register indirect to-register indirect
+ 0x0100: movw (Rn),(Rn) register indirect to-register indirect
+ 0x0200: movw I(Rn),(Rn) register indirect+offset to register indirect
+ 0x0200: movw I(Rn),(Rn) register indirect+offset to register indirect
+
+ 0x0400: movw Rn,I(Rn) register to register indirect+offset
+ 0x0800: movw K,I(Rn) quick immediate to register indirect+offset
+ 0x1000: movw I,I(Rn) long immediate to register indirect+offset
+ 0x1000: movw (Rn),I(Rn) register indirect to-register indirect+offset
+ 0x1000: movw I(Rn),I(Rn) register indirect+offset to register indirect
+ +offset
+ 0x0000: (irregular) ???
+
+
+ Each insn has a four-bit field encoding the type(s) of its operands.
+*/
+
+/* Some common combinations
+ */
+
+/* the first 5,(0x1|0x2|0x4|0x8|0x10) ie (1|2|4|8|16), ie ( 32 -1)*/
+#define GEN_TO_REG (31)
+
+#define UNKNOWN ((unsigned long)-1)
+#define ANY (GEN_TO_REG | (GEN_TO_REG << 5) | (GEN_TO_REG << 15))
+
+#define CONVERT (1|8|0x10|0x20|0x200)
+
+#define K_TO_REG (2)
+#define I_TO_REG (4)
+#define NOTK_TO_REG (GEN_TO_REG & ~K_TO_REG)
+#define NOTI_TO_REG (GEN_TO_REG & ~I_TO_REG)
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+
+struct pyr_opcode /* pyr opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct pyr_datum datum; /* rest of opcode table [datum] */
+};
+
+#define pyr_how args
+#define pyr_nargs nargs
+#define pyr_mask mask
+#define pyr_name name
+
+struct pyr_opcode pyr_opcodes[] =
+{
+ {"movb", { 2, "", UNKNOWN, 0x11}, },
+ {"movh", { 2, "", UNKNOWN, 0x12} },
+ {"movw", { 2, "", ANY, 0x10} },
+ {"movl", { 2, "", ANY, 0x13} },
+ {"mnegw", { 2, "", (0x1|0x8|0x10), 0x14} },
+ {"mnegf", { 2, "", 0x1, 0x15} },
+ {"mnegd", { 2, "", 0x1, 0x16} },
+ {"mcomw", { 2, "", (0x1|0x8|0x10), 0x17} },
+ {"mabsw", { 2, "", (0x1|0x8|0x10), 0x18} },
+ {"mabsf", { 2, "", 0x1, 0x19} },
+ {"mabsd", { 2, "", 0x1, 0x1a} },
+ {"mtstw", { 2, "", (0x1|0x8|0x10), 0x1c} },
+ {"mtstf", { 2, "", 0x1, 0x1d} },
+ {"mtstd", { 2, "", 0x1, 0x1e} },
+ {"mova", { 2, "", 0x8|0x10, 0x1f} },
+ {"movzbw", { 2, "", (0x1|0x8|0x10), 0x20} },
+ {"movzhw", { 2, "", (0x1|0x8|0x10), 0x21} },
+ /* 2 insns out of order here */
+ {"movbl", { 2, "", 1, 0x4f} },
+ {"filbl", { 2, "", 1, 0x4e} },
+
+ {"cvtbw", { 2, "", CONVERT, 0x22} },
+ {"cvthw", { 2, "", CONVERT, 0x23} },
+ {"cvtwb", { 2, "", CONVERT, 0x24} },
+ {"cvtwh", { 2, "", CONVERT, 0x25} },
+ {"cvtwf", { 2, "", CONVERT, 0x26} },
+ {"cvtwd", { 2, "", CONVERT, 0x27} },
+ {"cvtfw", { 2, "", CONVERT, 0x28} },
+ {"cvtfd", { 2, "", CONVERT, 0x29} },
+ {"cvtdw", { 2, "", CONVERT, 0x2a} },
+ {"cvtdf", { 2, "", CONVERT, 0x2b} },
+
+ {"addw", { 2, "", GEN_TO_REG, 0x40} },
+ {"addwc", { 2, "", GEN_TO_REG, 0x41} },
+ {"subw", { 2, "", GEN_TO_REG, 0x42} },
+ {"subwb", { 2, "", GEN_TO_REG, 0x43} },
+ {"rsubw", { 2, "", GEN_TO_REG, 0x44} },
+ {"mulw", { 2, "", GEN_TO_REG, 0x45} },
+ {"emul", { 2, "", GEN_TO_REG, 0x47} },
+ {"umulw", { 2, "", GEN_TO_REG, 0x46} },
+ {"divw", { 2, "", GEN_TO_REG, 0x48} },
+ {"ediv", { 2, "", GEN_TO_REG, 0x4a} },
+ {"rdivw", { 2, "", GEN_TO_REG, 0x4b} },
+ {"udivw", { 2, "", GEN_TO_REG, 0x49} },
+ {"modw", { 2, "", GEN_TO_REG, 0x4c} },
+ {"umodw", { 2, "", GEN_TO_REG, 0x4d} },
+
+
+ {"addf", { 2, "", 1, 0x50} },
+ {"addd", { 2, "", 1, 0x51} },
+ {"subf", { 2, "", 1, 0x52} },
+ {"subd", { 2, "", 1, 0x53} },
+ {"mulf", { 2, "", 1, 0x56} },
+ {"muld", { 2, "", 1, 0x57} },
+ {"divf", { 2, "", 1, 0x58} },
+ {"divd", { 2, "", 1, 0x59} },
+
+
+ {"cmpb", { 2, "", UNKNOWN, 0x61} },
+ {"cmph", { 2, "", UNKNOWN, 0x62} },
+ {"cmpw", { 2, "", UNKNOWN, 0x60} },
+ {"ucmpb", { 2, "", UNKNOWN, 0x66} },
+ /* WHY no "ucmph"??? */
+ {"ucmpw", { 2, "", UNKNOWN, 0x65} },
+ {"xchw", { 2, "", UNKNOWN, 0x0f} },
+
+
+ {"andw", { 2, "", GEN_TO_REG, 0x30} },
+ {"orw", { 2, "", GEN_TO_REG, 0x31} },
+ {"xorw", { 2, "", GEN_TO_REG, 0x32} },
+ {"bicw", { 2, "", GEN_TO_REG, 0x33} },
+ {"lshlw", { 2, "", GEN_TO_REG, 0x38} },
+ {"ashlw", { 2, "", GEN_TO_REG, 0x3a} },
+ {"ashll", { 2, "", GEN_TO_REG, 0x3c} },
+ {"ashrw", { 2, "", GEN_TO_REG, 0x3b} },
+ {"ashrl", { 2, "", GEN_TO_REG, 0x3d} },
+ {"rotlw", { 2, "", GEN_TO_REG, 0x3e} },
+ {"rotrw", { 2, "", GEN_TO_REG, 0x3f} },
+
+ /* push and pop insns are "going away next release". */
+ {"pushw", { 2, "", GEN_TO_REG, 0x0c} },
+ {"popw", { 2, "", (0x1|0x8|0x10), 0x0d} },
+ {"pusha", { 2, "", (0x8|0x10), 0x0e} },
+
+ {"bitsw", { 2, "", UNKNOWN, 0x35} },
+ {"bitcw", { 2, "", UNKNOWN, 0x36} },
+ /* some kind of ibra/dbra insns??*/
+ {"icmpw", { 2, "", UNKNOWN, 0x67} },
+ {"dcmpw", { 2, "", (1|4|0x20|0x80|0x400|0x1000), 0x69} },/*FIXME*/
+ {"acmpw", { 2, "", 1, 0x6b} },
+
+ /* Call is written as a 1-op insn, but is always (dis)assembled as a 2-op
+ insn with a 2nd op of tr14. The assembler will have to grok this. */
+ {"call", { 2, "", GEN_TO_REG, 0x04} },
+ {"call", { 1, "", GEN_TO_REG, 0x04} },
+
+ {"callk", { 1, "", UNKNOWN, 0x06} },/* system call?*/
+ /* Ret is usually written as a 0-op insn, but gets disassembled as a
+ 1-op insn. The operand is always tr15. */
+ {"ret", { 0, "", UNKNOWN, 0x09} },
+ {"ret", { 1, "", UNKNOWN, 0x09} },
+ {"adsf", { 2, "", (1|2|4), 0x08} },
+ {"retd", { 2, "", UNKNOWN, 0x0a} },
+ {"btc", { 2, "", UNKNOWN, 0x01} },
+ {"bfc", { 2, "", UNKNOWN, 0x02} },
+ /* Careful: halt is 0x00000000. Jump must have some other (mode?)bit set?? */
+ {"jump", { 1, "", UNKNOWN, 0x00} },
+ {"btp", { 2, "", UNKNOWN, 0xf00} },
+ /* read control-stack pointer is another 1-or-2 operand insn. */
+ {"rcsp", { 2, "", UNKNOWN, 0x01f} },
+ {"rcsp", { 1, "", UNKNOWN, 0x01f} }
+};
+
+/* end: pyramid.opcode.h */
+/* One day I will have to take the time to find out what operands
+ are valid for these insns, and guess at what they mean.
+
+ I can't imagine what the "I???" insns (iglob, etc) do.
+
+ the arithmetic-sounding insns ending in "p" sound awfully like BCD
+ arithmetic insns:
+ dshlp -> Decimal SHift Left Packed
+ dshrp -> Decimal SHift Right Packed
+ and cvtlp would be convert long to packed.
+ I have no idea how the operands are interpreted; but having them be
+ a long register with (address, length) of an in-memory packed BCD operand
+ would not be surprising.
+ They are unlikely to be a packed bcd string: 64 bits of long give
+ is only 15 digits+sign, which isn't enough for COBOL.
+ */
+#if 0
+ {"wcsp", { 2, "", UNKNOWN, 0x00} }, /*write csp?*/
+ /* The OSx Operating System Porting Guide claims SSL does things
+ with tr12 (a register reserved to it) to do with static block-structure
+ references. SSL=Set Static Link? It's "Going away next release". */
+ {"ssl", { 2, "", UNKNOWN, 0x00} },
+ {"ccmps", { 2, "", UNKNOWN, 0x00} },
+ {"lcd", { 2, "", UNKNOWN, 0x00} },
+ {"uemul", { 2, "", UNKNOWN, 0x00} }, /*unsigned emul*/
+ {"srf", { 2, "", UNKNOWN, 0x00} }, /*Gidget time???*/
+ {"mnegp", { 2, "", UNKNOWN, 0x00} }, /move-neg phys?*/
+ {"ldp", { 2, "", UNKNOWN, 0x00} }, /*load phys?*/
+ {"ldti", { 2, "", UNKNOWN, 0x00} },
+ {"ldb", { 2, "", UNKNOWN, 0x00} },
+ {"stp", { 2, "", UNKNOWN, 0x00} },
+ {"stti", { 2, "", UNKNOWN, 0x00} },
+ {"stb", { 2, "", UNKNOWN, 0x00} },
+ {"stu", { 2, "", UNKNOWN, 0x00} },
+ {"addp", { 2, "", UNKNOWN, 0x00} },
+ {"subp", { 2, "", UNKNOWN, 0x00} },
+ {"mulp", { 2, "", UNKNOWN, 0x00} },
+ {"divp", { 2, "", UNKNOWN, 0x00} },
+ {"dshlp", { 2, "", UNKNOWN, 0x00} }, /* dec shl packed? */
+ {"dshrp", { 2, "", UNKNOWN, 0x00} }, /* dec shr packed? */
+ {"movs", { 2, "", UNKNOWN, 0x00} }, /*move (string?)?*/
+ {"cmpp", { 2, "", UNKNOWN, 0x00} }, /* cmp phys?*/
+ {"cmps", { 2, "", UNKNOWN, 0x00} }, /* cmp (string?)?*/
+ {"cvtlp", { 2, "", UNKNOWN, 0x00} }, /* cvt long to p??*/
+ {"cvtpl", { 2, "", UNKNOWN, 0x00} }, /* cvt p to l??*/
+ {"dintr", { 2, "", UNKNOWN, 0x00} }, /* ?? intr ?*/
+ {"rphysw", { 2, "", UNKNOWN, 0x00} }, /* read phys word?*/
+ {"wphysw", { 2, "", UNKNOWN, 0x00} }, /* write phys word?*/
+ {"cmovs", { 2, "", UNKNOWN, 0x00} },
+ {"rsubw", { 2, "", UNKNOWN, 0x00} },
+ {"bicpsw", { 2, "", UNKNOWN, 0x00} }, /* clr bit in psw? */
+ {"bispsw", { 2, "", UNKNOWN, 0x00} }, /* set bit in psw? */
+ {"eio", { 2, "", UNKNOWN, 0x00} }, /* ?? ?io ? */
+ {"callp", { 2, "", UNKNOWN, 0x00} }, /* call phys?*/
+ {"callr", { 2, "", UNKNOWN, 0x00} },
+ {"lpcxt", { 2, "", UNKNOWN, 0x00} }, /*load proc context*/
+ {"rei", { 2, "", UNKNOWN, 0x00} }, /*ret from intrpt*/
+ {"rport", { 2, "", UNKNOWN, 0x00} }, /*read-port?*/
+ {"rtod", { 2, "", UNKNOWN, 0x00} }, /*read-time-of-day?*/
+ {"ssi", { 2, "", UNKNOWN, 0x00} },
+ {"vtpa", { 2, "", UNKNOWN, 0x00} }, /*virt-to-phys-addr?*/
+ {"wicl", { 2, "", UNKNOWN, 0x00} }, /* write icl ? */
+ {"wport", { 2, "", UNKNOWN, 0x00} }, /*write-port?*/
+ {"wtod", { 2, "", UNKNOWN, 0x00} }, /*write-time-of-day?*/
+ {"flic", { 2, "", UNKNOWN, 0x00} },
+ {"iglob", { 2, "", UNKNOWN, 0x00} }, /* I global? */
+ {"iphys", { 2, "", UNKNOWN, 0x00} }, /* I physical? */
+ {"ipid", { 2, "", UNKNOWN, 0x00} }, /* I pid? */
+ {"ivect", { 2, "", UNKNOWN, 0x00} }, /* I vector? */
+ {"lamst", { 2, "", UNKNOWN, 0x00} },
+ {"tio", { 2, "", UNKNOWN, 0x00} },
+#endif
--- /dev/null
+/* Disassembler for the Pyramid Technology 90x
+ Copyright (C) 1988,1989 Free Software Foundation, Inc.
+
+This file is part of GDB, the GNU disassembler.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "pyr-opcode.h"
+#include "gdbcore.h"
+
+\f
+/* A couple of functions used for debugging frame-handling on
+ Pyramids. (The Pyramid-dependent handling of register values for
+ windowed registers is known to be buggy.)
+
+ When debugging, these functions supplant the normal definitions of some
+ of the macros in m-pyramid.h The quantity of information produced
+ when these functions are used makes the gdb unusable as a
+ debugger for user programs. */
+
+extern unsigned pyr_saved_pc(), pyr_frame_chain();
+
+CORE_ADDR pyr_frame_chain(frame)
+ CORE_ADDR frame;
+{
+ int foo=frame - CONTROL_STACK_FRAME_SIZE;
+ /* printf ("...following chain from %x: got %x\n", frame, foo);*/
+ return foo;
+}
+
+CORE_ADDR pyr_saved_pc(frame)
+ CORE_ADDR frame;
+{
+ int foo=0;
+ foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
+ printf ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
+ frame, 60/4, foo);
+ return foo;
+}
+\f
+
+/* Pyramid instructions are never longer than this many bytes. */
+#define MAXLEN 24
+
+/* Number of elements in the opcode table. */
+/*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
+#define NOPCODES (nopcodes)
+
+extern char *reg_names[];
+\f
+/* Let's be byte-independent so we can use this as a cross-assembler.
+ (will this ever be useful?
+ */
+
+#define NEXTLONG(p) \
+ (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+\f
+/* Print one instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i, nargs, insn_size =4;
+ register unsigned char *p;
+ register char *d;
+ register int insn_opcode, operand_mode;
+ register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ;
+ long insn; /* first word of the insn, not broken down. */
+ pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */
+ long extra_1, extra_2;
+
+ read_memory (memaddr, buffer, MAXLEN);
+ insn_decode = *((pyr_insn_format *) buffer);
+ insn = * ((int *) buffer);
+ insn_opcode = insn_decode.operator;
+ operand_mode = insn_decode.mode;
+ index_multiplier = insn_decode.index_scale;
+ index_reg_regno = insn_decode.index_reg;
+ op_1_regno = insn_decode.operand_1;
+ op_2_regno = insn_decode.operand_2;
+
+
+ if (*((int *)buffer) == 0x0) {
+ /* "halt" looks just like an invalid "jump" to the insn decoder,
+ so is dealt with as a special case */
+ fprintf (stream, "halt");
+ return (4);
+ }
+
+ for (i = 0; i < NOPCODES; i++)
+ if (pyr_opcodes[i].datum.code == insn_opcode)
+ break;
+
+ if (i == NOPCODES)
+ /* FIXME: Handle unrecognised instructions better. */
+ fprintf (stream, "???\t#%08x\t(op=%x mode =%x)",
+ insn, insn_decode.operator, insn_decode.mode);
+ else
+ {
+ /* Print the mnemonic for the instruction. Pyramid insn operands
+ are so regular that we can deal with almost all of them
+ separately.
+ Unconditional branches are an exception: they are encoded as
+ conditional branches (branch if false condition, I think)
+ with no condition specified. The average user will not be
+ aware of this. To maintain their illusion that an
+ unconditional branch insn exists, we will have to FIXME to
+ treat the insn mnemnonic of all branch instructions here as a
+ special case: check the operands of branch insn and print an
+ appropriate mnemonic. */
+
+ fprintf (stream, "%s\t", pyr_opcodes[i].name);
+
+ /* Print the operands of the insn (as specified in
+ insn.operand_mode).
+ Branch operands of branches are a special case: they are a word
+ offset, not a byte offset. */
+
+ if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
+ register int bit_codes=(insn >> 16)&0xf;
+ register int i;
+ register int displacement = (insn & 0x0000ffff) << 2;
+
+ static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */
+
+ /* Is bfc and no bits specified an unconditional branch?*/
+ for (i=0;i<4;i++) {
+ if ((bit_codes) & 0x1)
+ fputc (cc_bit_names[i], stream);
+ bit_codes >>= 1;
+ }
+
+ fprintf (stream, ",%0x",
+ displacement + memaddr);
+ return (insn_size);
+ }
+
+ switch (operand_mode) {
+ case 0:
+ fprintf (stream, "%s,%s",
+ reg_names [op_1_regno],
+ reg_names [op_2_regno]);
+ break;
+
+ case 1:
+ fprintf (stream, " 0x%0x,%s",
+ op_1_regno,
+ reg_names [op_2_regno]);
+ break;
+
+ case 2:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf (stream, " $0x%0x,%s",
+ extra_1,
+ reg_names [op_2_regno]);
+ break;
+ case 3:
+ fprintf (stream, " (%s),%s",
+ reg_names [op_1_regno],
+ reg_names [op_2_regno]);
+ break;
+
+ case 4:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf (stream, " 0x%0x(%s),%s",
+ extra_1,
+ reg_names [op_1_regno],
+ reg_names [op_2_regno]);
+ break;
+
+ /* S1 destination mode */
+ case 5:
+ fprintf (stream,
+ ((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"),
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 6:
+ fprintf (stream,
+ ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+ : " $%#0x,(%s)"),
+ op_1_regno,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 7:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf (stream,
+ ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+ : " $%#0x,(%s)"),
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 8:
+ fprintf (stream,
+ ((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"),
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 9:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf (stream,
+ ((index_reg_regno)
+ ? "%#0x(%s),(%s)[%s*%1d]"
+ : "%#0x(%s),(%s)"),
+ extra_1,
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ /* S2 destination mode */
+ case 10:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf (stream,
+ ((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
+ reg_names [op_1_regno],
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+ case 11:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf (stream,
+ ((index_reg_regno) ?
+ " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+ op_1_regno,
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+ case 12:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ read_memory (memaddr+8, buffer, MAXLEN);
+ insn_size += 4;
+ extra_2 = * ((int *) buffer);
+ fprintf (stream,
+ ((index_reg_regno) ?
+ " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+ extra_1,
+ extra_2,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 13:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf (stream,
+ ((index_reg_regno)
+ ? " (%s),%#0x(%s)[%s*%1d]"
+ : " (%s),%#0x(%s)"),
+ reg_names [op_1_regno],
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+ case 14:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ read_memory (memaddr+8, buffer, MAXLEN);
+ insn_size += 4;
+ extra_2 = * ((int *) buffer);
+ fprintf (stream,
+ ((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
+ : "%#0x(%s),%#0x(%s) "),
+ extra_1,
+ reg_names [op_1_regno],
+ extra_2,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ default:
+ fprintf (stream,
+ ((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"),
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ fprintf (stream,
+ "\t\t# unknown mode in %08x",
+ insn);
+ break;
+ } /* switch */
+ }
+
+ {
+ return insn_size;
+ }
+ abort ();
+}
--- /dev/null
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*** Prettier register printing. ***/
+
+/* Print registers in the same format as pyramid's dbx, adb, sdb. */
+pyr_print_registers(reg_buf, regnum)
+ long *reg_buf[];
+{
+ register int regno;
+ int usp, ksp;
+ struct user u;
+
+ for (regno = 0; regno < 16; regno++) {
+ printf/*_filtered*/ ("%6.6s: %8x %6.6s: %8x %6s: %8x %6s: %8x\n",
+ reg_names[regno], reg_buf[regno],
+ reg_names[regno+16], reg_buf[regno+16],
+ reg_names[regno+32], reg_buf[regno+32],
+ reg_names[regno+48], reg_buf[regno+48]);
+ }
+ usp = ptrace (3, inferior_pid,
+ ((char *)&u.u_pcb.pcb_usp) -
+ ((char *)&u), 0);
+ ksp = ptrace (3, inferior_pid,
+ ((char *)&u.u_pcb.pcb_ksp) -
+ ((char *)&u), 0);
+ printf/*_filtered*/ ("\n%6.6s: %8x %6.6s: %8x (%08x) %6.6s %8x\n",
+ reg_names[CSP_REGNUM],reg_buf[CSP_REGNUM],
+ reg_names[KSP_REGNUM], reg_buf[KSP_REGNUM], ksp,
+ "usp", usp);
+}
+
+/* Print the register regnum, or all registers if regnum is -1. */
+
+pyr_do_registers_info (regnum)
+ int regnum;
+{
+ /* On a pyr, we know a virtual register can always fit in an long.
+ Here (and elsewhere) we take advantage of that. Yuk. */
+ long raw_regs[MAX_REGISTER_RAW_SIZE*NUM_REGS];
+ register int i;
+
+ for (i = 0 ; i < 64 ; i++) {
+ read_relative_register_raw_bytes(i, raw_regs+i);
+ }
+ if (regnum == -1)
+ pyr_print_registers (raw_regs, regnum);
+ else
+ for (i = 0; i < NUM_REGS; i++)
+ if (i == regnum) {
+ long val = raw_regs[i];
+
+ fputs_filtered (reg_names[i], stdout);
+ printf_filtered(":");
+ print_spaces_filtered (6 - strlen (reg_names[i]), stdout);
+ if (val == 0)
+ printf_filtered ("0");
+ else
+ printf_filtered ("0x%08x %d", val, val);
+ printf_filtered("\n");
+ }
+}
+\f
+/*** Debugging editions of various macros from m-pyr.h ****/
+
+CORE_ADDR frame_locals_address (frame)
+ FRAME frame;
+{
+ register int addr = find_saved_register (frame,CFP_REGNUM);
+ register int result = read_memory_integer (addr, 4);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ fprintf (stderr,
+ "\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+ frame->frame,
+ reg_names[CFP_REGNUM],
+ result, addr,
+ frame->frame_cfp, (CFP_REGNUM),
+
+
+ read_register(13), read_register(29), read_register(61),
+ find_saved_register(frame, 61));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+ or at least CFP_REGNUM relative to FRAME (ie, result).
+ There seems to be a bug in the way the innermost frame is set up. */
+
+ return ((frame->next) ? result: frame->frame_cfp);
+}
+
+CORE_ADDR frame_args_addr (frame)
+ FRAME frame;
+{
+ register int addr = find_saved_register (frame,CFP_REGNUM);
+ register int result = read_memory_integer (addr, 4);
+
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ fprintf (stderr,
+ "\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+ frame->frame,
+ reg_names[CFP_REGNUM],
+ result, addr,
+ frame->frame_cfp, read_register(CFP_REGNUM),
+
+ read_register(13), read_register(29), read_register(61),
+ find_saved_register(frame, 61));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+ or at least CFP_REGNUM relative to FRAME (ie, result).
+ There seems to be a bug in the way the innermost frame is set up. */
+ return ((frame->next) ? result: frame->frame_cfp);
+}
--- /dev/null
+/* Low level Pyramid interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h> Can we live without this? */
+
+#include "gdbcore.h"
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+void
+fetch_inferior_registers ()
+{
+ register int regno, datum;
+ register unsigned int regaddr;
+ int reg_buf[NUM_REGS+1];
+ struct user u;
+ register int skipped_frames = 0;
+
+ registers_fetched ();
+
+ for (regno = 0; regno < 64; regno++) {
+ reg_buf[regno] = ptrace (3, inferior_pid, regno, 0);
+
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf ("Fetching %s from inferior, got %0x\n",
+ reg_names[regno],
+ reg_buf[regno]);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ if (reg_buf[regno] == -1 && errno == EIO) {
+ printf("fetch_interior_registers: fetching %s from inferior\n",
+ reg_names[regno]);
+ errno = 0;
+ }
+ supply_register (regno, reg_buf+regno);
+ }
+ /* that leaves regs 64, 65, and 66 */
+ datum = ptrace (3, inferior_pid,
+ ((char *)&u.u_pcb.pcb_csp) -
+ ((char *)&u), 0);
+
+
+
+ /* FIXME: Find the Current Frame Pointer (CFP). CFP is a global
+ register (ie, NOT windowed), that gets saved in a frame iff
+ the code for that frame has a prologue (ie, "adsf N"). If
+ there is a prologue, the adsf insn saves the old cfp in
+ pr13, cfp is set to sp, and N bytes of locals are allocated
+ (sp is decremented by n).
+ This makes finding CFP hard. I guess the right way to do it
+ is:
+ - If this is the innermost frame, believe ptrace() or
+ the core area.
+ - Otherwise:
+ Find the first insn of the current frame.
+ - find the saved pc;
+ - find the call insn that saved it;
+ - figure out where the call is to;
+ - if the first insn is an adsf, we got a frame
+ pointer. */
+
+
+ /* Normal processors have separate stack pointers for user and
+ kernel mode. Getting the last user mode frame on such
+ machines is easy: the kernel context of the ptrace()'d
+ process is on the kernel stack, and the USP points to what
+ we want. But Pyramids only have a single cfp for both user and
+ kernel mode. And processes being ptrace()'d have some
+ kernel-context control frames on their stack.
+ To avoid tracing back into the kernel context of an inferior,
+ we skip 0 or more contiguous control frames where the pc is
+ in the kernel. */
+
+ while (1) {
+ register int inferior_saved_pc;
+ inferior_saved_pc = ptrace (1, inferior_pid, datum+((32+15)*4), 0);
+ if (inferior_saved_pc > 0) break;
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf("skipping kernel frame %08x, pc=%08x\n", datum,
+ inferior_saved_pc);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+ skipped_frames++;
+ datum -= CONTROL_STACK_FRAME_SIZE;
+ }
+
+ reg_buf[CSP_REGNUM] = datum;
+ supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ if (skipped_frames) {
+ fprintf (stderr,
+ "skipped %d frames from %x to %x; cfp was %x, now %x\n",
+ skipped_frames, reg_buf[CSP_REGNUM]);
+ }
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ if (regno >= 0)
+ {
+ if ((0 <= regno) && (regno < 64)) {
+ /*regaddr = register_addr (regno, offset);*/
+ regaddr = regno;
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ }
+ else
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ /*regaddr = register_addr (regno, offset);*/
+ regaddr = regno;
+ errno = 0;
+ ptrace (6, inferior_pid, regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+\f
+/*** Extensions to core and dump files, for GDB. */
+
+extern unsigned int last_frame_offset;
+
+#ifdef PYRAMID_CORE
+
+/* Can't make definitions here static, since core.c needs them
+ to do bounds checking on the core-file areas. O well. */
+
+/* have two stacks: one for data, one for register windows. */
+extern CORE_ADDR reg_stack_start;
+extern CORE_ADDR reg_stack_end;
+
+/* need this so we can find the global registers: they never get saved. */
+CORE_ADDR global_reg_offset;
+static CORE_ADDR last_frame_address;
+CORE_ADDR last_frame_offset;
+
+
+/* Address in core file of start of register window stack area.
+ Don't know if is this any of meaningful, useful or necessary. */
+extern int reg_stack_offset;
+
+#endif /* PYRAMID_CORE */
+
+\f
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+#ifdef PYRAMID_CORE
+ reg_stack_start = CONTROL_STACK_ADDR;
+ reg_stack_end = CONTROL_STACK_ADDR; /* this isn't strictly true...*/
+#endif /* PYRAMID_CORE */
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* find registers in core file */
+#ifdef PYRAMID_PTRACE
+ stack_start = stack_end - NBPG * u.u_ussize;
+ reg_stack_offset = stack_offset + (NBPG *u.u_ussize);
+ reg_stack_end = reg_stack_start + NBPG * u.u_cssize;
+
+ last_frame_address = ((int) u.u_pcb.pcb_csp);
+ last_frame_offset = reg_stack_offset + last_frame_address
+ - CONTROL_STACK_ADDR ;
+ global_reg_offset = (char *)&u - (char *)&u.u_pcb.pcb_gr0 ;
+
+ /* skip any control-stack frames that were executed in the
+ kernel. */
+
+ while (1) {
+ char buf[4];
+ val = lseek (corechan, last_frame_offset+(47*4), 0);
+ if (val < 0)
+ perror_with_name (filename);
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+
+ if (*(int *)buf >= 0)
+ break;
+ printf ("skipping frame %0x\n", last_frame_address);
+ last_frame_offset -= CONTROL_STACK_FRAME_SIZE;
+ last_frame_address -= CONTROL_STACK_FRAME_SIZE;
+ }
+ reg_offset = last_frame_offset;
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf ("Control stack pointer = 0x%08x\n",
+ u.u_pcb.pcb_csp);
+ printf ("offset to control stack %d outermost frame %d (%0x)\n",
+ reg_stack_offset, reg_offset, last_frame_address);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+#else /* not PYRAMID_CORE */
+ stack_start = stack_end - NBPG * u.u_ssize;
+ reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+#endif /* not PYRAMID_CORE */
+
+#ifdef __not_on_pyr_yet
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+#endif
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < 64; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (reg_names[regno])
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+
+ if (val < 0)
+ perror_with_name (filename);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ printf ("[reg %s(%d), offset in file %s=0x%0x, addr =0x%0x, =%0x]\n",
+ reg_names[regno], regno, filename,
+ register_addr(regno, reg_offset),
+ regno * 4 + last_frame_address,
+ *((int *)buf));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf ("Providing CSP (%0x) as nominal address of current frame.\n",
+ last_frame_address);
+#endif PYRAMID_CONTROL_FRAME_DEBUGGING
+ /* FIXME: Which of the following is correct? */
+#if 0
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+#else
+ set_current_frame ( create_new_frame (last_frame_address,
+ read_pc ()));
+#endif
+
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
--- /dev/null
+/* Extended regular expression matching and search library.
+ Copyright (C) 1985, 1989 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+
+/* To test, compile with -Dtest.
+ This Dtestable feature turns this into a self-contained program
+ which reads a pattern, describes how it compiles,
+ then reads a string and searches for it. */
+
+#ifdef emacs
+
+/* The `emacs' switch turns on certain special matching commands
+ that make sense only in emacs. */
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+#else /* not emacs */
+
+#ifdef USG
+#ifndef BSTRING
+#define bcopy(s,d,n) memcpy((d),(s),(n))
+#define bcmp(s1,s2,n) memcmp((s1),(s2),(n))
+#define bzero(s,n) memset((s),0,(n))
+#endif
+#endif
+
+/* Make alloca work the best possible way. */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef sparc
+#include <alloca.h>
+#endif
+#endif
+
+/*
+ * Define the syntax stuff, so we can do the \<...\> things.
+ */
+
+#ifndef Sword /* must be non-zero in some of the tests below... */
+#define Sword 1
+#endif
+
+#define SYNTAX(c) re_syntax_table[c]
+
+#ifdef SYNTAX_TABLE
+
+char *re_syntax_table;
+
+#else
+
+static char re_syntax_table[256];
+
+static void
+init_syntax_once ()
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+
+ bzero (re_syntax_table, sizeof re_syntax_table);
+
+ for (c = 'a'; c <= 'z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = 'A'; c <= 'Z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = '0'; c <= '9'; c++)
+ re_syntax_table[c] = Sword;
+
+ done = 1;
+}
+
+#endif /* SYNTAX_TABLE */
+#endif /* not emacs */
+
+#include "regex.h"
+
+/* Number of failure points to allocate space for initially,
+ when matching. If this number is exceeded, more space is allocated,
+ so it is not a hard limit. */
+
+#ifndef NFAILURES
+#define NFAILURES 80
+#endif /* NFAILURES */
+
+/* width of a byte in bits */
+
+#define BYTEWIDTH 8
+
+#ifndef SIGN_EXTEND_CHAR
+#define SIGN_EXTEND_CHAR(x) (x)
+#endif
+\f
+static int obscure_syntax = 0;
+
+/* Specify the precise syntax of regexp for compilation.
+ This provides for compatibility for various utilities
+ which historically have different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit-mask containing the two bits
+ RE_NO_BK_PARENS and RE_NO_BK_VBAR. */
+
+int
+re_set_syntax (syntax)
+{
+ int ret;
+
+ ret = obscure_syntax;
+ obscure_syntax = syntax;
+ return ret;
+}
+\f
+/* re_compile_pattern takes a regular-expression string
+ and converts it into a buffer full of byte commands for matching.
+
+ PATTERN is the address of the pattern string
+ SIZE is the length of it.
+ BUFP is a struct re_pattern_buffer * which points to the info
+ on where to store the byte commands.
+ This structure contains a char * which points to the
+ actual space, which should have been obtained with malloc.
+ re_compile_pattern may use realloc to grow the buffer space.
+
+ The number of bytes of commands can be found out by looking in
+ the struct re_pattern_buffer that bufp pointed to,
+ after re_compile_pattern returns.
+*/
+
+#define PATPUSH(ch) (*b++ = (char) (ch))
+
+#define PATFETCH(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; \
+ if (translate) c = translate[c]; }
+
+#define PATFETCH_RAW(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; }
+
+#define PATUNFETCH p--
+
+#define EXTEND_BUFFER \
+ { char *old_buffer = bufp->buffer; \
+ if (bufp->allocated == (1<<16)) goto too_big; \
+ bufp->allocated *= 2; \
+ if (bufp->allocated > (1<<16)) bufp->allocated = (1<<16); \
+ if (!(bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated))) \
+ goto memory_exhausted; \
+ c = bufp->buffer - old_buffer; \
+ b += c; \
+ if (fixup_jump) \
+ fixup_jump += c; \
+ if (laststart) \
+ laststart += c; \
+ begalt += c; \
+ if (pending_exact) \
+ pending_exact += c; \
+ }
+
+static int store_jump (), insert_jump ();
+
+char *
+re_compile_pattern (pattern, size, bufp)
+ char *pattern;
+ int size;
+ struct re_pattern_buffer *bufp;
+{
+ register char *b = bufp->buffer;
+ register char *p = pattern;
+ char *pend = pattern + size;
+ register unsigned c, c1;
+ char *p1;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ /* address of the count-byte of the most recently inserted "exactn" command.
+ This makes it possible to tell whether a new exact-match character
+ can be added to that command or requires a new "exactn" command. */
+
+ char *pending_exact = 0;
+
+ /* address of the place where a forward-jump should go
+ to the end of the containing expression.
+ Each alternative of an "or", except the last, ends with a forward-jump
+ of this sort. */
+
+ char *fixup_jump = 0;
+
+ /* address of start of the most recently finished expression.
+ This tells postfix * where to find the start of its operand. */
+
+ char *laststart = 0;
+
+ /* In processing a repeat, 1 means zero matches is allowed */
+
+ char zero_times_ok;
+
+ /* In processing a repeat, 1 means many matches is allowed */
+
+ char many_times_ok;
+
+ /* address of beginning of regexp, or inside of last \( */
+
+ char *begalt = b;
+
+ /* Stack of information saved by \( and restored by \).
+ Four stack elements are pushed by each \(:
+ First, the value of b.
+ Second, the value of fixup_jump.
+ Third, the value of regnum.
+ Fourth, the value of begalt. */
+
+ int stackb[40];
+ int *stackp = stackb;
+ int *stacke = stackb + 40;
+ int *stackt;
+
+ /* Counts \('s as they are encountered. Remembered for the matching \),
+ where it becomes the "register number" to put in the stop_memory command */
+
+ int regnum = 1;
+
+ bufp->fastmap_accurate = 0;
+
+#ifndef emacs
+#ifndef SYNTAX_TABLE
+ /*
+ * Initialize the syntax table.
+ */
+ init_syntax_once();
+#endif
+#endif
+
+ if (bufp->allocated == 0)
+ {
+ bufp->allocated = 28;
+ if (bufp->buffer)
+ /* EXTEND_BUFFER loses when bufp->allocated is 0 */
+ bufp->buffer = (char *) realloc (bufp->buffer, 28);
+ else
+ /* Caller did not allocate a buffer. Do it for him */
+ bufp->buffer = (char *) malloc (28);
+ if (!bufp->buffer) goto memory_exhausted;
+ begalt = b = bufp->buffer;
+ }
+
+ while (p != pend)
+ {
+ if (b - bufp->buffer > bufp->allocated - 10)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ PATFETCH (c);
+
+ switch (c)
+ {
+ case '$':
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend)
+ goto normal_char;
+ /* Make operand of last vbar end before this `$'. */
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = 0;
+ PATPUSH (endline);
+ break;
+ }
+
+ /* $ means succeed if at end of line, but only in special contexts.
+ If randomly in the middle of a pattern, it is a normal character. */
+ if (p == pend || *p == '\n'
+ || (obscure_syntax & RE_CONTEXT_INDEP_OPS)
+ || (obscure_syntax & RE_NO_BK_PARENS
+ ? *p == ')'
+ : *p == '\\' && p[1] == ')')
+ || (obscure_syntax & RE_NO_BK_VBAR
+ ? *p == '|'
+ : *p == '\\' && p[1] == '|'))
+ {
+ PATPUSH (endline);
+ break;
+ }
+ goto normal_char;
+
+ case '^':
+ /* ^ means succeed if at beg of line, but only if no preceding pattern. */
+
+ if (laststart && p[-2] != '\n'
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (p != pattern + 1
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ PATPUSH (begline);
+ begalt = b;
+ }
+ else
+ PATPUSH (begline);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern, char not special. */
+ if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ /* If there is a sequence of repetition chars,
+ collapse it down to equivalent to just one. */
+ zero_times_ok = 0;
+ many_times_ok = 0;
+ while (1)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+ if (p == pend)
+ break;
+ PATFETCH (c);
+ if (c == '*')
+ ;
+ else if (!(obscure_syntax & RE_BK_PLUS_QM)
+ && (c == '+' || c == '?'))
+ ;
+ else if ((obscure_syntax & RE_BK_PLUS_QM)
+ && c == '\\')
+ {
+ int c1;
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether 0 matches is allowed,
+ and whether 2 or more matches is allowed. */
+ if (many_times_ok)
+ {
+ /* If more than one repetition is allowed,
+ put in a backward jump at the end. */
+ store_jump (b, maybe_finalize_jump, laststart - 3);
+ b += 3;
+ }
+ insert_jump (on_failure_jump, laststart, b + 3, b);
+ pending_exact = 0;
+ b += 3;
+ if (!zero_times_ok)
+ {
+ /* At least one repetition required: insert before the loop
+ a skip over the initial on-failure-jump instruction */
+ insert_jump (dummy_failure_jump, laststart, laststart + 6, b);
+ b += 3;
+ }
+ break;
+
+ case '.':
+ laststart = b;
+ PATPUSH (anychar);
+ break;
+
+ case '[':
+ while (b - bufp->buffer
+ > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ laststart = b;
+ if (*p == '^')
+ PATPUSH (charset_not), p++;
+ else
+ PATPUSH (charset);
+ p1 = p;
+
+ PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Clear the whole map */
+ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Read in characters and ranges, setting map bits */
+ while (1)
+ {
+ PATFETCH (c);
+ if (c == ']' && p != p1 + 1) break;
+ if (*p == '-' && p[1] != ']')
+ {
+ PATFETCH (c1);
+ PATFETCH (c1);
+ while (c <= c1)
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++;
+ }
+ else
+ {
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH);
+ }
+ }
+ /* Discard any bitmap bytes that are all 0 at the end of the map.
+ Decrement the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+ break;
+
+ case '(':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_open;
+
+ case ')':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_close;
+
+ case '\n':
+ if (! (obscure_syntax & RE_NEWLINE_OR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '|':
+ if (! (obscure_syntax & RE_NO_BK_VBAR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '\\':
+ if (p == pend) goto invalid_pattern;
+ PATFETCH_RAW (c);
+ switch (c)
+ {
+ case '(':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_open:
+ if (stackp == stacke) goto nesting_too_deep;
+ if (regnum < RE_NREGS)
+ {
+ PATPUSH (start_memory);
+ PATPUSH (regnum);
+ }
+ *stackp++ = b - bufp->buffer;
+ *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0;
+ *stackp++ = regnum++;
+ *stackp++ = begalt - bufp->buffer;
+ fixup_jump = 0;
+ laststart = 0;
+ begalt = b;
+ break;
+
+ case ')':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_close:
+ if (stackp == stackb) goto unmatched_close;
+ begalt = *--stackp + bufp->buffer;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ if (stackp[-1] < RE_NREGS)
+ {
+ PATPUSH (stop_memory);
+ PATPUSH (stackp[-1]);
+ }
+ stackp -= 2;
+ fixup_jump = 0;
+ if (*stackp)
+ fixup_jump = *stackp + bufp->buffer - 1;
+ laststart = *--stackp + bufp->buffer;
+ break;
+
+ case '|':
+ if (obscure_syntax & RE_NO_BK_VBAR)
+ goto normal_backsl;
+ handle_bar:
+ insert_jump (on_failure_jump, begalt, b + 6, b);
+ pending_exact = 0;
+ b += 3;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = b;
+ b += 3;
+ laststart = 0;
+ begalt = b;
+ break;
+
+#ifdef emacs
+ case '=':
+ PATPUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATPUSH (syntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATPUSH (notsyntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+#endif /* emacs */
+
+ case 'w':
+ laststart = b;
+ PATPUSH (wordchar);
+ break;
+
+ case 'W':
+ laststart = b;
+ PATPUSH (notwordchar);
+ break;
+
+ case '<':
+ PATPUSH (wordbeg);
+ break;
+
+ case '>':
+ PATPUSH (wordend);
+ break;
+
+ case 'b':
+ PATPUSH (wordbound);
+ break;
+
+ case 'B':
+ PATPUSH (notwordbound);
+ break;
+
+ case '`':
+ PATPUSH (begbuf);
+ break;
+
+ case '\'':
+ PATPUSH (endbuf);
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c - '0';
+ if (c1 >= regnum)
+ goto normal_char;
+ for (stackt = stackp - 2; stackt > stackb; stackt -= 4)
+ if (*stackt == c1)
+ goto normal_char;
+ laststart = b;
+ PATPUSH (duplicate);
+ PATPUSH (c1);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+
+ default:
+ normal_backsl:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ if (translate) c = translate[c];
+ goto normal_char;
+ }
+ break;
+
+ default:
+ normal_char:
+ if (!pending_exact || pending_exact + *pending_exact + 1 != b
+ || *pending_exact == 0177 || *p == '*' || *p == '^'
+ || ((obscure_syntax & RE_BK_PLUS_QM)
+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+ : (*p == '+' || *p == '?')))
+ {
+ laststart = b;
+ PATPUSH (exactn);
+ pending_exact = b;
+ PATPUSH (0);
+ }
+ PATPUSH (c);
+ (*pending_exact)++;
+ }
+ }
+
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+
+ if (stackp != stackb) goto unmatched_open;
+
+ bufp->used = b - bufp->buffer;
+ return 0;
+
+ invalid_pattern:
+ return "Invalid regular expression";
+
+ unmatched_open:
+ return "Unmatched \\(";
+
+ unmatched_close:
+ return "Unmatched \\)";
+
+ end_of_pattern:
+ return "Premature end of regular expression";
+
+ nesting_too_deep:
+ return "Nesting too deep";
+
+ too_big:
+ return "Regular expression too big";
+
+ memory_exhausted:
+ return "Memory exhausted";
+}
+
+/* Store where `from' points a jump operation to jump to where `to' points.
+ `opcode' is the opcode to store. */
+
+static int
+store_jump (from, opcode, to)
+ char *from, *to;
+ char opcode;
+{
+ from[0] = opcode;
+ from[1] = (to - (from + 3)) & 0377;
+ from[2] = (to - (from + 3)) >> 8;
+}
+
+/* Open up space at char FROM, and insert there a jump to TO.
+ CURRENT_END gives te end of the storage no in use,
+ so we know how much data to copy up.
+ OP is the opcode of the jump to insert.
+
+ If you call this function, you must zero out pending_exact. */
+
+static int
+insert_jump (op, from, to, current_end)
+ char op;
+ char *from, *to, *current_end;
+{
+ register char *pto = current_end + 3;
+ register char *pfrom = current_end;
+ while (pfrom != from)
+ *--pto = *--pfrom;
+ store_jump (from, op, to);
+}
+\f
+/* Given a pattern, compute a fastmap from it.
+ The fastmap records which of the (1 << BYTEWIDTH) possible characters
+ can start a string that matches the pattern.
+ This fastmap is used by re_search to skip quickly over totally implausible text.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data area
+ as bufp->fastmap.
+ The other components of bufp describe the pattern to be used. */
+
+void
+re_compile_fastmap (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *pattern = (unsigned char *) bufp->buffer;
+ int size = bufp->used;
+ register char *fastmap = bufp->fastmap;
+ register unsigned char *p = pattern;
+ register unsigned char *pend = pattern + size;
+ register int j, k;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ unsigned char *stackb[NFAILURES];
+ unsigned char **stackp = stackb;
+
+ bzero (fastmap, (1 << BYTEWIDTH));
+ bufp->fastmap_accurate = 1;
+ bufp->can_be_null = 0;
+
+ while (p)
+ {
+ if (p == pend)
+ {
+ bufp->can_be_null = 1;
+ break;
+ }
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+ case exactn:
+ if (translate)
+ fastmap[translate[p[1]]] = 1;
+ else
+ fastmap[p[1]] = 1;
+ break;
+
+ case begline:
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ continue;
+
+ case endline:
+ if (translate)
+ fastmap[translate['\n']] = 1;
+ else
+ fastmap['\n'] = 1;
+ if (bufp->can_be_null != 1)
+ bufp->can_be_null = 2;
+ break;
+
+ case finalize_jump:
+ case maybe_finalize_jump:
+ case jump:
+ case dummy_failure_jump:
+ bufp->can_be_null = 1;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (j > 0)
+ continue;
+ /* Jump backward reached implies we just went through
+ the body of a loop and matched nothing.
+ Opcode jumped to should be an on_failure_jump.
+ Just treat it like an ordinary jump.
+ For a * loop, it has pushed its failure point already;
+ if so, discard that as redundant. */
+ if ((enum regexpcode) *p != on_failure_jump)
+ continue;
+ p++;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (stackp != stackb && *stackp == p)
+ stackp--;
+ continue;
+
+ case on_failure_jump:
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *++stackp = p + j;
+ continue;
+
+ case start_memory:
+ case stop_memory:
+ p++;
+ continue;
+
+ case duplicate:
+ bufp->can_be_null = 1;
+ fastmap['\n'] = 1;
+ case anychar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (j != '\n')
+ fastmap[j] = 1;
+ if (bufp->can_be_null)
+ return;
+ /* Don't return; check the alternative paths
+ so we can set can_be_null if appropriate. */
+ break;
+
+ case wordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == Sword)
+ fastmap[j] = 1;
+ break;
+
+ case notwordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != Sword)
+ fastmap[j] = 1;
+ break;
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+#endif /* emacs */
+
+ case charset:
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+
+ case charset_not:
+ /* Chars beyond end of map must be allowed */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+ }
+
+ /* Get here means we have successfully found the possible starting characters
+ of one path of the pattern. We need not follow this path any farther.
+ Instead, look at the next alternative remembered in the stack. */
+ if (stackp != stackb)
+ p = *stackp--;
+ else
+ break;
+ }
+}
+\f
+/* Like re_search_2, below, but only one string is specified. */
+
+int
+re_search (pbufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, startpos, range;
+ struct re_registers *regs;
+{
+ return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size);
+}
+
+/* Like re_match_2 but tries first a match starting at index STARTPOS,
+ then at STARTPOS + 1, and so on.
+ RANGE is the number of places to try before giving up.
+ If RANGE is negative, the starting positions tried are
+ STARTPOS, STARTPOS - 1, etc.
+ It is up to the caller to make sure that range is not so large
+ as to take the starting position outside of the input strings.
+
+The value returned is the position at which the match was found,
+ or -1 if no match was found,
+ or -2 if error (such as failure stack overflow). */
+
+int
+re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ char *string1, *string2;
+ int size1, size2;
+ int startpos;
+ register int range;
+ struct re_registers *regs;
+ int mstop;
+{
+ register char *fastmap = pbufp->fastmap;
+ register unsigned char *translate = (unsigned char *) pbufp->translate;
+ int total = size1 + size2;
+ int val;
+
+ /* Update the fastmap now if not correct already */
+ if (fastmap && !pbufp->fastmap_accurate)
+ re_compile_fastmap (pbufp);
+
+ /* Don't waste time in a long search for a pattern
+ that says it is anchored. */
+ if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf
+ && range > 0)
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+ while (1)
+ {
+ /* If a fastmap is supplied, skip quickly over characters
+ that cannot possibly be the start of a match.
+ Note, however, that if the pattern can possibly match
+ the null string, we must test it at each starting point
+ so that we take the first null string we get. */
+
+ if (fastmap && startpos < total && pbufp->can_be_null != 1)
+ {
+ if (range > 0)
+ {
+ register int lim = 0;
+ register unsigned char *p;
+ int irange = range;
+ if (startpos < size1 && startpos + range >= size1)
+ lim = range - (size1 - startpos);
+
+ p = ((unsigned char *)
+ &(startpos >= size1 ? string2 - size1 : string1)[startpos]);
+
+ if (translate)
+ {
+ while (range > lim && !fastmap[translate[*p++]])
+ range--;
+ }
+ else
+ {
+ while (range > lim && !fastmap[*p++])
+ range--;
+ }
+ startpos += irange - range;
+ }
+ else
+ {
+ register unsigned char c;
+ if (startpos >= size1)
+ c = string2[startpos - size1];
+ else
+ c = string1[startpos];
+ c &= 0xff;
+ if (translate ? !fastmap[translate[c]] : !fastmap[c])
+ goto advance;
+ }
+ }
+
+ if (range >= 0 && startpos == total
+ && fastmap && pbufp->can_be_null == 0)
+ return -1;
+
+ val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, regs, mstop);
+ if (0 <= val)
+ {
+ if (val == -2)
+ return -2;
+ return startpos;
+ }
+
+#ifdef C_ALLOCA
+ alloca (0);
+#endif /* C_ALLOCA */
+
+ advance:
+ if (!range) break;
+ if (range > 0) range--, startpos++; else range++, startpos--;
+ }
+ return -1;
+}
+\f
+#ifndef emacs /* emacs never uses this */
+int
+re_match (pbufp, string, size, pos, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, pos;
+ struct re_registers *regs;
+{
+ return re_match_2 (pbufp, 0, 0, string, size, pos, regs, size);
+}
+#endif /* emacs */
+
+/* Maximum size of failure stack. Beyond this, overflow is an error. */
+
+int re_max_failures = 2000;
+
+static int bcmp_translate();
+/* Match the pattern described by PBUFP
+ against data which is the virtual concatenation of STRING1 and STRING2.
+ SIZE1 and SIZE2 are the sizes of the two data strings.
+ Start the match at position POS.
+ Do not consider matching past the position MSTOP.
+
+ If pbufp->fastmap is nonzero, then it had better be up to date.
+
+ The reason that the data to match are specified as two components
+ which are to be regarded as concatenated
+ is so this function can be used directly on the contents of an Emacs buffer.
+
+ -1 is returned if there is no match. -2 is returned if there is
+ an error (such as match stack overflow). Otherwise the value is the length
+ of the substring which was matched. */
+
+int
+re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ unsigned char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int mstop;
+{
+ register unsigned char *p = (unsigned char *) pbufp->buffer;
+ register unsigned char *pend = p + pbufp->used;
+ /* End of first string */
+ unsigned char *end1;
+ /* End of second string */
+ unsigned char *end2;
+ /* Pointer just past last char to consider matching */
+ unsigned char *end_match_1, *end_match_2;
+ register unsigned char *d, *dend;
+ register int mcnt;
+ unsigned char *translate = (unsigned char *) pbufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further down the line
+ pushes a failure point on this stack. It consists of two char *'s.
+ The first one pushed is where to resume scanning the pattern;
+ the second pushed is where to resume scanning the strings.
+ If the latter is zero, the failure point is a "dummy".
+ If a failure happens and the innermost failure point is dormant,
+ it discards that failure point and tries the next one. */
+
+ unsigned char *initial_stack[2 * NFAILURES];
+ unsigned char **stackb = initial_stack;
+ unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES];
+
+ /* Information on the "contents" of registers.
+ These are pointers into the input strings; they record
+ just what was matched (on this attempt) by some part of the pattern.
+ The start_memory command stores the start of a register's contents
+ and the stop_memory command stores the end.
+
+ At that point, regstart[regnum] points to the first character in the register,
+ regend[regnum] points to the first character beyond the end of the register,
+ regstart_seg1[regnum] is true iff regstart[regnum] points into string1,
+ and regend_seg1[regnum] is true iff regend[regnum] points into string1. */
+
+ unsigned char *regstart[RE_NREGS];
+ unsigned char *regend[RE_NREGS];
+ unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS];
+
+ /* Set up pointers to ends of strings.
+ Don't allow the second string to be empty unless both are empty. */
+ if (!size2)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings */
+ if (mstop <= size1)
+ {
+ end_match_1 = string1 + mstop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + mstop - size1;
+ }
+
+ /* Initialize \) text positions to -1
+ to mark ones that no \( or \) has been seen for. */
+
+ for (mcnt = 0; mcnt < sizeof (regend) / sizeof (*regend); mcnt++)
+ regend[mcnt] = (unsigned char *) -1;
+
+ /* `p' scans through the pattern as `d' scans through the data.
+ `dend' is the end of the input string that `d' points within.
+ `d' is advanced into the following input string whenever necessary,
+ but this happens before fetching;
+ therefore, at the beginning of the loop,
+ `d' can be pointing at the end of a string,
+ but it cannot equal string2. */
+
+ if (pos <= size1)
+ d = string1 + pos, dend = end_match_1;
+ else
+ d = string2 + pos - size1, dend = end_match_2;
+
+/* Write PREFETCH; just before fetching a character with *d. */
+#define PREFETCH \
+ while (d == dend) \
+ { if (dend == end_match_2) goto fail; /* end of string2 => failure */ \
+ d = string2; /* end of string1 => advance to string2. */ \
+ dend = end_match_2; }
+
+ /* This loop loops over pattern commands.
+ It exits by returning from the function if match is complete,
+ or it drops through if match fails at this starting point in the input data. */
+
+ while (1)
+ {
+ if (p == pend)
+ /* End of pattern means we have succeeded! */
+ {
+ /* If caller wants register contents data back, convert it to indices */
+ if (regs)
+ {
+ regs->start[0] = pos;
+ if (dend == end_match_1)
+ regs->end[0] = d - string1;
+ else
+ regs->end[0] = d - string2 + size1;
+ for (mcnt = 1; mcnt < RE_NREGS; mcnt++)
+ {
+ if (regend[mcnt] == (unsigned char *) -1)
+ {
+ regs->start[mcnt] = -1;
+ regs->end[mcnt] = -1;
+ continue;
+ }
+ if (regstart_seg1[mcnt])
+ regs->start[mcnt] = regstart[mcnt] - string1;
+ else
+ regs->start[mcnt] = regstart[mcnt] - string2 + size1;
+ if (regend_seg1[mcnt])
+ regs->end[mcnt] = regend[mcnt] - string1;
+ else
+ regs->end[mcnt] = regend[mcnt] - string2 + size1;
+ }
+ }
+ if (dend == end_match_1)
+ return (d - string1 - pos);
+ else
+ return d - string2 + size1 - pos;
+ }
+
+ /* Otherwise match next pattern command */
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+
+ /* \( is represented by a start_memory, \) by a stop_memory.
+ Both of those commands contain a "register number" argument.
+ The text matched within the \( and \) is recorded under that number.
+ Then, \<digit> turns into a `duplicate' command which
+ is followed by the numeric value of <digit> as the register number. */
+
+ case start_memory:
+ regstart[*p] = d;
+ regstart_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case stop_memory:
+ regend[*p] = d;
+ regend_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case duplicate:
+ {
+ int regno = *p++; /* Get which register to match against */
+ register unsigned char *d2, *dend2;
+
+ d2 = regstart[regno];
+ dend2 = ((regstart_seg1[regno] == regend_seg1[regno])
+ ? regend[regno] : end_match_1);
+ while (1)
+ {
+ /* Advance to next segment in register contents, if necessary */
+ while (d2 == dend2)
+ {
+ if (dend2 == end_match_2) break;
+ if (dend2 == regend[regno]) break;
+ d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */
+ }
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* Advance to next segment in data being matched, if necessary */
+ PREFETCH;
+
+ /* mcnt gets # consecutive chars to compare */
+ mcnt = dend - d;
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+ /* Compare that many; failure if mismatch, else skip them. */
+ if (translate ? bcmp_translate (d, d2, mcnt, translate) : bcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+ }
+ }
+ break;
+
+ case anychar:
+ /* fetch a data character */
+ PREFETCH;
+ /* Match anything but a newline. */
+ if ((translate ? translate[*d++] : *d++) == '\n')
+ goto fail;
+ break;
+
+ case charset:
+ case charset_not:
+ {
+ /* Nonzero for charset_not */
+ int not = 0;
+ register int c;
+ if (*(p - 1) == (unsigned char) charset_not)
+ not = 1;
+
+ /* fetch a data character */
+ PREFETCH;
+
+ if (translate)
+ c = translate [*d];
+ else
+ c = *d;
+
+ if (c < *p * BYTEWIDTH
+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ p += 1 + *p;
+
+ if (!not) goto fail;
+ d++;
+ break;
+ }
+
+ case begline:
+ if (d == string1 || d[-1] == '\n')
+ break;
+ goto fail;
+
+ case endline:
+ if (d == end2
+ || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n'))
+ break;
+ goto fail;
+
+ /* "or" constructs ("|") are handled by starting each alternative
+ with an on_failure_jump that points to the start of the next alternative.
+ Each alternative except the last ends with a jump to the joining point.
+ (Actually, each jump except for the last one really jumps
+ to the following jump, because tensioning the jumps is a hassle.) */
+
+ /* The start of a stupid repeat has an on_failure_jump that points
+ past the end of the repeat text.
+ This makes a failure point so that, on failure to match a repetition,
+ matching restarts past as many repetitions have been found
+ with no way to fail and look for another one. */
+
+ /* A smart repeat is similar but loops back to the on_failure_jump
+ so that each repetition makes another failure point. */
+
+ case on_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx;
+ if (stacke - stackb > re_max_failures * 2)
+ return -2;
+ stackx = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *stackp++ = mcnt + p;
+ *stackp++ = d;
+ break;
+
+ /* The end of a smart repeat has an maybe_finalize_jump back.
+ Change it either to a finalize_jump or an ordinary jump. */
+
+ case maybe_finalize_jump:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ {
+ register unsigned char *p2 = p;
+ /* Compare what follows with the begining of the repeat.
+ If we can establish that there is nothing that they would
+ both match, we can change to finalize_jump */
+ while (p2 != pend
+ && (*p2 == (unsigned char) stop_memory
+ || *p2 == (unsigned char) start_memory))
+ p2++;
+ if (p2 == pend)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (*p2 == (unsigned char) exactn
+ || *p2 == (unsigned char) endline)
+ {
+ register int c = *p2 == (unsigned char) endline ? '\n' : p2[2];
+ register unsigned char *p1 = p + mcnt;
+ /* p1[0] ... p1[2] are an on_failure_jump.
+ Examine what follows that */
+ if (p1[3] == (unsigned char) exactn && p1[5] != c)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (p1[3] == (unsigned char) charset
+ || p1[3] == (unsigned char) charset_not)
+ {
+ int not = p1[3] == (unsigned char) charset_not;
+ if (c < p1[4] * BYTEWIDTH
+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+ /* not is 1 if c would match */
+ /* That means it is not safe to finalize */
+ if (!not)
+ p[-3] = (unsigned char) finalize_jump;
+ }
+ }
+ }
+ p -= 2;
+ if (p[-1] != (unsigned char) finalize_jump)
+ {
+ p[-1] = (unsigned char) jump;
+ goto nofinalize;
+ }
+
+ /* The end of a stupid repeat has a finalize-jump
+ back to the start, where another failure point will be made
+ which will point after all the repetitions found so far. */
+
+ case finalize_jump:
+ stackp -= 2;
+
+ case jump:
+ nofinalize:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += mcnt + 1; /* The 1 compensates for missing ++ above */
+ break;
+
+ case dummy_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx
+ = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ *stackp++ = 0;
+ *stackp++ = 0;
+ goto nofinalize;
+
+ case wordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ break;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ break;
+ goto fail;
+
+ case notwordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ goto fail;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ goto fail;
+ break;
+
+ case wordbeg:
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */
+ goto fail;
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ break;
+ goto fail;
+
+ case wordend:
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ goto fail;
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */
+ break;
+ goto fail;
+
+#ifdef emacs
+ case before_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ <= point)
+ goto fail;
+ break;
+
+ case at_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ == point)
+ goto fail;
+ break;
+
+ case after_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ >= point)
+ goto fail;
+ break;
+
+ case wordchar:
+ mcnt = (int) Sword;
+ goto matchsyntax;
+
+ case syntaxspec:
+ mcnt = *p++;
+ matchsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail;
+ break;
+
+ case notwordchar:
+ mcnt = (int) Sword;
+ goto matchnotsyntax;
+
+ case notsyntaxspec:
+ mcnt = *p++;
+ matchnotsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail;
+ break;
+#else
+ case wordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) == 0) goto fail;
+ break;
+
+ case notwordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) != 0) goto fail;
+ break;
+#endif /* not emacs */
+
+ case begbuf:
+ if (d == string1) /* Note, d cannot equal string2 */
+ break; /* unless string1 == string2. */
+ goto fail;
+
+ case endbuf:
+ if (d == end2 || (d == end1 && size2 == 0))
+ break;
+ goto fail;
+
+ case exactn:
+ /* Match the next few pattern characters exactly.
+ mcnt is how many characters to match. */
+ mcnt = *p++;
+ if (translate)
+ {
+ do
+ {
+ PREFETCH;
+ if (translate[*d++] != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH;
+ if (*d++ != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ break;
+ }
+ continue; /* Successfully matched one pattern command; keep matching */
+
+ /* Jump here if any matching operation fails. */
+ fail:
+ if (stackp != stackb)
+ /* A restart point is known. Restart there and pop it. */
+ {
+ if (!stackp[-2])
+ { /* If innermost failure point is dormant, flush it and keep looking */
+ stackp -= 2;
+ goto fail;
+ }
+ d = *--stackp;
+ p = *--stackp;
+ if (d >= string1 && d <= end1)
+ dend = end_match_1;
+ }
+ else break; /* Matching at this starting point really fails! */
+ }
+ return -1; /* Failure to match */
+}
+
+static int
+bcmp_translate (s1, s2, len, translate)
+ unsigned char *s1, *s2;
+ register int len;
+ unsigned char *translate;
+{
+ register unsigned char *p1 = s1, *p2 = s2;
+ while (len)
+ {
+ if (translate [*p1++] != translate [*p2++]) return 1;
+ len--;
+ }
+ return 0;
+}
+\f
+/* Entry points compatible with bsd4.2 regex library */
+
+#ifndef emacs
+
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+ char *s;
+{
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return "No previous regular expression";
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ if (!(re_comp_buf.buffer = (char *) malloc (200)))
+ return "Memory exhausted";
+ re_comp_buf.allocated = 200;
+ if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH)))
+ return "Memory exhausted";
+ }
+ return re_compile_pattern (s, strlen (s), &re_comp_buf);
+}
+
+int
+re_exec (s)
+ char *s;
+{
+ int len = strlen (s);
+ return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0);
+}
+
+#endif /* emacs */
+\f
+#ifdef test
+
+#include <stdio.h>
+
+/* Indexed by a character, gives the upper case equivalent of the character */
+
+static char upcase[0400] =
+ { 000, 001, 002, 003, 004, 005, 006, 007,
+ 010, 011, 012, 013, 014, 015, 016, 017,
+ 020, 021, 022, 023, 024, 025, 026, 027,
+ 030, 031, 032, 033, 034, 035, 036, 037,
+ 040, 041, 042, 043, 044, 045, 046, 047,
+ 050, 051, 052, 053, 054, 055, 056, 057,
+ 060, 061, 062, 063, 064, 065, 066, 067,
+ 070, 071, 072, 073, 074, 075, 076, 077,
+ 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+ };
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char pat[80];
+ struct re_pattern_buffer buf;
+ int i;
+ char c;
+ char fastmap[(1 << BYTEWIDTH)];
+
+ /* Allow a command argument to specify the style of syntax. */
+ if (argc > 1)
+ obscure_syntax = atoi (argv[1]);
+
+ buf.allocated = 40;
+ buf.buffer = (char *) malloc (buf.allocated);
+ buf.fastmap = fastmap;
+ buf.translate = upcase;
+
+ while (1)
+ {
+ gets (pat);
+
+ if (*pat)
+ {
+ re_compile_pattern (pat, strlen(pat), &buf);
+
+ for (i = 0; i < buf.used; i++)
+ printchar (buf.buffer[i]);
+
+ putchar ('\n');
+
+ printf ("%d allocated, %d used.\n", buf.allocated, buf.used);
+
+ re_compile_fastmap (&buf);
+ printf ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (fastmap[i]) printchar (i);
+ putchar ('\n');
+ }
+
+ gets (pat); /* Now read the string to match against */
+
+ i = re_match (&buf, pat, strlen (pat), 0, 0);
+ printf ("Match value %d.\n", i);
+ }
+}
+
+#ifdef NOTDEF
+print_buf (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ int i;
+
+ printf ("buf is :\n----------------\n");
+ for (i = 0; i < bufp->used; i++)
+ printchar (bufp->buffer[i]);
+
+ printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used);
+
+ printf ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->fastmap[i])
+ printchar (i);
+ printf ("\nAllowed by translate: ");
+ if (bufp->translate)
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->translate[i])
+ printchar (i);
+ printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't");
+ printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not");
+}
+#endif
+
+printchar (c)
+ char c;
+{
+ if (c < 041 || c >= 0177)
+ {
+ putchar ('\\');
+ putchar (((c >> 6) & 3) + '0');
+ putchar (((c >> 3) & 7) + '0');
+ putchar ((c & 7) + '0');
+ }
+ else
+ putchar (c);
+}
+
+error (string)
+ char *string;
+{
+ puts (string);
+ exit (1);
+}
+
+#endif /* test */
--- /dev/null
+/* Definitions for data structures callers pass the regex library.
+ Copyright (C) 1985, 1989 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+
+/* Define number of parens for which we record the beginnings and ends.
+ This affects how much space the `struct re_registers' type takes up. */
+#ifndef RE_NREGS
+#define RE_NREGS 10
+#endif
+
+/* These bits are used in the obscure_syntax variable to choose among
+ alternative regexp syntaxes. */
+
+/* 1 means plain parentheses serve as grouping, and backslash
+ parentheses are needed for literal searching.
+ 0 means backslash-parentheses are grouping, and plain parentheses
+ are for literal searching. */
+#define RE_NO_BK_PARENS 1
+
+/* 1 means plain | serves as the "or"-operator, and \| is a literal.
+ 0 means \| serves as the "or"-operator, and | is a literal. */
+#define RE_NO_BK_VBAR 2
+
+/* 0 means plain + or ? serves as an operator, and \+, \? are literals.
+ 1 means \+, \? are operators and plain +, ? are literals. */
+#define RE_BK_PLUS_QM 4
+
+/* 1 means | binds tighter than ^ or $.
+ 0 means the contrary. */
+#define RE_TIGHT_VBAR 8
+
+/* 1 means treat \n as an _OR operator
+ 0 means treat it as a normal character */
+#define RE_NEWLINE_OR 16
+
+/* 0 means that a special characters (such as *, ^, and $) always have
+ their special meaning regardless of the surrounding context.
+ 1 means that special characters may act as normal characters in some
+ contexts. Specifically, this applies to:
+ ^ - only special at the beginning, or after ( or |
+ $ - only special at the end, or before ) or |
+ *, +, ? - only special when not after the beginning, (, or | */
+#define RE_CONTEXT_INDEP_OPS 32
+
+/* Now define combinations of bits for the standard possibilities. */
+#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS)
+#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR)
+#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
+#define RE_SYNTAX_EMACS 0
+
+/* This data structure is used to represent a compiled pattern. */
+
+struct re_pattern_buffer
+ {
+ char *buffer; /* Space holding the compiled pattern commands. */
+ int allocated; /* Size of space that buffer points to */
+ int used; /* Length of portion of buffer actually occupied */
+ char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
+ /* re_search uses the fastmap, if there is one,
+ to skip quickly over totally implausible characters */
+ char *translate; /* Translate table to apply to all characters before comparing.
+ Or zero for no translation.
+ The translation is applied to a pattern when it is compiled
+ and to data when it is matched. */
+ char fastmap_accurate;
+ /* Set to zero when a new pattern is stored,
+ set to one when the fastmap is updated from it. */
+ char can_be_null; /* Set to one by compiling fastmap
+ if this pattern might match the null string.
+ It does not necessarily match the null string
+ in that case, but if this is zero, it cannot.
+ 2 as value means can match null string
+ but at end of range or before a character
+ listed in the fastmap. */
+ };
+
+/* Structure to store "register" contents data in.
+
+ Pass the address of such a structure as an argument to re_match, etc.,
+ if you want this information back.
+
+ start[i] and end[i] record the string matched by \( ... \) grouping i,
+ for i from 1 to RE_NREGS - 1.
+ start[0] and end[0] record the entire string matched. */
+
+struct re_registers
+ {
+ int start[RE_NREGS];
+ int end[RE_NREGS];
+ };
+
+/* These are the command codes that appear in compiled regular expressions, one per byte.
+ Some command codes are followed by argument bytes.
+ A command code can specify any interpretation whatever for its arguments.
+ Zero-bytes may appear in the compiled regular expression. */
+
+enum regexpcode
+ {
+ unused,
+ exactn, /* followed by one byte giving n, and then by n literal bytes */
+ begline, /* fails unless at beginning of line */
+ endline, /* fails unless at end of line */
+ jump, /* followed by two bytes giving relative address to jump to */
+ on_failure_jump, /* followed by two bytes giving relative address of place
+ to resume at in case of failure. */
+ finalize_jump, /* Throw away latest failure point and then jump to address. */
+ maybe_finalize_jump, /* Like jump but finalize if safe to do so.
+ This is used to jump back to the beginning
+ of a repeat. If the command that follows
+ this jump is clearly incompatible with the
+ one at the beginning of the repeat, such that
+ we can be sure that there is no use backtracking
+ out of repetitions already completed,
+ then we finalize. */
+ dummy_failure_jump, /* jump, and push a dummy failure point.
+ This failure point will be thrown away
+ if an attempt is made to use it for a failure.
+ A + construct makes this before the first repeat. */
+ anychar, /* matches any one character */
+ charset, /* matches any one char belonging to specified set.
+ First following byte is # bitmap bytes.
+ Then come bytes for a bit-map saying which chars are in.
+ Bits in each byte are ordered low-bit-first.
+ A character is in the set if its bit is 1.
+ A character too large to have a bit in the map
+ is automatically not in the set */
+ charset_not, /* similar but match any character that is NOT one of those specified */
+ start_memory, /* starts remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ stop_memory, /* stops remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ duplicate, /* match a duplicate of something remembered.
+ Followed by one byte containing the index of the memory register. */
+ before_dot, /* Succeeds if before dot */
+ at_dot, /* Succeeds if at dot */
+ after_dot, /* Succeeds if after dot */
+ begbuf, /* Succeeds if at beginning of buffer */
+ endbuf, /* Succeeds if at end of buffer */
+ wordchar, /* Matches any word-constituent character */
+ notwordchar, /* Matches any char that is not a word-constituent */
+ wordbeg, /* Succeeds if at word beginning */
+ wordend, /* Succeeds if at word end */
+ wordbound, /* Succeeds if at a word boundary */
+ notwordbound, /* Succeeds if not at a word boundary */
+ syntaxspec, /* Matches any character whose syntax is specified.
+ followed by a byte which contains a syntax code, Sword or such like */
+ notsyntaxspec /* Matches any character whose syntax differs from the specified. */
+ };
+\f
+extern char *re_compile_pattern ();
+/* Is this really advertised? */
+extern void re_compile_fastmap ();
+extern int re_search (), re_search_2 ();
+extern int re_match (), re_match_2 ();
+
+/* 4.2 bsd compatibility (yuck) */
+extern char *re_comp ();
+extern int re_exec ();
+
+#ifdef SYNTAX_TABLE
+extern char *re_syntax_table;
+#endif
--- /dev/null
+/* Remote debugging interface for AMD 29000 EBMON on IBM PC, for GDB.
+ Copyright 1990-1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is like remote.c but is for an esoteric situation--
+ having a 29k board in a PC hooked up to a unix machine with
+ a serial line, and running ctty com1 on the PC, through which
+ the unix machine can run ebmon. Not to mention that the PC
+ has PC/NFS, so it can access the same executables that gdb can,
+ over the net in real time. */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "tm-29k.h"
+#include "param-no-tm.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+
+extern void add_syms_addr_command ();
+extern struct value *call_function_by_hand();
+
+extern struct target_ops eb_ops; /* Forward declaration */
+
+#define LOG_FILE "eb.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 5;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ eb_open knows that we don't have a file open when the program
+ starts. */
+int eb_desc = -1;
+
+/* stream which is fdopen'd from eb_desc. Only valid when
+ eb_desc != -1. */
+FILE *eb_stream;
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+static int
+readchar ()
+{
+ char buf;
+
+ buf = '\0';
+#ifdef HAVE_TERMIO
+ /* termio does the timeout for us. */
+ read (eb_desc, &buf, 1);
+#else
+ alarm (timeout);
+ if (read (eb_desc, &buf, 1) < 0)
+ {
+ if (errno == EINTR)
+ error ("Timeout reading from remote system.");
+ else
+ perror_with_name ("remote");
+ }
+ alarm (0);
+#endif
+
+ if (buf == '\0')
+ error ("Timeout reading from remote system.");
+#if defined (LOG_FILE)
+ putc (buf & 0x7f, log_file);
+#endif
+ return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ if (readchar() == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ p = string;
+ }
+}
+
+/* Keep discarding input until we see the ebmon prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: eb_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a eb_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt ()
+{
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush (log_file);
+#endif
+ expect ("\n# ");
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from eb_desc and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ supply_register (regno++, &val);
+ }
+}
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+#define volatile /**/
+#endif
+volatile int n_alarms;
+
+void
+eb_timer ()
+{
+#if 0
+ if (kiodebug)
+ printf ("eb_timer called\n");
+#endif
+ n_alarms++;
+}
+#endif
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+/* Nonzero if we have loaded the file ("yc") and not yet issued a "gi"
+ command. "gi" is supposed to happen exactly once for each "yc". */
+static int need_gi = 0;
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to eb_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+void
+eb_start (inferior_args)
+char *inferior_args;
+{
+ /* OK, now read in the file. Y=read, C=COFF, D=no symbols
+ 0=start address, %s=filename. */
+
+ fprintf (eb_stream, "YC D,0:%s", prog_name);
+
+ if (inferior_args != NULL)
+ fprintf(eb_stream, " %s", inferior_args);
+
+ fprintf (eb_stream, "\n");
+ fflush (eb_stream);
+
+ expect_prompt ();
+
+ need_gi = 1;
+}
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+struct {int rate, damn_b;} baudtab[] = {
+ {0, B0},
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+int damn_b (rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+ return B38400; /* Random */
+}
+
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication, then a space,
+ then the name of the program as we should name it to EBMON. */
+
+static int baudrate = 9600;
+static char *dev_name;
+void
+eb_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ TERMINAL sg;
+
+ char *p;
+
+ /* Find the first whitespace character, it separates dev_name from
+ prog_name. */
+ if (name == 0)
+ goto erroid;
+
+ for (p = name;
+ *p != '\0' && !isspace (*p); p++)
+ ;
+ if (*p == '\0')
+erroid:
+ error ("\
+Please include the name of the device for the serial port,\n\
+the baud rate, and the name of the program to run on the remote system.");
+ dev_name = alloca (p - name + 1);
+ strncpy (dev_name, name, p - name);
+ dev_name[p - name] = '\0';
+
+ /* Skip over the whitespace after dev_name */
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (1 != sscanf (p, "%d ", &baudrate))
+ goto erroid;
+
+ /* Skip the number and then the spaces */
+ for (; isdigit (*p); p++)
+ /*EMPTY*/;
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (p, strlen (p));
+
+ eb_close (0);
+
+ eb_desc = open (dev_name, O_RDWR);
+ if (eb_desc < 0)
+ perror_with_name (dev_name);
+ ioctl (eb_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+ sg.c_cc[VMIN] = 0; /* read with timeout. */
+ sg.c_cc[VTIME] = timeout * 10;
+ sg.c_lflag &= ~(ICANON | ECHO);
+ sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+ sg.sg_ispeed = damn_b (baudrate);
+ sg.sg_ospeed = damn_b (baudrate);
+ sg.sg_flags |= RAW | ANYP;
+ sg.sg_flags &= ~ECHO;
+#endif
+
+ ioctl (eb_desc, TIOCSETP, &sg);
+ eb_stream = fdopen (eb_desc, "r+");
+
+ push_target (&eb_ops);
+ if (from_tty)
+ printf ("Remote %s debugging %s using %s\n", target_shortname,
+ prog_name, dev_name);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+ /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+ the read. */
+ if (siginterrupt (SIGALRM, 1) != 0)
+ perror ("eb_open: error in siginterrupt");
+#endif
+
+ /* Set up read timeout timer. */
+ if ((void (*)) signal (SIGALRM, eb_timer) == (void (*)) -1)
+ perror ("eb_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+
+ /* Hello? Are you there? */
+ write (eb_desc, "\n", 1);
+
+ expect_prompt ();
+}
+
+/* Close out all files and local state before this target loses control. */
+
+void
+eb_close (quitting)
+ int quitting;
+{
+
+ /* Due to a bug in Unix, fclose closes not only the stdio stream,
+ but also the file descriptor. So we don't actually close
+ eb_desc. */
+ if (eb_stream)
+ fclose (eb_stream); /* This also closes eb_desc */
+ if (eb_desc >= 0)
+ /* close (eb_desc); */
+
+ /* Do not try to close eb_desc again, later in the program. */
+ eb_stream = NULL;
+ eb_desc = -1;
+
+#if defined (LOG_FILE)
+ if (ferror (log_file))
+ printf ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf ("Error closing log file.\n");
+#endif
+}
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+void
+eb_detach (from_tty)
+ int from_tty;
+{
+ pop_target(); /* calls eb_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+void
+eb_resume (step, sig)
+ int step, sig;
+{
+ if (step)
+ {
+ write (eb_desc, "t 1,s\n", 6);
+ /* Wait for the echo. */
+ expect ("t 1,s\r");
+ /* Then comes a line containing the instruction we stepped to. */
+ expect ("\n@");
+ /* Then we get the prompt. */
+ expect_prompt ();
+
+ /* Force the next eb_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type
+ "continue" to see any. This should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ {
+ if (need_gi)
+ {
+ need_gi = 0;
+ write (eb_desc, "gi\n", 3);
+
+ /* Swallow the echo of "gi". */
+ expect ("gi\r");
+ }
+ else
+ {
+ write (eb_desc, "GR\n", 3);
+ /* Swallow the echo. */
+ expect ("GR\r");
+ }
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+int
+eb_wait (status)
+ WAITTYPE *status;
+{
+ /* Strings to look for. '?' means match any single character.
+ Note that with the algorithm we use, the initial character
+ of the string cannot recur in the string, or we will not
+ find some cases of the string in the input. */
+
+ static char bpt[] = "Invalid interrupt taken - #0x50 - ";
+ /* It would be tempting to look for "\n[__exit + 0x8]\n"
+ but that requires loading symbols with "yc i" and even if
+ we did do that we don't know that the file has symbols. */
+ static char exitmsg[] = "\n@????????I JMPTI GR121,LR0";
+ char *bp = bpt;
+ char *ep = exitmsg;
+
+ /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
+ char swallowed[50];
+ /* Current position in swallowed. */
+ char *swallowed_p = swallowed;
+
+ int ch;
+ int ch_handled;
+
+ int old_timeout = timeout;
+
+ WSETEXIT ((*status), 0);
+
+ if (need_artificial_trap != 0)
+ {
+ WSETSTOP ((*status), SIGTRAP);
+ need_artificial_trap--;
+ return 0;
+ }
+
+ timeout = 0; /* Don't time out -- user program is running. */
+ while (1)
+ {
+ ch_handled = 0;
+ ch = readchar ();
+ if (ch == *bp)
+ {
+ bp++;
+ if (*bp == '\0')
+ break;
+ ch_handled = 1;
+
+ *swallowed_p++ = ch;
+ }
+ else
+ bp = bpt;
+
+ if (ch == *ep || *ep == '?')
+ {
+ ep++;
+ if (*ep == '\0')
+ break;
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+ ch_handled = 1;
+ }
+ else
+ ep = exitmsg;
+
+ if (!ch_handled)
+ {
+ char *p;
+
+ /* Print out any characters which have been swallowed. */
+ for (p = swallowed; p < swallowed_p; ++p)
+ putc (*p, stdout);
+ swallowed_p = swallowed;
+
+ putc (ch, stdout);
+ }
+ }
+ expect_prompt ();
+ if (*bp== '\0')
+ WSETSTOP ((*status), SIGTRAP);
+ else
+ WSETEXIT ((*status), 0);
+ timeout = old_timeout;
+
+ return 0;
+}
+
+/* Return the name of register number REGNO
+ in the form input and output by EBMON.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[80];
+ if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ sprintf (buf, "LR%03d", regno - LR0_REGNUM);
+ else if (regno == Q_REGNUM)
+ strcpy (buf, "SR131");
+ else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
+ sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
+ else if (regno == ALU_REGNUM)
+ strcpy (buf, "SR132");
+ else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
+ sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
+ else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM)
+ sprintf (buf, "SR%03d", regno - VAB_REGNUM);
+ else if (regno == GR1_REGNUM)
+ strcpy (buf, "GR001");
+ return buf;
+}
+
+/* Read the remote registers into the block REGS. */
+
+static void
+eb_fetch_registers ()
+{
+ int reg_index;
+ int regnum_index;
+ char tempbuf[10];
+ int i;
+
+#if 0
+ /* This should not be necessary, because one is supposed to read the
+ registers only when the inferior is stopped (at least with
+ ptrace() and why not make it the same for remote?). */
+ /* ^A is the "normal character" used to make sure we are talking to EBMON
+ and not to the program being debugged. */
+ write (eb_desc, "\001\n");
+ expect_prompt ();
+#endif
+
+ write (eb_desc, "dw gr96,gr127\n", 14);
+ for (reg_index = 96, regnum_index = GR96_REGNUM;
+ reg_index < 128;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "GR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+
+ for (i = 0; i < 128; i += 32)
+ {
+ /* The PC has a tendency to hang if we get these
+ all in one fell swoop ("dw lr0,lr127"). */
+ sprintf (tempbuf, "dw lr%d\n", i);
+ write (eb_desc, tempbuf, strlen (tempbuf));
+ for (reg_index = i, regnum_index = LR0_REGNUM + i;
+ reg_index < i + 32;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "LR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+ }
+
+ write (eb_desc, "dw sr133,sr133\n", 15);
+ expect ("SR133 ");
+ get_hex_regs (1, BP_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr134,sr134\n", 15);
+ expect ("SR134 ");
+ get_hex_regs (1, FC_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr135,sr135\n", 15);
+ expect ("SR135 ");
+ get_hex_regs (1, CR_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr131,sr131\n", 15);
+ expect ("SR131 ");
+ get_hex_regs (1, Q_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr0,sr14\n", 12);
+ for (reg_index = 0, regnum_index = VAB_REGNUM;
+ regnum_index <= LRU_REGNUM;
+ regnum_index += 4, reg_index += 4)
+ {
+ sprintf (tempbuf, "SR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (reg_index == 12 ? 3 : 4, regnum_index);
+ expect ("\n");
+ }
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, &val);
+ supply_register (INT_REGNUM, &val);
+ supply_register (FPS_REGNUM, &val);
+ supply_register (EXO_REGNUM, &val);
+ }
+
+ write (eb_desc, "dw gr1,gr1\n", 11);
+ expect ("GR001 ");
+ get_hex_regs (1, GR1_REGNUM);
+ expect_prompt ();
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ Returns errno value. */
+int
+eb_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ eb_fetch_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (eb_stream, "dw %s,%s\n", name, name);
+ expect (name);
+ expect (" ");
+ get_hex_regs (1, regno);
+ expect_prompt ();
+ }
+ return 0;
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+eb_store_registers ()
+{
+ int i, j;
+ fprintf (eb_stream, "s gr1,%x\n", read_register (GR1_REGNUM));
+ expect_prompt ();
+
+ for (j = 0; j < 32; j += 16)
+ {
+ fprintf (eb_stream, "s gr%d,", j + 96);
+ for (i = 0; i < 15; ++i)
+ fprintf (eb_stream, "%x,", read_register (GR96_REGNUM + j + i));
+ fprintf (eb_stream, "%x\n", read_register (GR96_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ for (j = 0; j < 128; j += 16)
+ {
+ fprintf (eb_stream, "s lr%d,", j);
+ for (i = 0; i < 15; ++i)
+ fprintf (eb_stream, "%x,", read_register (LR0_REGNUM + j + i));
+ fprintf (eb_stream, "%x\n", read_register (LR0_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ fprintf (eb_stream, "s sr133,%x,%x,%x\n", read_register (BP_REGNUM),
+ read_register (FC_REGNUM), read_register (CR_REGNUM));
+ expect_prompt ();
+ fprintf (eb_stream, "s sr131,%x\n", read_register (Q_REGNUM));
+ expect_prompt ();
+ fprintf (eb_stream, "s sr0,");
+ for (i = 0; i < 11; ++i)
+ fprintf (eb_stream, "%x,", read_register (VAB_REGNUM + i));
+ fprintf (eb_stream, "%x\n", read_register (VAB_REGNUM + 11));
+ expect_prompt ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+ Return errno value. */
+int
+eb_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ eb_store_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (eb_stream, "s %s,%x\n", name, read_register (regno));
+ /* Setting GR1 changes the numbers of all the locals, so
+ invalidate the register cache. Do this *after* calling
+ read_register, because we want read_register to return the
+ value that write_register has just stuffed into the registers
+ array, not the value of the register fetched from the
+ inferior. */
+ if (regno == GR1_REGNUM)
+ registers_changed ();
+ expect_prompt ();
+ }
+ return 0;
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+void
+eb_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+/* FIXME! Merge these two. */
+int
+eb_xfer_inferior_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+ if (write)
+ return eb_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return eb_write_inferior_memory (memaddr, myaddr, len);
+}
+
+void
+eb_files_info ()
+{
+ printf ("\tAttached to %s at %d baud and running program %s.\n",
+ dev_name, baudrate, prog_name);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns errno value. */
+int
+eb_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ if ((i % 16) == 0)
+ fprintf (eb_stream, "sb %x,", memaddr + i);
+ if ((i % 16) == 15 || i == len - 1)
+ {
+ fprintf (eb_stream, "%x\n", ((unsigned char *)myaddr)[i]);
+ expect_prompt ();
+ }
+ else
+ fprintf (eb_stream, "%x,", ((unsigned char *)myaddr)[i]);
+ }
+ return 0;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns errno value. */
+int
+eb_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ eb_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len to memaddr and gets 0. */
+ /* However, something like
+ eb_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr)
+ return EIO;
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+
+ fprintf (eb_stream, "db %x,%x\n", startaddr,
+ (startaddr - 1) + len_this_pass);
+ expect ("\n");
+
+ /* Look for 8 hex digits. */
+ i = 0;
+ while (1)
+ {
+ if (isxdigit (readchar ()))
+ ++i;
+ else
+ {
+ expect_prompt ();
+ error ("Hex digit expected from remote system.");
+ }
+ if (i >= 8)
+ break;
+ }
+
+ expect (" ");
+
+ for (i = 0; i < len_this_pass; i++)
+ get_hex_byte (&myaddr[count++]);
+
+ expect_prompt ();
+
+ startaddr += len_this_pass;
+ }
+ return 0;
+}
+
+/* Define the target subroutine names */
+
+struct target_ops eb_ops = {
+ "amd-eb", "Remote serial AMD EBMON target",
+ eb_open, eb_close,
+ 0, eb_detach, eb_resume, eb_wait,
+ eb_fetch_register, eb_store_register,
+ eb_prepare_to_store, 0, 0, /* conv_to, conv_from */
+ eb_xfer_inferior_memory, eb_files_info,
+ 0, 0, /* Breakpoints */
+ 0, 0, 0, 0, 0, /* Terminal handling */
+ 0, /* FIXME, kill */
+ 0, add_syms_addr_command, /* load */
+ call_function_by_hand,
+ 0, /* lookup_symbol */
+ 0, /* create_inferior FIXME, eb_start here or something? */
+ 0, /* mourn_inferior FIXME */
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_eb ()
+{
+ add_target (&eb_ops);
+}
--- /dev/null
+#!/bin/sh
+# This is a shell archive.
+# Run the file through sh to extract its contents.
+# shar: Shell Archiver
+# Run the following text with /bin/sh to create:
+# Remote_Makefile
+# remote_gutils.c
+# remote_inflow.c
+# remote_server.c
+# remote_utils.c
+# This archive created: Fri Jun 23 17:06:55 1989
+cat << \SHAR_EOF > Remote_Makefile
+# Makefile for the remote server for GDB, the GNU debugger.
+# Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# GDB is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 1, or (at your option)
+# any later version.
+#
+# GDB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+CFLAGS = -g
+CC = cc
+
+SERVER = remote_server.o\
+ remote_inflow.o\
+ remote_utils.o\
+ remote_gutils.o
+
+prog : $(SERVER)
+ $(CC) -g -o serve $(SERVER)
+SHAR_EOF
+cat << \SHAR_EOF > remote_gutils.c
+/* General utility routines for the remote server for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include "defs.h"
+
+void error ();
+void fatal ();
+
+/* Chain of cleanup actions established with make_cleanup,
+ to be executed if an error happens. */
+
+static struct cleanup *cleanup_chain;
+
+/* Nonzero means a quit has been requested. */
+
+int quit_flag;
+
+/* Nonzero means quit immediately if Control-C is typed now,
+ rather than waiting until QUIT is executed. */
+
+int immediate_quit;
+\f
+/* Add a new cleanup to the cleanup_chain,
+ and return the previous chain pointer
+ to be passed later to do_cleanups or discard_cleanups.
+ Args are FUNCTION to clean up with, and ARG to pass to it. */
+
+struct cleanup *
+make_cleanup (function, arg)
+ void (*function) ();
+ int arg;
+{
+ register struct cleanup *new
+ = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+ register struct cleanup *old_chain = cleanup_chain;
+
+ new->next = cleanup_chain;
+ new->function = function;
+ new->arg = arg;
+ cleanup_chain = new;
+
+ return old_chain;
+}
+
+/* Discard cleanups and do the actions they describe
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+do_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ (*ptr->function) (ptr->arg);
+ cleanup_chain = ptr->next;
+ free (ptr);
+ }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+discard_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ cleanup_chain = ptr->next;
+ free (ptr);
+ }
+}
+
+/* This function is useful for cleanups.
+ Do
+
+ foo = xmalloc (...);
+ old_chain = make_cleanup (free_current_contents, &foo);
+
+ to arrange to free the object thus allocated. */
+
+void
+free_current_contents (location)
+ char **location;
+{
+ free (*location);
+}
+\f
+/* Generally useful subroutines used throughout the program. */
+
+/* Like malloc but get error if no storage available. */
+
+char *
+xmalloc (size)
+ long size;
+{
+ register char *val = (char *) malloc (size);
+ if (!val)
+ fatal ("virtual memory exhausted.", 0);
+ return val;
+}
+
+/* Like realloc but get error if no storage available. */
+
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ long size;
+{
+ register char *val = (char *) realloc (ptr, size);
+ if (!val)
+ fatal ("virtual memory exhausted.", 0);
+ return val;
+}
+
+/* Print the system error message for errno, and also mention STRING
+ as the file name for which the error was encountered.
+ Then return to command level. */
+
+void
+perror_with_name (string)
+ char *string;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ extern int errno;
+ char *err;
+ char *combined;
+
+ if (errno < sys_nerr)
+ err = sys_errlist[errno];
+ else
+ err = "unknown error";
+
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ error ("%s.", combined);
+}
+
+/* Print the system error message for ERRCODE, and also mention STRING
+ as the file name for which the error was encountered. */
+
+void
+print_sys_errmsg (string, errcode)
+ char *string;
+ int errcode;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ char *err;
+ char *combined;
+
+ if (errcode < sys_nerr)
+ err = sys_errlist[errcode];
+ else
+ err = "unknown error";
+
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ printf ("%s.\n", combined);
+}
+
+void
+quit ()
+{
+ fflush (stdout);
+ ioctl (fileno (stdout), TIOCFLUSH, 0);
+ error ("Quit");
+}
+
+/* Control C comes here */
+
+void
+request_quit ()
+{
+ quit_flag = 1;
+ if (immediate_quit)
+ quit ();
+}
+
+/* Print an error message and return to command level.
+ STRING is the error message, used as a fprintf string,
+ and ARG is passed as an argument to it. */
+
+void
+error (string, arg1, arg2, arg3)
+ char *string;
+ int arg1, arg2, arg3;
+{
+ fflush (stdout);
+ fprintf (stderr, string, arg1, arg2, arg3);
+ fprintf (stderr, "\n");
+ /************return_to_top_level ();************/
+}
+
+/* Print an error message and exit reporting failure.
+ This is for a error that we cannot continue from.
+ STRING and ARG are passed to fprintf. */
+
+void
+fatal (string, arg)
+ char *string;
+ int arg;
+{
+ fprintf (stderr, "gdb: ");
+ fprintf (stderr, string, arg);
+ fprintf (stderr, "\n");
+ exit (1);
+}
+
+/* Make a copy of the string at PTR with SIZE characters
+ (and add a null character at the end in the copy).
+ Uses malloc to get the space. Returns the address of the copy. */
+
+char *
+savestring (ptr, size)
+ char *ptr;
+ int size;
+{
+ register char *p = (char *) xmalloc (size + 1);
+ bcopy (ptr, p, size);
+ p[size] = 0;
+ return p;
+}
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+ register char *val = (char *) xmalloc (len);
+ strcpy (val, s1);
+ strcat (val, s2);
+ strcat (val, s3);
+ return val;
+}
+
+void
+print_spaces (n, file)
+ register int n;
+ register FILE *file;
+{
+ while (n-- > 0)
+ fputc (' ', file);
+}
+
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+ Takes three args which are given to printf to print the question.
+ The first, a control string, should end in "? ".
+ It should not say how to answer, because we do that. */
+
+int
+query (ctlstr, arg1, arg2)
+ char *ctlstr;
+{
+ register int answer;
+
+ /* Automatically answer "yes" if input is not from a terminal. */
+ /***********if (!input_from_terminal_p ())
+ return 1; *************************/
+
+ while (1)
+ {
+ printf (ctlstr, arg1, arg2);
+ printf ("(y or n) ");
+ fflush (stdout);
+ answer = fgetc (stdin);
+ clearerr (stdin); /* in case of C-d */
+ if (answer != '\n')
+ while (fgetc (stdin) != '\n') clearerr (stdin);
+ if (answer >= 'a')
+ answer -= 040;
+ if (answer == 'Y')
+ return 1;
+ if (answer == 'N')
+ return 0;
+ printf ("Please answer y or n.\n");
+ }
+}
+\f
+/* Parse a C escape sequence. STRING_PTR points to a variable
+ containing a pointer to the string to parse. That pointer
+ is updated past the characters we use. The value of the
+ escape sequence is returned.
+
+ A negative value means the sequence \ newline was seen,
+ which is supposed to be equivalent to nothing at all.
+
+ If \ is followed by a null character, we return a negative
+ value and leave the string pointer pointing at the null character.
+
+ If \ is followed by 000, we return 0 and leave the string pointer
+ after the zeros. A value of 0 does not mean end of string. */
+
+int
+parse_escape (string_ptr)
+ char **string_ptr;
+{
+ register int c = *(*string_ptr)++;
+ switch (c)
+ {
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+ case 'e':
+ return 033;
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case '\n':
+ return -2;
+ case 0:
+ (*string_ptr)--;
+ return 0;
+ case '^':
+ c = *(*string_ptr)++;
+ if (c == '\\')
+ c = parse_escape (string_ptr);
+ if (c == '?')
+ return 0177;
+ return (c & 0200) | (c & 037);
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ register int i = c - '0';
+ register int count = 0;
+ while (++count < 3)
+ {
+ if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+ {
+ i *= 8;
+ i += c - '0';
+ }
+ else
+ {
+ (*string_ptr)--;
+ break;
+ }
+ }
+ return i;
+ }
+ default:
+ return c;
+ }
+}
+\f
+void
+printchar (ch, stream)
+ unsigned char ch;
+ FILE *stream;
+{
+ register int c = ch;
+ if (c < 040 || c >= 0177)
+ {
+ if (c == '\n')
+ fprintf (stream, "\\n");
+ else if (c == '\b')
+ fprintf (stream, "\\b");
+ else if (c == '\t')
+ fprintf (stream, "\\t");
+ else if (c == '\f')
+ fprintf (stream, "\\f");
+ else if (c == '\r')
+ fprintf (stream, "\\r");
+ else if (c == 033)
+ fprintf (stream, "\\e");
+ else if (c == '\a')
+ fprintf (stream, "\\a");
+ else
+ fprintf (stream, "\\%03o", c);
+ }
+ else
+ {
+ if (c == '\\' || c == '"' || c == '\'')
+ fputc ('\\', stream);
+ fputc (c, stream);
+ }
+}
+SHAR_EOF
+cat << \SHAR_EOF > remote_inflow.c
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+*/
+
+#include "defs.h"
+#include "param.h"
+#include "wait.h"
+#include "frame.h"
+#include "inferior.h"
+/***************************
+#include "initialize.h"
+****************************/
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#ifdef NEW_SUN_PTRACE
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#endif
+
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void error(), quit(), perror_with_name();
+int query();
+void supply_register(), write_register();
+CORE_ADDR read_register();
+
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (allargs, env)
+ char **allargs;
+ char **env;
+{
+ int pid;
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ extern int errno;
+
+ /* exec is said to fail if the executable is open. */
+ /****************close_exec_file ();*****************/
+
+ pid = vfork ();
+ if (pid < 0)
+ perror_with_name ("vfork");
+
+ if (pid == 0)
+ {
+ /* Run inferior in a separate process group. */
+ setpgrp (getpid (), getpid ());
+
+/* Not needed on Sun, at least, and loses there
+ because it clobbers the superior. */
+/*??? signal (SIGQUIT, SIG_DFL);
+ signal (SIGINT, SIG_DFL); */
+
+ errno = 0;
+ ptrace (0);
+
+ execle ("/bin/sh", "sh", "-c", allargs, 0, env);
+
+ fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+unsigned char
+resume (step, signal,status)
+ int step;
+ int signal;
+ char *status;
+{
+ int pid ;
+ WAITTYPE w;
+
+ errno = 0;
+ ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+ pid = wait(&w);
+ if(pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if(WIFEXITED(w))
+ {
+ printf("\nchild exited with retcode = %x \n",WRETCODE(w));
+ *status = 'E';
+ return((unsigned char) WRETCODE(w));
+ }
+ else if(!WIFSTOPPED(w))
+ {
+ printf("\nchild did terminated with signal = %x \n",WTERMSIG(w));
+ *status = 'T';
+ return((unsigned char) WTERMSIG(w));
+ }
+ else
+ {
+ printf("\nchild stopped with signal = %x \n",WSTOPSIG(w));
+ *status = 'S';
+ return((unsigned char) WSTOPSIG(w));
+ }
+
+}
+
+
+#ifdef NEW_SUN_PTRACE
+
+void
+fetch_inferior_registers ()
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+
+ ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+ /**********debugging begin **********/
+ print_some_registers(&inferior_registers);
+ /**********debugging end **********/
+ ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+
+ bcopy (&inferior_registers, registers, 16 * 4);
+ bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ bcopy (&inferior_fp_registers.fps_control,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+
+ bcopy (registers, &inferior_registers, 16 * 4);
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+ inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+ bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+ ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+ ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#endif /* not NEW_SUN_PTRACE */
+
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_PTRACE case.
+ It ought to be straightforward. But it appears that writing did
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+\f
+void
+try_writing_regs_command ()
+{
+ register int i;
+ register int value;
+ extern int errno;
+
+ if (inferior_pid == 0)
+ error ("There is no inferior process now.");
+
+ fetch_inferior_registers();
+ for (i = 0;i<18 ; i ++)
+ {
+ QUIT;
+ errno = 0;
+ value = read_register(i);
+ write_register ( i, value);
+ if (errno == 0)
+ {
+ printf (" Succeeded with register %d; value 0x%x (%d).\n",
+ i, value, value);
+ }
+ else
+ printf (" Failed with register %d.\n", i);
+ }
+}
+
+void
+initialize ()
+{
+
+ inferior_pid = 0;
+
+
+}
+
+
+/* Return the contents of register REGNO,
+ regarding it as an integer. */
+
+CORE_ADDR
+read_register (regno)
+ int regno;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+ return *(int *) ®isters[REGISTER_BYTE (regno)];
+}
+
+/* Store VALUE in the register number REGNO, regarded as an integer. */
+
+void
+write_register (regno, val)
+ int regno, val;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+ *(int *) ®isters[REGISTER_BYTE (regno)] = val;
+
+ if (have_inferior_p ())
+ store_inferior_registers (regno);
+}
+
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
+
+print_some_registers(regs)
+int regs[];
+{
+ register int i;
+ for (i = 0; i < 18; i++) {
+ printf("reg[%d] = %x\n", i, regs[i]);
+ }
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_server.c
+/* Main code for remote server for GDB, the GNU Debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "param.h"
+#include <stdio.h>
+
+void read_inferior_memory(), fetch_inferior_registers();
+unsigned char resume();
+void kill_inferior();
+void initialize(), try_writing_regs_command();
+int create_inferior(), read_register();
+
+extern char registers[];
+int inferior_pid;
+extern char **environ;
+
+/* Descriptor for I/O to remote machine. */
+int remote_desc;
+int kiodebug = 0;
+int remote_debugging;
+
+void remote_send ();
+void putpkt ();
+void getpkt ();
+void remote_open();
+void write_ok();
+void write_enn();
+void convert_ascii_to_int();
+void convert_int_to_ascii();
+void prepare_resume_reply();
+void decode_m_packet();
+void decode_M_packet();
+
+
+main(argc,argv)
+int argc; char *argv[];
+{
+ char ch,status, own_buf[2000], mem_buf[2000];
+ int i=0;
+ unsigned char signal;
+ unsigned int mem_addr, len;
+
+ initialize();
+ printf("\nwill open serial link\n");
+ remote_open("/dev/ttya",0);
+
+ if(argc < 2)
+ {
+ printf("Enter name of program to be run with command line args\n");
+ gets(own_buf);
+ inferior_pid = create_inferior(own_buf,environ);
+ printf("\nProcess %s created; pid = %d\n",own_buf,inferior_pid);
+ }
+ else
+ {
+ inferior_pid = create_inferior(argv[1],environ);
+ printf("\nProcess %s created; pid = %d\n",argv[1],inferior_pid);
+ }
+
+ do {
+ getpkt(own_buf);
+ printf("\nPacket received is>:%s\n",own_buf);
+ i = 0;
+ ch = own_buf[i++];
+ switch (ch) {
+ case 'h': /**********This is only for tweaking the gdb+ program *******/
+ signal = resume(1,0,&status);
+ prepare_resume_reply(own_buf,status,signal);
+ break;
+ /*************end tweak*************************************/
+
+ case 'g': fetch_inferior_registers();
+ convert_int_to_ascii(registers,own_buf,REGISTER_BYTES);
+ break;
+ case 'G': convert_ascii_to_int(&own_buf[1],registers,REGISTER_BYTES);
+ if(store_inferior_registers(-1)==0)
+ write_ok(own_buf);
+ else
+ write_enn(own_buf);
+ break;
+ case 'm': decode_m_packet(&own_buf[1],&mem_addr,&len);
+ read_inferior_memory(mem_addr,mem_buf,len);
+ convert_int_to_ascii(mem_buf,own_buf,len);
+ break;
+ case 'M': decode_M_packet(&own_buf[1],&mem_addr,&len,mem_buf);
+ if(write_inferior_memory(mem_addr,mem_buf,len)==0)
+ write_ok(own_buf);
+ else
+ write_enn(own_buf);
+ break;
+ case 'c': signal = resume(0,0,&status);
+ printf("\nSignal received is >: %0x \n",signal);
+ prepare_resume_reply(own_buf,status,signal);
+ break;
+ case 's': signal = resume(1,0,&status);
+ prepare_resume_reply(own_buf,status,signal);
+ break;
+ case 'k': kill_inferior();
+ sprintf(own_buf,"q");
+ putpkt(own_buf);
+ printf("\nObtained kill request...terminating\n");
+ close(remote_desc);
+ exit(0);
+ case 't': try_writing_regs_command();
+ own_buf[0] = '\0';
+ break;
+ default : printf("\nUnknown option chosen by master\n");
+ write_enn(own_buf);
+ break;
+ }
+
+ putpkt(own_buf);
+ } while(1) ;
+
+ close(remote_desc);
+ /** now get out of here**/
+ printf("\nFinished reading data from serial link - Bye!\n");
+ exit(0);
+
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_utils.c
+/* Remote utility routines for the remote server for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "param.h"
+#include <stdio.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <a.out.h>
+#include <sys/file.h>
+#include <sgtty.h>
+
+extern int remote_desc;
+extern int remote_debugging;
+extern int kiodebug;
+
+void remote_open();
+void remote_send();
+void putpkt();
+void getpkt();
+
+void write_ok();
+void write_enn();
+void convert_ascii_to_int();
+void convert_int_to_ascii();
+void prepare_resume_reply();
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+void
+remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ struct sgttyb sg;
+
+ remote_debugging = 0;
+
+ remote_desc = open (name, O_RDWR);
+ if (remote_desc < 0)
+ printf("\ncould not open remote device\n");
+
+ ioctl (remote_desc, TIOCGETP, &sg);
+ sg.sg_flags = RAW;
+ ioctl (remote_desc, TIOCSETP, &sg);
+
+ if (from_tty)
+ printf ("Remote debugging using %s\n", name);
+ remote_debugging = 1;
+}
+
+/* Convert hex digit A to a number. */
+
+static int
+fromhex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else
+ perror ("Reply contains invalid hex digit");
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0'+nib;
+ else
+ return 'a'+nib-10;
+}
+
+/* Send the command in BUF to the remote machine,
+ and read the reply into BUF.
+ Report an error if we get an error reply. */
+
+void
+remote_send (buf)
+ char *buf;
+{
+ putpkt (buf);
+ getpkt (buf);
+
+ if (buf[0] == 'E')
+ perror ("Remote failure reply: %s", buf);
+}
+
+/* Send a packet to the remote machine, with error checking.
+ The data of the packet is in BUF. */
+
+void
+putpkt (buf)
+ char *buf;
+{
+ int i;
+ unsigned char csum = 0;
+ char buf2[500];
+ char buf3[1];
+ int cnt = strlen (buf);
+ char *p;
+
+ if (kiodebug)
+ fprintf (stderr, "Sending packet: %s\n", buf);
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ /* Send it over and over until we get a positive ack. */
+
+ do {
+ write (remote_desc, buf2, p - buf2);
+ read (remote_desc, buf3, 1);
+ } while (buf3[0] != '+');
+}
+
+static int
+readchar ()
+{
+ char buf[1];
+ while (read (remote_desc, buf, 1) != 1) ;
+ return buf[0] & 0x7f;
+}
+
+/* Read a packet from the remote machine, with error checking,
+ and store it in BUF. */
+
+void
+getpkt (buf)
+ char *buf;
+{
+ char *bp;
+ unsigned char csum, c, c1, c2;
+ extern kiodebug;
+
+ while (1)
+ {
+ csum = 0;
+ while ((c = readchar()) != '$');
+
+ bp = buf;
+ while (1)
+ {
+ c = readchar ();
+ if (c == '#')
+ break;
+ *bp++ = c;
+ csum += c;
+ }
+ *bp = 0;
+
+ c1 = fromhex (readchar ());
+ c2 = fromhex (readchar ());
+ if (csum == (c1 << 4) + c2)
+ break;
+
+ printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+ (c1 << 4) + c2, csum, buf);
+ write (remote_desc, "-", 1);
+ }
+
+ write (remote_desc, "+", 1);
+
+ if (kiodebug)
+ fprintf (stderr,"Packet received :%s\n", buf);
+}
+
+
+void
+write_ok(buf)
+ char *buf;
+{
+ buf[0] = 'O';
+ buf[1] = 'k';
+ buf[2] = '\0';
+}
+
+void
+write_enn(buf)
+ char *buf;
+{
+ buf[0] = 'E';
+ buf[1] = 'N';
+ buf[2] = 'N';
+ buf[3] = '\0';
+}
+
+void
+convert_int_to_ascii(from,to,n)
+char *from, *to; int n;
+{
+ int nib ;
+ char ch;
+ while( n-- )
+ {
+ ch = *from++;
+ nib = ((ch & 0xf0) >> 4)& 0x0f;
+ *to++ = tohex(nib);
+ nib = ch & 0x0f;
+ *to++ = tohex(nib);
+ }
+ *to++ = 0;
+}
+
+
+void
+convert_ascii_to_int(from,to,n)
+char *from, *to; int n;
+{
+ int nib1,nib2 ;
+ while( n-- )
+ {
+ nib1 = fromhex(*from++);
+ nib2 = fromhex(*from++);
+ *to++ = (((nib1 & 0x0f)<< 4)& 0xf0) | (nib2 & 0x0f);
+ }
+}
+
+void
+prepare_resume_reply(buf,status,signal)
+char *buf ,status;
+unsigned char signal;
+{
+ int nib;
+ char ch;
+
+ *buf++ = 'S';
+ *buf++ = status;
+ nib = ((signal & 0xf0) >> 4) ;
+ *buf++ = tohex(nib);
+ nib = signal & 0x0f;
+ *buf++ = tohex(nib);
+ *buf++ = 0;
+}
+
+void
+decode_m_packet(from,mem_addr_ptr,len_ptr)
+char *from;
+unsigned int *mem_addr_ptr, *len_ptr;
+{
+ int i = 0, j = 0 ;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+ /************debugging begin************/
+ printf("\nIn decode_m_packet");
+ /************debugging end************/
+
+ while((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished mem_addr part");
+ /************debugging end************/
+
+ for(j=0; j < 4; j++)
+ {
+ if((ch = from[i++]) == 0)
+ break;
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished len_ptr part");
+ /************debugging end************/
+}
+
+void
+decode_M_packet(from,mem_addr_ptr,len_ptr,to)
+char *from, *to;
+unsigned int *mem_addr_ptr, *len_ptr;
+{
+ int i = 0, j = 0 ;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+ /************debugging begin************/
+ printf("\nIn decode_M_packet");
+ /************debugging end************/
+
+ while((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished mem_addr part: memaddr = %x",*mem_addr_ptr);
+ /************debugging end************/
+
+ while((ch = from[i++]) != ':')
+ {
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished len_ptr part: len = %d",*len_ptr);
+ /************debugging end************/
+
+ convert_ascii_to_int(&from[i++],to,*len_ptr);
+
+ /************debugging begin************/
+ printf("\nmembuf : %x",*(int *)to);
+ /************debugging end************/
+}
+
+SHAR_EOF
+# End of shell archive
+exit 0
--- /dev/null
+/* Memory-access and commands for remote NINDY process, for GDB.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation. Modified from remote.c by Chris Benenati.
+
+GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY. No author or distributor accepts responsibility to anyone
+for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.
+Refer to the GDB General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute GDB,
+but only under the conditions described in the GDB General Public
+License. A copy of this license is supposed to have been given to you
+along with GDB so you can know your rights and responsibilities. It
+should be in a file named COPYING. Among other things, the copyright
+notice and this notice must be preserved on all copies.
+
+In other words, go ahead and share GDB, but don't try to stop
+anyone else from sharing it farther. Help stamp out software hoarding!
+*/
+
+/*
+Except for the data cache routines, this file bears little resemblence
+to remote.c. A new (although similar) protocol has been specified, and
+portions of the code are entirely dependent on having an i80960 with a
+NINDY ROM monitor at the other end of the line.
+*/
+
+/*****************************************************************************
+ *
+ * REMOTE COMMUNICATION PROTOCOL BETWEEN GDB960 AND THE NINDY ROM MONITOR.
+ *
+ *
+ * MODES OF OPERATION
+ * ----- -- ---------
+ *
+ * As far as NINDY is concerned, GDB is always in one of two modes: command
+ * mode or passthrough mode.
+ *
+ * In command mode (the default) pre-defined packets containing requests
+ * are sent by GDB to NINDY. NINDY never talks except in reponse to a request.
+ *
+ * Once the the user program is started, GDB enters passthrough mode, to give
+ * the user program access to the terminal. GDB remains in this mode until
+ * NINDY indicates that the program has stopped.
+ *
+ *
+ * PASSTHROUGH MODE
+ * ----------- ----
+ *
+ * GDB writes all input received from the keyboard directly to NINDY, and writes
+ * all characters received from NINDY directly to the monitor.
+ *
+ * Keyboard input is neither buffered nor echoed to the monitor.
+ *
+ * GDB remains in passthrough mode until NINDY sends a single ^P character,
+ * to indicate that the user process has stopped.
+ *
+ * Note:
+ * GDB assumes NINDY performs a 'flushreg' when the user program stops.
+ *
+ *
+ * COMMAND MODE
+ * ------- ----
+ *
+ * All info (except for message ack and nak) is transferred between gdb
+ * and the remote processor in messages of the following format:
+ *
+ * <info>#<checksum>
+ *
+ * where
+ * # is a literal character
+ *
+ * <info> ASCII information; all numeric information is in the
+ * form of hex digits ('0'-'9' and lowercase 'a'-'f').
+ *
+ * <checksum>
+ * is a pair of ASCII hex digits representing an 8-bit
+ * checksum formed by adding together each of the
+ * characters in <info>.
+ *
+ * The receiver of a message always sends a single character to the sender
+ * to indicate that the checksum was good ('+') or bad ('-'); the sender
+ * re-transmits the entire message over until a '+' is received.
+ *
+ * In response to a command NINDY always sends back either data or
+ * a result code of the form "Xnn", where "nn" are hex digits and "X00"
+ * means no errors. (Exceptions: the "s" and "c" commands don't respond.)
+ *
+ * SEE THE HEADER OF THE FILE "gdb.c" IN THE NINDY MONITOR SOURCE CODE FOR A
+ * FULL DESCRIPTION OF LEGAL COMMANDS.
+ *
+ * SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
+ * OF STOP CODES.
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <setjmp.h>
+
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "bfd.h"
+#include "ieee-float.h"
+
+#include "wait.h"
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <ctype.h>
+#include "nindy-share/ttycntl.h"
+#include "nindy-share/demux.h"
+#include "nindy-share/env.h"
+#include "nindy-share/stop.h"
+
+extern int unlink();
+extern char *getenv();
+extern char *mktemp();
+
+extern char *coffstrip();
+extern void add_syms_addr_command ();
+extern value call_function_by_hand ();
+extern void generic_mourn_inferior ();
+
+extern struct target_ops nindy_ops;
+extern jmp_buf to_top_level;
+extern FILE *instream;
+extern struct ext_format ext_format_i960[]; /* i960-tdep.c */
+
+extern char ninStopWhy ();
+
+int nindy_initial_brk; /* nonzero if want to send an initial BREAK to nindy */
+int nindy_old_protocol; /* nonzero if want to use old protocol */
+char *nindy_ttyname; /* name of tty to talk to nindy on, or null */
+
+#define DLE '\020' /* Character NINDY sends to indicate user program has
+ * halted. */
+#define TRUE 1
+#define FALSE 0
+
+int nindy_fd = 0; /* Descriptor for I/O to NINDY */
+static int have_regs = 0; /* 1 iff regs read since i960 last halted */
+static int regs_changed = 0; /* 1 iff regs were modified since last read */
+
+extern char *exists();
+static void dcache_flush (), dcache_poke (), dcache_init();
+static int dcache_fetch ();
+\f
+/* FIXME, we can probably use the normal terminal_inferior stuff here.
+ We have to do terminal_inferior and then set up the passthrough
+ settings initially. Thereafter, terminal_ours and terminal_inferior
+ will automatically swap the settings around for us. */
+
+/* Restore TTY to normal operation */
+
+static TTY_STRUCT orig_tty; /* TTY attributes before entering passthrough */
+
+static void
+restore_tty()
+{
+ ioctl( 0, TIOCSETN, &orig_tty );
+}
+
+
+/* Recover from ^Z or ^C while remote process is running */
+
+static void (*old_ctrlc)(); /* Signal handlers before entering passthrough */
+
+#ifdef SIGTSTP
+static void (*old_ctrlz)();
+#endif
+
+static
+#ifdef USG
+void
+#endif
+cleanup()
+{
+ restore_tty();
+ signal(SIGINT, old_ctrlc);
+#ifdef SIGTSTP
+ signal(SIGTSTP, old_ctrlz);
+#endif
+ error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
+}
+\f
+/* Clean up anything that needs cleaning when losing control. */
+
+static char *savename;
+
+static void
+nindy_close (quitting)
+ int quitting;
+{
+ if (nindy_fd)
+ close (nindy_fd);
+ nindy_fd = 0;
+
+ if (savename)
+ free (savename);
+ savename = 0;
+}
+
+/* Open a connection to a remote debugger.
+ FIXME, there should be a way to specify the various options that are
+ now specified with gdb command-line options. (baud_rate, old_protocol,
+ and initial_brk) */
+void
+nindy_open (name, from_tty)
+ char *name; /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
+ int from_tty;
+{
+
+ if (!name)
+ error_no_arg ("serial port device name");
+
+ nindy_close (0);
+
+ have_regs = regs_changed = 0;
+ dcache_init();
+
+ /* Allow user to interrupt the following -- we could hang if
+ * there's no NINDY at the other end of the remote tty.
+ */
+ immediate_quit++;
+ nindy_fd = ninConnect( name, baud_rate? baud_rate: "9600",
+ nindy_initial_brk, !from_tty, nindy_old_protocol );
+ immediate_quit--;
+
+ if ( nindy_fd < 0 ){
+ nindy_fd = 0;
+ error( "Can't open tty '%s'", name );
+ }
+
+ savename = savestring (name, strlen (name));
+ push_target (&nindy_ops);
+ target_fetch_registers(-1);
+}
+
+/* User-initiated quit of nindy operations. */
+
+static void
+nindy_detach (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ dont_repeat ();
+ if (name)
+ error ("Too many arguments");
+ pop_target ();
+}
+
+static void
+nindy_files_info ()
+{
+ printf("\tAttached to %s at %s bps%s%s.\n", savename,
+ baud_rate? baud_rate: "9600",
+ nindy_old_protocol? " in old protocol": "",
+ nindy_initial_brk? " with initial break": "");
+}
+\f
+/******************************************************************************
+ * remote_load:
+ * Download an object file to the remote system by invoking the "comm960"
+ * utility. We look for "comm960" in $G960BIN, $G960BASE/bin, and
+ * DEFAULT_BASE/bin/HOST/bin where
+ * DEFAULT_BASE is defined in env.h, and
+ * HOST must be defined on the compiler invocation line.
+ ******************************************************************************/
+
+static void
+nindy_load( filename, from_tty )
+ char *filename;
+ int from_tty;
+{
+ char *tmpfile;
+ struct cleanup *old_chain;
+ char *scratch_pathname;
+ int scratch_chan;
+
+ if (!filename)
+ filename = get_exec_file (1);
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &scratch_pathname);
+ if (scratch_chan < 0)
+ perror_with_name (filename);
+ close (scratch_chan); /* Slightly wasteful FIXME */
+
+ have_regs = regs_changed = 0;
+ mark_breakpoints_out();
+ inferior_pid = 0;
+ dcache_flush();
+
+ tmpfile = coffstrip(scratch_pathname);
+ if ( tmpfile ){
+ old_chain = make_cleanup(unlink,tmpfile);
+ immediate_quit++;
+ ninDownload( tmpfile, !from_tty );
+/* FIXME, don't we want this merged in here? */
+ immediate_quit--;
+ do_cleanups (old_chain);
+ }
+}
+
+
+
+/* Return the number of characters in the buffer before the first DLE character.
+ */
+
+static
+int
+non_dle( buf, n )
+ char *buf; /* Character buffer; NOT '\0'-terminated */
+ int n; /* Number of characters in buffer */
+{
+ int i;
+
+ for ( i = 0; i < n; i++ ){
+ if ( buf[i] == DLE ){
+ break;
+ }
+ }
+ return i;
+}
+\f
+/* Tell the remote machine to resume. */
+
+void
+nindy_resume (step, siggnal)
+ int step, siggnal;
+{
+ if (siggnal != 0 && siggnal != stop_signal)
+ error ("Can't send signals to remote NINDY targets.");
+
+ dcache_flush();
+ if ( regs_changed ){
+ nindy_store_registers ();
+ regs_changed = 0;
+ }
+ have_regs = 0;
+ ninGo( step );
+}
+
+/* Wait until the remote machine stops. While waiting, operate in passthrough
+ * mode; i.e., pass everything NINDY sends to stdout, and everything from
+ * stdin to NINDY.
+ *
+ * Return to caller, storing status in 'status' just as `wait' would.
+ */
+
+void
+nindy_wait( status )
+ WAITTYPE *status;
+{
+ DEMUX_DECL; /* OS-dependent data needed by DEMUX... macros */
+ char buf[500]; /* FIXME, what is "500" here? */
+ int i, n;
+ unsigned char stop_exit;
+ unsigned char stop_code;
+ TTY_STRUCT tty;
+ long ip_value, fp_value, sp_value; /* Reg values from stop */
+
+
+ WSETEXIT( (*status), 0 );
+
+ /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
+
+ /* Save current tty attributes, set up signals to restore them.
+ */
+ ioctl( 0, TIOCGETP, &orig_tty );
+ old_ctrlc = signal( SIGINT, cleanup );
+#ifdef SIGTSTP
+ old_ctrlz = signal( SIGTSTP, cleanup );
+#endif
+
+ /* Pass input from keyboard to NINDY as it arrives.
+ * NINDY will interpret <CR> and perform echo.
+ */
+ tty = orig_tty;
+ TTY_NINDYTERM( tty );
+ ioctl( 0, TIOCSETN, &tty );
+
+ while ( 1 ){
+ /* Go to sleep until there's something for us on either
+ * the remote port or stdin.
+ */
+
+ DEMUX_WAIT( nindy_fd );
+
+ /* Pass input through to correct place */
+
+ n = DEMUX_READ( 0, buf, sizeof(buf) );
+ if ( n ){ /* Input on stdin */
+ write( nindy_fd, buf, n );
+ }
+
+ n = DEMUX_READ( nindy_fd, buf, sizeof(buf) );
+ if ( n ){ /* Input on remote */
+ /* Write out any characters in buffer preceding DLE */
+ i = non_dle( buf, n );
+ if ( i > 0 ){
+ write( 1, buf, i );
+ }
+
+ if ( i != n ){
+ /* There *was* a DLE in the buffer */
+ stop_exit = ninStopWhy( &stop_code,
+ &ip_value, &fp_value, &sp_value);
+ if ( !stop_exit && (stop_code==STOP_SRQ) ){
+ immediate_quit++;
+ ninSrq();
+ immediate_quit--;
+ } else {
+ /* Get out of loop */
+ supply_register (IP_REGNUM, &ip_value);
+ supply_register (FP_REGNUM, &fp_value);
+ supply_register (SP_REGNUM, &sp_value);
+ break;
+ }
+ }
+ }
+ }
+
+ signal( SIGINT, old_ctrlc );
+#ifdef SIGTSTP
+ signal( SIGTSTP, old_ctrlz );
+#endif
+ restore_tty();
+
+ if ( stop_exit ){ /* User program exited */
+ WSETEXIT( (*status), stop_code );
+ } else { /* Fault or trace */
+ switch (stop_code){
+ case STOP_GDB_BPT:
+ case TRACE_STEP:
+ /* Make it look like a VAX trace trap */
+ stop_code = SIGTRAP;
+ break;
+ default:
+ /* The target is not running Unix, and its
+ faults/traces do not map nicely into Unix signals.
+ Make sure they do not get confused with Unix signals
+ by numbering them with values higher than the highest
+ legal Unix signal. code in i960_print_fault(),
+ called via PRINT_RANDOM_SIGNAL, will interpret the
+ value. */
+ stop_code += NSIG;
+ break;
+ }
+ WSETSTOP( (*status), stop_code );
+ }
+}
+
+/* Read the remote registers into the block REGS. */
+
+/* This is the block that ninRegsGet and ninRegsPut handles. */
+struct nindy_regs {
+ char local_regs[16 * 4];
+ char global_regs[16 * 4];
+ char pcw_acw[2 * 4];
+ char ip[4];
+ char tcw[4];
+ char fp_as_double[4 * 8];
+};
+
+static int
+nindy_fetch_registers(regno)
+ int regno;
+{
+ struct nindy_regs nindy_regs;
+ int regnum, inv;
+ double dub;
+
+ immediate_quit++;
+ ninRegsGet( (char *) &nindy_regs );
+ immediate_quit--;
+
+ bcopy (nindy_regs.local_regs, ®isters[REGISTER_BYTE (R0_REGNUM)], 16*4);
+ bcopy (nindy_regs.global_regs, ®isters[REGISTER_BYTE (G0_REGNUM)], 16*4);
+ bcopy (nindy_regs.pcw_acw, ®isters[REGISTER_BYTE (PCW_REGNUM)], 2*4);
+ bcopy (nindy_regs.ip, ®isters[REGISTER_BYTE (IP_REGNUM)], 1*4);
+ bcopy (nindy_regs.tcw, ®isters[REGISTER_BYTE (TCW_REGNUM)], 1*4);
+ for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
+ dub = unpack_double (builtin_type_double,
+ &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
+ &inv);
+ /* dub now in host byte order */
+ double_to_ieee_extended (ext_format_i960, &dub,
+ ®isters[REGISTER_BYTE (regnum)]);
+ }
+
+ registers_fetched ();
+ return 0;
+}
+
+static void
+nindy_prepare_to_store()
+{
+ nindy_fetch_registers(-1);
+}
+
+static int
+nindy_store_registers(regno)
+ int regno;
+{
+ struct nindy_regs nindy_regs;
+ int regnum, inv;
+ double dub;
+
+ bcopy (®isters[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4);
+ bcopy (®isters[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
+ bcopy (®isters[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4);
+ bcopy (®isters[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4);
+ bcopy (®isters[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4);
+ /* Float regs. Only works on IEEE_FLOAT hosts. */
+ for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
+ ieee_extended_to_double (ext_format_i960,
+ ®isters[REGISTER_BYTE (regnum)], &dub);
+ /* dub now in host byte order */
+ /* FIXME-someday, the arguments to unpack_double are backward.
+ It expects a target double and returns a host; we pass the opposite.
+ This mostly works but not quite. */
+ dub = unpack_double (builtin_type_double, &dub, &inv);
+ /* dub now in target byte order */
+ bcopy ((char *)&dub, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
+ 8);
+ }
+
+ immediate_quit++;
+ ninRegsPut( (char *) &nindy_regs );
+ immediate_quit--;
+ return 0;
+}
+
+/* Read a word from remote address ADDR and return it.
+ * This goes through the data cache.
+ */
+int
+nindy_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ return dcache_fetch (addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+void
+nindy_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (addr, word);
+}
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. Copy to inferior if
+ WRITE is nonzero. Returns the length copied.
+
+ This is stolen almost directly from infptrace.c's child_xfer_memory,
+ which also deals with a word-oriented memory interface. Sometime,
+ FIXME, rewrite this to not use the word-oriented routines. */
+
+int
+nindy_xfer_inferior_memory(memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int)sizeof (int)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = nindy_fetch_word (addr);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = nindy_fetch_word (addr + (count - 1) * sizeof (int));
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ nindy_store_word (addr, buffer[i]);
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ buffer[i] = nindy_fetch_word (addr);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+ }
+ return len;
+}
+\f
+/* The data cache records all the data read from the remote machine
+ since the last time it stopped.
+
+ Each cache block holds 16 bytes of data
+ starting at a multiple-of-16 address. */
+
+#define DCACHE_SIZE 64 /* Number of cache blocks */
+
+struct dcache_block {
+ struct dcache_block *next, *last;
+ unsigned int addr; /* Address for which data is recorded. */
+ int data[4];
+};
+
+struct dcache_block dcache_free, dcache_valid;
+
+/* Free all the data cache blocks, thus discarding all cached data. */
+static
+void
+dcache_flush ()
+{
+ register struct dcache_block *db;
+
+ while ((db = dcache_valid.next) != &dcache_valid)
+ {
+ remque (db);
+ insque (db, &dcache_free);
+ }
+}
+
+/*
+ * If addr is present in the dcache, return the address of the block
+ * containing it.
+ */
+static
+struct dcache_block *
+dcache_hit (addr)
+ unsigned int addr;
+{
+ register struct dcache_block *db;
+
+ if (addr & 3)
+ abort ();
+
+ /* Search all cache blocks for one that is at this address. */
+ db = dcache_valid.next;
+ while (db != &dcache_valid)
+ {
+ if ((addr & 0xfffffff0) == db->addr)
+ return db;
+ db = db->next;
+ }
+ return NULL;
+}
+
+/* Return the int data at address ADDR in dcache block DC. */
+static
+int
+dcache_value (db, addr)
+ struct dcache_block *db;
+ unsigned int addr;
+{
+ if (addr & 3)
+ abort ();
+ return (db->data[(addr>>2)&3]);
+}
+
+/* Get a free cache block, put or keep it on the valid list,
+ and return its address. The caller should store into the block
+ the address and data that it describes, then remque it from the
+ free list and insert it into the valid list. This procedure
+ prevents errors from creeping in if a ninMemGet is interrupted
+ (which used to put garbage blocks in the valid list...). */
+static
+struct dcache_block *
+dcache_alloc ()
+{
+ register struct dcache_block *db;
+
+ if ((db = dcache_free.next) == &dcache_free)
+ {
+ /* If we can't get one from the free list, take last valid and put
+ it on the free list. */
+ db = dcache_valid.last;
+ remque (db);
+ insque (db, &dcache_free);
+ }
+
+ remque (db);
+ insque (db, &dcache_valid);
+ return (db);
+}
+
+/* Return the contents of the word at address ADDR in the remote machine,
+ using the data cache. */
+static
+int
+dcache_fetch (addr)
+ CORE_ADDR addr;
+{
+ register struct dcache_block *db;
+
+ db = dcache_hit (addr);
+ if (db == 0)
+ {
+ db = dcache_alloc ();
+ immediate_quit++;
+ ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
+ immediate_quit--;
+ db->addr = addr & ~0xf;
+ remque (db); /* Off the free list */
+ insque (db, &dcache_valid); /* On the valid list */
+ }
+ return (dcache_value (db, addr));
+}
+
+/* Write the word at ADDR both in the data cache and in the remote machine. */
+static void
+dcache_poke (addr, data)
+ CORE_ADDR addr;
+ int data;
+{
+ register struct dcache_block *db;
+
+ /* First make sure the word is IN the cache. DB is its cache block. */
+ db = dcache_hit (addr);
+ if (db == 0)
+ {
+ db = dcache_alloc ();
+ immediate_quit++;
+ ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
+ immediate_quit--;
+ db->addr = addr & ~0xf;
+ remque (db); /* Off the free list */
+ insque (db, &dcache_valid); /* On the valid list */
+ }
+
+ /* Modify the word in the cache. */
+ db->data[(addr>>2)&3] = data;
+
+ /* Send the changed word. */
+ immediate_quit++;
+ ninMemPut(addr, (unsigned char *)&data, 4);
+ immediate_quit--;
+}
+
+/* The cache itself. */
+struct dcache_block the_cache[DCACHE_SIZE];
+
+/* Initialize the data cache. */
+static void
+dcache_init ()
+{
+ register i;
+ register struct dcache_block *db;
+
+ db = the_cache;
+ dcache_free.next = dcache_free.last = &dcache_free;
+ dcache_valid.next = dcache_valid.last = &dcache_valid;
+ for (i=0;i<DCACHE_SIZE;i++,db++)
+ insque (db, &dcache_free);
+}
+
+
+static void
+nindy_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+ int pid;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote NINDY process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ pid = 42;
+
+#ifdef CREATE_INFERIOR_HOOK
+ CREATE_INFERIOR_HOOK (pid);
+#endif
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ inferior_pid = pid; /* Needed for wait_for_inferior below */
+
+ clear_proceed_status ();
+
+#if defined (START_INFERIOR_HOOK)
+ START_INFERIOR_HOOK ();
+#endif
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* remote_start(args); */
+ /* trap_expected = 0; */
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed ((CORE_ADDR)entry_pt, -1, 0); /* Let 'er rip... */
+}
+
+static void
+reset_command(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if ( !nindy_fd ){
+ error( "No target system to reset -- use 'target nindy' command.");
+ }
+ if ( query("Really reset the target system?",0,0) ){
+ send_break( nindy_fd );
+ tty_flush( nindy_fd );
+ }
+}
+
+void
+nindy_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+void
+nindy_mourn_inferior ()
+{
+ remove_breakpoints ();
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+\f
+/* This routine is run as a hook, just before the main command loop is
+ entered. If gdb is configured for the i960, but has not had its
+ nindy target specified yet, this will loop prompting the user to do so.
+
+ Unlike the loop provided by Intel, we actually let the user get out
+ of this with a RETURN. This is useful when e.g. simply examining
+ an i960 object file on the host system. */
+
+nindy_before_main_loop ()
+{
+ char ttyname[100];
+ char *p, *p2;
+
+ setjmp(to_top_level);
+ while (current_target != &nindy_ops) { /* remote tty not specified yet */
+ if ( instream == stdin ){
+ printf("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
+ fflush( stdout );
+ }
+ fgets( ttyname, sizeof(ttyname)-1, stdin );
+
+ /* Strip leading and trailing whitespace */
+ for ( p = ttyname; isspace(*p); p++ ){
+ ;
+ }
+ if ( *p == '\0' ){
+ return; /* User just hit spaces or return, wants out */
+ }
+ for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
+ ;
+ }
+ *p2= '\0';
+ if ( !strcmp("quit",p) ){
+ exit(1);
+ }
+
+ nindy_open( p, 1 );
+
+ /* Now that we have a tty open for talking to the remote machine,
+ download the executable file if one was specified. */
+ if ( !setjmp(to_top_level) && exec_bfd ) {
+ target_load (bfd_get_filename (exec_bfd), 1);
+ }
+ }
+}
+\f
+/* Define the target subroutine names */
+
+struct target_ops nindy_ops = {
+ "nindy", "Remote serial target in i960 NINDY-specific protocol",
+ nindy_open, nindy_close,
+ 0, nindy_detach, nindy_resume, nindy_wait,
+ nindy_fetch_registers, nindy_store_registers,
+ nindy_prepare_to_store, 0, 0, /* conv_from, conv_to */
+ nindy_xfer_inferior_memory, nindy_files_info,
+ 0, 0, /* insert_breakpoint, remove_breakpoint, */
+ 0, 0, 0, 0, 0, /* Terminal crud */
+ nindy_kill,
+ nindy_load, add_syms_addr_command,
+ call_function_by_hand,
+ 0, /* lookup_symbol */
+ nindy_create_inferior,
+ nindy_mourn_inferior,
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_nindy ()
+{
+ add_target (&nindy_ops);
+ add_com ("reset", class_obscure, reset_command,
+ "Send a 'break' to the remote target system.\n\
+Only useful if the target has been equipped with a circuit\n\
+to perform a hard reset when a break is detected.");
+}
--- /dev/null
+/* Memory-access and commands for remote VxWorks processes, for GDB.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Contributed by Wind River Systems and Cygnus Support.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#define free bogon_free /* Sun claims "int free()" not void */
+#include <rpc/rpc.h>
+#undef free
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include <ptrace.h>
+#include "xdr_ptrace.h"
+#include "xdr_ld.h"
+#include "xdr_rdb.h"
+#include "dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+extern value call_function_by_hand ();
+extern void symbol_file_command ();
+extern void add_syms_addr_command ();
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+static int net_ptrace_clnt_call (); /* Forward decl */
+static enum clnt_stat net_clnt_call (); /* Forward decl */
+extern struct target_ops vx_ops, vx_run_ops; /* Forward declaration */
+
+/* Saved name of target host and called function for "info files".
+ Both malloc'd. */
+
+static char *vx_host;
+static char *vx_running; /* Called function */
+
+/* Nonzero means target that is being debugged remotely has a floating
+ point processor. */
+
+static int target_has_fp;
+
+/* Default error message when the network is forking up. */
+
+static const char rpcerr[] = "network target debugging: rpc error";
+
+CLIENT *pClient; /* client used in net debugging */
+static int ptraceSock = RPC_ANYSOCK;
+
+enum clnt_stat net_clnt_call();
+static void parse_args ();
+
+static struct timeval rpcTimeout = { 10, 0 };
+
+static char *skip_white_space ();
+static char *find_white_space ();
+
+/* Tell the VxWorks target system to download a file.
+ The load addresses of the text, data, and bss segments are
+ stored in pTextAddr, pDataAddr, and *pBssAddr (respectively).
+ Returns 0 for success, -1 for failure. */
+
+static int
+net_load (filename, pTextAddr, pDataAddr, pBssAddr)
+ char *filename;
+ CORE_ADDR *pTextAddr;
+ CORE_ADDR *pDataAddr;
+ CORE_ADDR *pBssAddr;
+ {
+ enum clnt_stat status;
+ struct ldfile ldstruct;
+ struct timeval load_timeout;
+
+ bzero ((char *) &ldstruct, sizeof (ldstruct));
+
+ /* We invoke clnt_call () here directly, instead of through
+ net_clnt_call (), because we need to set a large timeout value.
+ The load on the target side can take quite a while, easily
+ more than 10 seconds. The user can kill this call by typing
+ CTRL-C if there really is a problem with the load.
+
+ Do not change the tv_sec value without checking -- select() imposes
+ a limit of 10**8 on it for no good reason that I can see... */
+
+ load_timeout.tv_sec = 99999999; /* A large number, effectively inf. */
+ load_timeout.tv_usec = 0;
+
+ status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
+ &ldstruct, load_timeout);
+
+ if (status == RPC_SUCCESS)
+ {
+ if (*ldstruct.name == NULL) /* load failed on VxWorks side */
+ return -1;
+ *pTextAddr = ldstruct.txt_addr;
+ *pDataAddr = ldstruct.data_addr;
+ *pBssAddr = ldstruct.bss_addr;
+ return 0;
+ }
+ else
+ return -1;
+ }
+
+/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
+
+static int
+net_break (addr, procnum)
+ int addr;
+ u_long procnum;
+ {
+ enum clnt_stat status;
+ int break_status;
+ Rptrace ptrace_in; /* XXX This is stupid. It doesn't need to be a ptrace
+ structure. How about something smaller? */
+
+ bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+ break_status = 0;
+
+ ptrace_in.addr = addr;
+ ptrace_in.pid = inferior_pid;
+
+ status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
+ &break_status);
+
+ if (status != RPC_SUCCESS)
+ return errno;
+
+ if (break_status == -1)
+ return ENOMEM;
+ return break_status; /* probably (FIXME) zero */
+ }
+
+/* returns 0 if successful, errno otherwise */
+
+int
+vx_insert_breakpoint (addr)
+ int addr;
+ {
+ return net_break (addr, VX_BREAK_ADD);
+ }
+
+/* returns 0 if successful, errno otherwise */
+
+int
+vx_remove_breakpoint (addr)
+ int addr;
+ {
+ return net_break (addr, VX_BREAK_DELETE);
+ }
+
+/* Call a function on the VxWorks target system.
+ ARGS is a vector of values of arguments (NARGS of them).
+ FUNCTION is a value, the function to be called.
+ Returns a struct value * representing what the function returned.
+ May fail to return, if a breakpoint or signal is hit
+ during the execution of the function. */
+
+#ifdef FIXME
+/* FIXME, function calls are really fried. GO back to manual method. */
+value
+vx_call_function (function, nargs, args)
+ value function;
+ int nargs;
+ value *args;
+{
+ register CORE_ADDR sp;
+ register int i;
+ CORE_ADDR start_sp;
+ static REGISTER_TYPE dummy[] = CALL_DUMMY;
+ REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
+ CORE_ADDR old_sp;
+ struct type *value_type;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+ struct inferior_status inf_status;
+ struct cleanup *old_chain;
+ CORE_ADDR funaddr;
+ int using_gcc;
+
+ save_inferior_status (&inf_status, 1);
+ old_chain = make_cleanup (restore_inferior_status, &inf_status);
+
+ /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
+ (and POP_FRAME for restoring them). (At least on most machines)
+ they are saved on the stack in the inferior. */
+ PUSH_DUMMY_FRAME;
+
+ old_sp = sp = read_register (SP_REGNUM);
+
+#if 1 INNER_THAN 2 /* Stack grows down */
+ sp -= sizeof dummy;
+ start_sp = sp;
+#else /* Stack grows up */
+ start_sp = sp;
+ sp += sizeof dummy;
+#endif
+
+ funaddr = find_function_addr (function, &value_type);
+
+ {
+ struct block *b = block_for_pc (funaddr);
+ /* If compiled without -g, assume GCC. */
+ using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
+ }
+
+ /* Are we returning a value using a structure return or a normal
+ value return? */
+
+ struct_return = using_struct_return (function, funaddr, value_type,
+ using_gcc);
+
+ /* Create a call sequence customized for this function
+ and the number of arguments for it. */
+ bcopy (dummy, dummy1, sizeof dummy);
+ FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+ value_type, using_gcc);
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+ write_memory (start_sp, dummy1, sizeof dummy);
+
+#else /* Not on stack. */
+#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
+ /* Convex Unix prohibits executing in the stack segment. */
+ /* Hope there is empty room at the top of the text segment. */
+ {
+ static checked = 0;
+ if (!checked)
+ for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
+ if (read_memory_integer (start_sp, 1) != 0)
+ error ("text segment full -- no place to put call");
+ checked = 1;
+ sp = old_sp;
+ start_sp = text_end - sizeof dummy;
+ write_memory (start_sp, dummy1, sizeof dummy);
+ }
+#else /* After text_end. */
+ {
+ int errcode;
+ sp = old_sp;
+ start_sp = text_end;
+ errcode = target_write_memory (start_sp, dummy1, sizeof dummy);
+ if (errcode != 0)
+ error ("Cannot write text segment -- call_function failed");
+ }
+#endif /* After text_end. */
+#endif /* Not on stack. */
+
+#ifdef STACK_ALIGN
+ /* If stack grows down, we must leave a hole at the top. */
+ {
+ int len = 0;
+
+ /* Reserve space for the return structure to be written on the
+ stack, if necessary */
+
+ if (struct_return)
+ len += TYPE_LENGTH (value_type);
+
+ for (i = nargs - 1; i >= 0; i--)
+ len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
+#ifdef CALL_DUMMY_STACK_ADJUST
+ len += CALL_DUMMY_STACK_ADJUST;
+#endif
+#if 1 INNER_THAN 2
+ sp -= STACK_ALIGN (len) - len;
+#else
+ sp += STACK_ALIGN (len) - len;
+#endif
+ }
+#endif /* STACK_ALIGN */
+
+ /* Reserve space for the return structure to be written on the
+ stack, if necessary */
+
+ if (struct_return)
+ {
+#if 1 INNER_THAN 2
+ sp -= TYPE_LENGTH (value_type);
+ struct_addr = sp;
+#else
+ struct_addr = sp;
+ sp += TYPE_LENGTH (value_type);
+#endif
+ }
+
+#if defined (REG_STRUCT_HAS_ADDR)
+ {
+ /* This is a machine like the sparc, where we need to pass a pointer
+ to the structure, not the structure itself. */
+ if (REG_STRUCT_HAS_ADDR (using_gcc))
+ for (i = nargs - 1; i >= 0; i--)
+ if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
+ {
+ CORE_ADDR addr;
+#if !(1 INNER_THAN 2)
+ /* The stack grows up, so the address of the thing we push
+ is the stack pointer before we push it. */
+ addr = sp;
+#endif
+ /* Push the structure. */
+ sp = value_push (sp, args[i]);
+#if 1 INNER_THAN 2
+ /* The stack grows down, so the address of the thing we push
+ is the stack pointer after we push it. */
+ addr = sp;
+#endif
+ /* The value we're going to pass is the address of the thing
+ we just pushed. */
+ args[i] = value_from_long (builtin_type_long, (LONGEST) addr);
+ }
+ }
+#endif /* REG_STRUCT_HAS_ADDR. */
+
+#ifdef PUSH_ARGUMENTS
+ PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
+#else /* !PUSH_ARGUMENTS */
+ for (i = nargs - 1; i >= 0; i--)
+ sp = value_arg_push (sp, args[i]);
+#endif /* !PUSH_ARGUMENTS */
+
+#ifdef CALL_DUMMY_STACK_ADJUST
+#if 1 INNER_THAN 2
+ sp -= CALL_DUMMY_STACK_ADJUST;
+#else
+ sp += CALL_DUMMY_STACK_ADJUST;
+#endif
+#endif /* CALL_DUMMY_STACK_ADJUST */
+
+ /* Store the address at which the structure is supposed to be
+ written. Note that this (and the code which reserved the space
+ above) assumes that gcc was used to compile this function. Since
+ it doesn't cost us anything but space and if the function is pcc
+ it will ignore this value, we will make that assumption.
+
+ Also note that on some machines (like the sparc) pcc uses a
+ convention like gcc's. */
+
+ if (struct_return)
+ STORE_STRUCT_RETURN (struct_addr, sp);
+
+ /* Write the stack pointer. This is here because the statements above
+ might fool with it. On SPARC, this write also stores the register
+ window into the right place in the new stack frame, which otherwise
+ wouldn't happen. (See write_inferior_registers in sparc-xdep.c.) */
+ write_register (SP_REGNUM, sp);
+
+ /* Figure out the value returned by the function. */
+ {
+ char retbuf[REGISTER_BYTES];
+
+ /* Execute the stack dummy routine, calling FUNCTION.
+ When it is done, discard the empty frame
+ after storing the contents of all regs into retbuf. */
+ run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
+
+ do_cleanups (old_chain);
+
+ return value_being_returned (value_type, retbuf, struct_return);
+ }
+}
+/* should return a value of some sort */
+
+value
+vx_call_function (funcAddr, nargs, args, valueType)
+ char *funcAddr;
+ int nargs;
+ value *args;
+ struct type * valueType;
+{
+ int i;
+ func_call funcInfo;
+ arg_value *argValue;
+ enum clnt_stat status;
+ register int len;
+ arg_value funcReturn;
+ value gdbValue;
+
+ argValue = (arg_value *) xmalloc (nargs * sizeof (arg_value));
+
+ bzero (argValue, nargs * sizeof (arg_value));
+ bzero (&funcReturn, sizeof (funcReturn));
+
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ len = TYPE_LENGTH (VALUE_TYPE (args [i]));
+
+ switch (TYPE_CODE (VALUE_TYPE (args[i])))
+ {
+ /* XXX put other types here. Where's CHAR, etc??? */
+
+ case TYPE_CODE_FLT:
+ argValue[i].type = T_FLOAT;
+ break;
+ case TYPE_CODE_INT:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FUNC:
+ argValue[i].type = T_INT;
+ break;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_PASCAL_ARRAY:
+ case TYPE_CODE_MEMBER: /* C++ */
+ case TYPE_CODE_METHOD: /* C++ */
+ case TYPE_CODE_REF: /* C++ */
+ default:
+ error ("No corresponding VxWorks type for %d. CHECK IT OUT!!!\n",
+ TYPE_CODE(VALUE_TYPE(args[i])));
+ } /* switch */
+ if (TYPE_CODE(VALUE_TYPE(args[i])) == TYPE_CODE_FUNC)
+ argValue[i].arg_value_u.v_int = VALUE_ADDRESS(args[i]);
+ else
+ bcopy (VALUE_CONTENTS (args[i]), (char *) &argValue[i].arg_value_u,
+ len);
+ }
+
+ /* XXX what should the type of this function addr be?
+ * XXX Both in gdb and vxWorks
+ */
+ funcInfo.func_addr = (int) funcAddr;
+ funcInfo.args.args_len = nargs;
+ funcInfo.args.args_val = argValue;
+
+ status = net_clnt_call (VX_CALL_FUNC, xdr_func_call, (char *) &funcInfo,
+ xdr_arg_value, &funcReturn);
+
+ free ((char *) argValue);
+
+ if (status == RPC_SUCCESS)
+ {
+ /* XXX this assumes that vxWorks ALWAYS returns an int, and that
+ * XXX gdb isn't expecting anything more
+ */
+
+ /*******************
+ if (funcReturn.type == T_UNKNOWN)
+ return YYYXXX...;
+ *******************/
+ gdbValue = allocate_value (valueType);
+ bcopy (&funcReturn.arg_value_u.v_int, VALUE_CONTENTS (gdbValue),
+ sizeof (int));
+ return gdbValue;
+ }
+ else
+ error (rpcerr);
+ }
+#endif /* FIXME */
+
+/* Start an inferior process and sets inferior_pid to its pid.
+ EXEC_FILE is the file to run.
+ ALLARGS is a string containing the arguments to the program.
+ ENV is the environment vector to pass.
+ Returns process id. Errors reported with error().
+ On VxWorks, we ignore exec_file. */
+
+void
+vx_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ enum clnt_stat status;
+ arg_array passArgs;
+ TASK_START taskStart;
+
+ bzero ((char *) &passArgs, sizeof (passArgs));
+ bzero ((char *) &taskStart, sizeof (taskStart));
+
+ /* parse arguments, put them in passArgs */
+
+ parse_args (args, &passArgs);
+
+ if (passArgs.arg_array_len == 0)
+ error ("You must specify a function name to run, and arguments if any");
+
+ status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
+ xdr_TASK_START, &taskStart);
+
+ if ((status != RPC_SUCCESS) || (taskStart.status == -1))
+ error ("Can't create process on remote target machine");
+
+ /* Save the name of the running function */
+ vx_running = savestring (passArgs.arg_array_val[0],
+ strlen (passArgs.arg_array_val[0]));
+
+#ifdef CREATE_INFERIOR_HOOK
+ CREATE_INFERIOR_HOOK (pid);
+#endif
+
+ push_target (&vx_run_ops);
+ inferior_pid = taskStart.pid;
+
+#if defined (START_INFERIOR_HOOK)
+ START_INFERIOR_HOOK ();
+#endif
+
+ /* We will get a trace trap after one instruction.
+ Insert breakpoints and continue. */
+
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* remote_start(args); */
+ /* trap_expected = 0; */
+ stop_soon_quietly = 1;
+ wait_for_inferior (); /* Get the task spawn event */
+ stop_soon_quietly = 0;
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed(-1, -1, 0);
+}
+
+/* Fill ARGSTRUCT in argc/argv form with the arguments from the
+ argument string ARGSTRING. */
+
+static void
+parse_args (arg_string, arg_struct)
+ register char *arg_string;
+ arg_array *arg_struct;
+{
+ register int arg_count = 0; /* number of arguments */
+ register int arg_index = 0;
+ register char *p0;
+
+ bzero ((char *) arg_struct, sizeof (arg_array));
+
+ /* first count how many arguments there are */
+
+ p0 = arg_string;
+ while (*p0 != '\0')
+ {
+ if (*(p0 = skip_white_space (p0)) == '\0')
+ break;
+ p0 = find_white_space (p0);
+ arg_count++;
+ }
+
+ arg_struct->arg_array_len = arg_count;
+ arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
+ * sizeof (char *));
+
+ /* now copy argument strings into arg_struct. */
+
+ while (*(arg_string = skip_white_space (arg_string)))
+ {
+ p0 = find_white_space (arg_string);
+ arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
+ p0 - arg_string);
+ arg_string = p0;
+ }
+
+ arg_struct->arg_array_val[arg_count] = NULL;
+}
+
+/* Advance a string pointer across whitespace and return a pointer
+ to the first non-white character. */
+
+static char *
+skip_white_space (p)
+ register char *p;
+{
+ while (*p == ' ' || *p == '\t')
+ p++;
+ return p;
+}
+
+/* Search for the first unquoted whitespace character in a string.
+ Returns a pointer to the character, or to the null terminator
+ if no whitespace is found. */
+
+static char *
+find_white_space (p)
+ register char *p;
+{
+ register int c;
+
+ while ((c = *p) != ' ' && c != '\t' && c)
+ {
+ if (c == '\'' || c == '"')
+ {
+ while (*++p != c && *p)
+ {
+ if (*p == '\\')
+ p++;
+ }
+ if (!*p)
+ break;
+ }
+ p++;
+ }
+ return p;
+}
+
+/* Poll the VxWorks target system for an event related
+ to the debugged task.
+ Returns -1 if remote wait failed, task status otherwise. */
+
+int
+net_wait (pEvent)
+ RDB_EVENT *pEvent;
+{
+ int pid;
+ enum clnt_stat status;
+
+ bzero ((char *) pEvent, sizeof (RDB_EVENT));
+
+ pid = inferior_pid;
+ status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, pEvent);
+
+ return (status == RPC_SUCCESS)? pEvent->status: -1;
+}
+
+/* Suspend the remote task.
+ Returns -1 if suspend fails on target system, 0 otherwise. */
+
+int
+net_quit ()
+{
+ int pid;
+ int quit_status;
+ enum clnt_stat status;
+
+ quit_status = 0;
+
+ /* don't let rdbTask suspend itself by passing a pid of 0 */
+
+ if ((pid = inferior_pid) == 0)
+ return -1;
+
+ status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
+ &quit_status);
+
+ return (status == RPC_SUCCESS)? quit_status: -1;
+}
+
+/* Read a register or registers from the remote system. */
+
+int
+vx_read_register (regno)
+ int regno;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+
+ bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+ bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+ /* FIXME, eventually only get the ones we need. */
+ registers_fetched ();
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_out.info.more_data = (caddr_t) &inferior_registers;
+ status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ return -1;
+ }
+
+#ifdef I80960
+
+ bcopy ((char *) inferior_registers.r_lreg,
+ ®isters[REGISTER_BYTE (R0_REGNUM)], 16 * sizeof (int));
+ bcopy ((char *) inferior_registers.r_greg,
+ ®isters[REGISTER_BYTE (G0_REGNUM)], 16 * sizeof (int));
+
+ /* Don't assume that a location in registers[] is properly aligned. */
+
+ bcopy ((char *) &inferior_registers.r_pcw,
+ ®isters[REGISTER_BYTE (PCW_REGNUM)], sizeof (int));
+ bcopy ((char *) &inferior_registers.r_acw,
+ ®isters[REGISTER_BYTE (ACW_REGNUM)], sizeof (int));
+ bcopy ((char *) &inferior_registers.r_lreg[2], /* r2 (RIP) -> IP */
+ ®isters[REGISTER_BYTE (IP_REGNUM)], sizeof (int));
+ bcopy ((char *) &inferior_registers.r_tcw,
+ ®isters[REGISTER_BYTE (TCW_REGNUM)], sizeof (int));
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ ptrace_in.pid = inferior_pid;
+ ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
+ status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ return -1;
+ }
+
+ bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+ }
+ else
+ {
+ bzero ((char *) ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+ }
+
+#else /* not 960, thus must be 68000: FIXME! */
+
+ bcopy (&inferior_registers, registers, 16 * 4);
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+
+ if (target_has_fp)
+ {
+ ptrace_in.pid = inferior_pid;
+ ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
+ status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ return -1;
+ }
+
+ bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ bcopy (&inferior_fp_registers.fps_control,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+ }
+ else
+ {
+ bzero (®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ bzero (®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+ }
+#endif /* various architectures */
+
+ return 0;
+}
+
+/* Prepare to store registers. Since we will store all of them,
+ read out their current values now. */
+
+void
+vx_prepare_to_store ()
+{
+ vx_read_register (-1);
+}
+
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+ /* FIXME, look at REGNO to save time here */
+
+vx_write_register (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+
+ bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+ bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+#ifdef I80960
+
+ bcopy (®isters[REGISTER_BYTE (R0_REGNUM)],
+ (char *) inferior_registers.r_lreg, 16 * sizeof (int));
+ bcopy (®isters[REGISTER_BYTE (G0_REGNUM)],
+ (char *) inferior_registers.r_greg, 16 * sizeof (int));
+
+ /* Don't assume that a location in registers[] is properly aligned. */
+
+ bcopy (®isters[REGISTER_BYTE (PCW_REGNUM)],
+ (char *) &inferior_registers.r_pcw, sizeof (int));
+ bcopy (®isters[REGISTER_BYTE (ACW_REGNUM)],
+ (char *) &inferior_registers.r_acw, sizeof (int));
+ bcopy (®isters[REGISTER_BYTE (TCW_REGNUM)],
+ (char *) &inferior_registers.r_tcw, sizeof (int));
+
+#else /* not 960 -- assume 68k -- FIXME */
+
+ bcopy (registers, &inferior_registers, 16 * 4);
+ inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+
+#endif /* Different register sets */
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_in.info.ttype = REGS;
+ ptrace_in.info.more_data = (caddr_t) &inferior_registers;
+
+ /* XXX change second param to be a proc number */
+ status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ return -1;
+ }
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+#ifdef I80960
+
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+
+#else /* not 960 -- assume 68k -- FIXME */
+
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+ bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+#endif /* Different register sets */
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_in.info.ttype = FPREGS;
+ ptrace_in.info.more_data = (caddr_t) &inferior_fp_registers;
+
+ status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. WRITE is true if writing to the
+ inferior.
+ Result is the number of bytes written or read (zero if error). The
+ protocol allows us to return a negative count, indicating that we can't
+ handle the current address but can handle one N bytes further, but
+ vxworks doesn't give us that information. */
+
+int
+vx_xfer_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ C_bytes data;
+
+ bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+ bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+ ptrace_in.pid = inferior_pid; /* XXX pid unnecessary for READDATA */
+ ptrace_in.addr = (int) memaddr; /* Where from */
+ ptrace_in.data = len; /* How many bytes */
+
+ if (write)
+ {
+ ptrace_in.info.ttype = DATA;
+ ptrace_in.info.more_data = (caddr_t) &data;
+
+ data.bytes = (caddr_t) myaddr; /* Where from */
+ data.len = len; /* How many bytes (again, for XDR) */
+
+ /* XXX change second param to be a proc number */
+ status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in, &ptrace_out);
+ }
+ else
+ {
+ ptrace_out.info.more_data = (caddr_t) &data;
+ data.bytes = myaddr; /* Where to */
+ data.len = len; /* How many (again, for XDR) */
+
+ /* XXX change second param to be a proc number */
+ status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
+ }
+
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ return 0; /* No bytes moved */
+ }
+ return len; /* Moved *all* the bytes */
+}
+
+void
+vx_files_info ()
+{
+ printf ("\tAttached to host `%s'", vx_host);
+ printf (", which has %sfloating point", target_has_fp? "": "no ");
+ printf (".\n");
+}
+
+void
+vx_run_files_info ()
+{
+ printf ("\tRunning %s VxWorks process 0x%x",
+ vx_running? "child": "attached",
+ inferior_pid);
+ if (vx_running)
+ printf (", function `%s'", vx_running);
+ printf(".\n");
+}
+
+void
+vx_resume (step, siggnal)
+ int step;
+ int siggnal;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+
+ if (siggnal != 0 && siggnal != stop_signal)
+ error ("Cannot send signals to VxWorks processes");
+
+ bzero ((char *) &ptrace_in, sizeof (ptrace_in));
+ bzero ((char *) &ptrace_out, sizeof (ptrace_out));
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_in.addr = 1; /* Target side insists on this, or it panics. */
+
+ /* XXX change second param to be a proc number */
+ status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
+ &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Resuming remote process");
+ }
+}
+
+void
+vx_mourn_inferior ()
+{
+ pop_target (); /* Pop back to no-child state */
+ generic_mourn_inferior ();
+}
+
+\f
+/* This function allows the addition of incrementally linked object files. */
+
+void
+vx_load_command (arg_string, from_tty)
+ char* arg_string;
+ int from_tty;
+{
+ CORE_ADDR text_addr;
+ CORE_ADDR data_addr;
+ CORE_ADDR bss_addr;
+
+ if (arg_string == 0)
+ error ("The load command takes a file name");
+
+ arg_string = tilde_expand (arg_string);
+ make_cleanup (free, arg_string);
+
+ dont_repeat ();
+
+ QUIT;
+ immediate_quit++;
+ if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
+ error ("Load failed on target machine");
+ immediate_quit--;
+
+ /* FIXME, for now we ignore data_addr and bss_addr. */
+ symbol_file_add (arg_string, from_tty, text_addr, 0);
+}
+
+#ifdef FIXME /* Not ready for prime time */
+/* Single step the target program at the source or machine level.
+ Takes an error exit if rpc fails.
+ Returns -1 if remote single-step operation fails, else 0. */
+
+static int
+net_step ()
+{
+ enum clnt_stat status;
+ int step_status;
+ SOURCE_STEP source_step;
+
+ source_step.taskId = inferior_pid;
+
+ if (step_range_end)
+ {
+ source_step.startAddr = step_range_start;
+ source_step.endAddr = step_range_end;
+ }
+ else
+ {
+ source_step.startAddr = 0;
+ source_step.endAddr = 0;
+ }
+
+ status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
+ xdr_int, &step_status);
+
+ if (status == RPC_SUCCESS)
+ return step_status;
+ else
+ error (rpcerr);
+}
+#endif
+
+/* Emulate ptrace using RPC calls to the VxWorks target system.
+ Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */
+
+static int
+net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
+ enum ptracereq request;
+ Rptrace *pPtraceIn;
+ Ptrace_return *pPtraceOut;
+{
+ enum clnt_stat status;
+
+ status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
+ pPtraceOut);
+
+ if (status != RPC_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+/* Query the target for the name of the file from which VxWorks was
+ booted. pBootFile is the address of a pointer to the buffer to
+ receive the file name; if the pointer pointed to by pBootFile is
+ NULL, memory for the buffer will be allocated by XDR.
+ Returns -1 if rpc failed, 0 otherwise. */
+
+int
+net_get_boot_file (pBootFile)
+ char **pBootFile;
+{
+ enum clnt_stat status;
+
+ status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
+ xdr_wrapstring, pBootFile);
+ return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Fetch a list of loaded object modules from the VxWorks target.
+ Returns -1 if rpc failed, 0 otherwise
+ There's no way to check if the returned loadTable is correct.
+ VxWorks doesn't check it. */
+
+int
+net_get_symbols (pLoadTable)
+ ldtabl *pLoadTable; /* return pointer to ldtabl here */
+{
+ enum clnt_stat status;
+
+ bzero ((char *) pLoadTable, sizeof (struct ldtabl));
+
+ status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
+ return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Look up a symbol in the VxWorks target's symbol table.
+ Returns status of symbol read on target side (0=success, -1=fail)
+ Returns -1 and complain()s if rpc fails. */
+
+struct complaint cant_contact_target =
+ {"Lost contact with VxWorks target", 0, 0};
+
+int
+vx_lookup_symbol (name, pAddr)
+ char *name; /* symbol name */
+ CORE_ADDR *pAddr;
+{
+ enum clnt_stat status;
+ SYMBOL_ADDR symbolAddr;
+
+ *pAddr = 0;
+ bzero ((char *) &symbolAddr, sizeof (symbolAddr));
+
+ status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
+ xdr_SYMBOL_ADDR, &symbolAddr);
+ if (status != RPC_SUCCESS) {
+ complain (&cant_contact_target, 0);
+ return -1;
+ }
+
+ *pAddr = symbolAddr.addr;
+ return symbolAddr.status;
+}
+
+/* Check to see if the VxWorks target has a floating point coprocessor.
+ Returns 1 if target has floating point processor, 0 otherwise.
+ Calls error() if rpc fails. */
+
+int
+net_check_for_fp ()
+{
+ enum clnt_stat status;
+ bool_t fp = 0; /* true if fp processor is present on target board */
+
+ status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
+ if (status != RPC_SUCCESS)
+ error (rpcerr);
+
+ return (int) fp;
+}
+
+/* Establish an RPC connection with the VxWorks target system.
+ Calls error () if unable to establish connection. */
+
+void
+net_connect (host)
+ char *host;
+{
+ struct sockaddr_in destAddr;
+ struct hostent *destHost;
+
+ /* get the internet address for the given host */
+
+ if ((destHost = (struct hostent *) gethostbyname (host)) == NULL)
+ error ("Invalid hostname. Couldn't find remote host address.");
+
+ bzero (&destAddr, sizeof (destAddr));
+
+ destAddr.sin_addr.s_addr = * (u_long *) destHost->h_addr;
+ destAddr.sin_family = AF_INET;
+ destAddr.sin_port = 0; /* set to actual port that remote
+ ptrace is listening on. */
+
+ /* Create a tcp client transport on which to issue
+ calls to the remote ptrace server. */
+
+ ptraceSock = RPC_ANYSOCK;
+ pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
+ /* FIXME, here is where we deal with different version numbers of the proto */
+
+ if (pClient == NULL)
+ {
+ clnt_pcreateerror ("\tnet_connect");
+ error ("Couldn't connect to remote target.");
+ }
+}
+\f
+/* Sleep for the specified number of milliseconds
+ * (assumed to be less than 1000).
+ * If select () is interrupted, returns immediately;
+ * takes an error exit if select () fails for some other reason.
+ */
+
+static void
+sleep_ms (ms)
+ long ms;
+{
+ struct timeval select_timeout;
+ int status;
+
+ select_timeout.tv_sec = 0;
+ select_timeout.tv_usec = ms * 1000;
+
+ status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
+
+ if (status < 0 && errno != EINTR)
+ perror_with_name ("select");
+}
+
+/* Wait for control to return from inferior to debugger.
+ If inferior gets a signal, we may decide to start it up again
+ instead of returning. That is why there is a loop in this function.
+ When this function actually returns it means the inferior
+ should be left stopped and GDB should read more commands. */
+
+/* For network debugging with VxWorks.
+ * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
+ * so vx_wait() receives this information directly from
+ * VxWorks instead of trying to figure out what happenned via a wait() call.
+ */
+
+static int
+vx_wait (status)
+ int *status;
+{
+ register int pid;
+ WAITTYPE w;
+ RDB_EVENT rdbEvent;
+ int quit_failed;
+
+ do
+ {
+ /* If CTRL-C is hit during this loop,
+ suspend the inferior process. */
+
+ quit_failed = 0;
+ if (quit_flag)
+ {
+ quit_failed = (net_quit () == -1);
+ quit_flag = 0;
+ }
+
+ /* If a net_quit () or net_wait () call has failed,
+ allow the user to break the connection with the target.
+ We can't simply error () out of this loop, since the
+ data structures representing the state of the inferior
+ are in an inconsistent state. */
+
+ if (quit_failed || net_wait (&rdbEvent) == -1)
+ {
+ terminal_ours ();
+ if (query ("Can't %s. Disconnect from target system? ",
+ (quit_failed) ? "suspend remote task"
+ : "get status of remote task"))
+ {
+ target_mourn_inferior();
+ error ("Use the \"target\" command to reconnect.");
+ }
+ else
+ {
+ terminal_inferior ();
+ continue;
+ }
+ }
+
+ pid = rdbEvent.taskId;
+ if (pid == 0)
+ {
+ sleep_ms (200); /* FIXME Don't kill the network too badly */
+ }
+ else if (pid != inferior_pid)
+ fatal ("Bad pid for debugged task: 0x%x\n", pid);
+ } while (pid == 0);
+
+ /* FIXME, eventually do more then SIGTRAP on everything... */
+ switch (rdbEvent.eventType)
+ {
+ case EVENT_EXIT:
+ WSETEXIT (w, 0);
+ /* FIXME is it possible to distinguish between a
+ XXX normal vs abnormal exit in VxWorks? */
+ break;
+
+ case EVENT_START: /* Task was just started. */
+ WSETSTOP (w, SIGTRAP);
+ break;
+
+ case EVENT_STOP:
+ WSETSTOP (w, SIGTRAP);
+ /* XXX was it stopped by a signal? act accordingly */
+ break;
+
+ case EVENT_BREAK: /* Breakpoint was hit. */
+ WSETSTOP (w, SIGTRAP);
+ break;
+
+ case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */
+ WSETSTOP (w, SIGINT);
+ break;
+
+ case EVENT_BUS_ERR: /* Task made evil nasty reference. */
+ WSETSTOP (w, SIGBUS);
+ break;
+
+ case EVENT_ZERO_DIV: /* Division by zero */
+ WSETSTOP (w, SIGFPE); /* Like Unix, call it a float exception. */
+
+ case EVENT_SIGNAL:
+ /* The target is not running Unix, and its
+ faults/traces do not map nicely into Unix signals.
+ Make sure they do not get confused with Unix signals
+ by numbering them with values higher than the highest
+ legal Unix signal. code in the arch-dependent PRINT_RANDOM_SIGNAL
+ routine will interpret the value for wait_for_inferior. */
+ WSETSTOP (w, rdbEvent.sigType + NSIG);
+ break;
+ } /* switch */
+ *status = *(int *)&w; /* Grumble union wait crap Grumble */
+ return pid;
+}
+\f
+static int
+symbol_stub (arg)
+ int arg;
+{
+ char *bootFile = (char *)arg;
+ symbol_file_command (bootFile, 0);
+ return 1;
+}
+
+static int
+add_symbol_stub (arg)
+ int arg;
+{
+ struct ldfile *pLoadFile = (struct ldfile *)arg;
+
+ printf("\t%s: ", pLoadFile->name);
+ symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
+ printf ("ok\n");
+ return 1;
+}
+/* Target command for VxWorks target systems.
+
+ Used in vxgdb. Takes the name of a remote target machine
+ running vxWorks and connects to it to initialize remote network
+ debugging. */
+
+static void
+vx_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int close ();
+ char *bootFile;
+ extern char *source_path;
+ struct ldtabl loadTable;
+ struct ldfile *pLoadFile;
+ int i;
+ extern CLIENT *pClient;
+
+ if (!args)
+ error_no_arg ("target machine name");
+
+ unpush_target (&vx_ops);
+ printf ("Attaching remote machine across net...\n");
+ fflush (stdout);
+
+ /* Allow the user to kill the connect attempt by typing ^C.
+ Wait until the call to target_has_fp () completes before
+ disallowing an immediate quit, since even if net_connect ()
+ is successful, the remote debug server might be hung. */
+
+ immediate_quit++;
+
+ net_connect (args);
+ target_has_fp = net_check_for_fp ();
+ printf_filtered ("Connected to %s.\n", args);
+
+ immediate_quit--;
+
+ push_target (&vx_ops);
+
+ /* Save a copy of the target host's name. */
+ vx_host = savestring (args, strlen (args));
+
+ /* Find out the name of the file from which the target was booted
+ and load its symbol table. */
+
+ printf_filtered ("Looking in Unix path for all loaded modules:\n");
+ bootFile = NULL;
+ if (!net_get_boot_file (&bootFile))
+ {
+ if (*bootFile) {
+ printf_filtered ("\t%s: ", bootFile);
+ if (catch_errors (symbol_stub, (int)bootFile,
+ "Error reading symbols from boot file"))
+ puts_filtered ("ok\n");
+ } else if (from_tty)
+ printf ("VxWorks kernel symbols not loaded.\n");
+ }
+ else
+ error ("Can't retrieve boot file name from target machine.");
+
+ clnt_freeres (pClient, xdr_wrapstring, &bootFile);
+
+ if (net_get_symbols (&loadTable) != 0)
+ error ("Can't read loaded modules from target machine");
+
+ i = 0-1;
+ while (++i < loadTable.tbl_size)
+ {
+ QUIT; /* FIXME, avoids clnt_freeres below: mem leak */
+ pLoadFile = &loadTable.tbl_ent [i];
+#ifdef WRS_ORIG
+ {
+ register int desc;
+ struct cleanup *old_chain;
+ char *fullname = NULL;
+
+ desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
+ if (desc < 0)
+ perror_with_name (pLoadFile->name);
+ old_chain = make_cleanup (close, desc);
+ add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
+ pLoadFile->bss_addr);
+ do_cleanups (old_chain);
+ }
+#else
+ /* Botches, FIXME:
+ (1) Searches the PATH, not the source path.
+ (2) data and bss are assumed to be at the usual offsets from text. */
+ catch_errors (add_symbol_stub, (int)pLoadFile, (char *)0);
+#endif
+ }
+ printf_filtered ("Done.\n");
+
+ clnt_freeres (pClient, xdr_ldtabl, &loadTable);
+}
+\f
+/* attach_command --
+ takes a task started up outside of gdb and ``attaches'' to it.
+ This stops it cold in its tracks and allows us to start tracing it. */
+
+static void
+vx_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int pid;
+ char *cptr = 0;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int status;
+
+ dont_repeat();
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ pid = strtol (args, &cptr, 0);
+ if ((cptr == args) || (*cptr != '\0'))
+ error ("Invalid process-id -- give a single number in decimal or 0xhex");
+
+ if (from_tty)
+ printf ("Attaching pid 0x%x.\n", pid);
+
+ bzero ((char *)&ptrace_in, sizeof (ptrace_in));
+ bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+ ptrace_in.pid = pid;
+
+ status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Attaching remote process");
+ }
+
+ /* It worked... */
+ push_target (&vx_run_ops);
+ inferior_pid = pid;
+ vx_running = 0;
+
+#if defined (START_INFERIOR_HOOK)
+ START_INFERIOR_HOOK ();
+#endif
+
+ mark_breakpoints_out ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* We will get a task spawn event immediately. */
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ wait_for_inferior ();
+ stop_soon_quietly = 0;
+ normal_stop ();
+}
+
+
+/* detach_command --
+ takes a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via the normal ptrace (PTRACE_TRACEME). */
+
+static void
+vx_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int signal = 0;
+ int status;
+
+ if (args)
+ error ("Argument given to VxWorks \"detach\".");
+
+ if (from_tty)
+ printf ("Detaching pid 0x%x.\n", inferior_pid);
+
+ if (args) /* FIXME, should be possible to leave suspended */
+ signal = atoi (args);
+
+ bzero ((char *)&ptrace_in, sizeof (ptrace_in));
+ bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+ ptrace_in.pid = inferior_pid;
+
+ status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Detaching VxWorks process");
+ }
+
+ inferior_pid = 0;
+ pop_target (); /* go back to non-executing VxWorks connection */
+}
+
+/* vx_kill -- takes a running task and wipes it out. */
+
+static void
+vx_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int status;
+
+ if (args)
+ error ("Argument given to VxWorks \"kill\".");
+
+ if (from_tty)
+ printf ("Killing pid 0x%x.\n", inferior_pid);
+
+ bzero ((char *)&ptrace_in, sizeof (ptrace_in));
+ bzero ((char *)&ptrace_out, sizeof (ptrace_out));
+ ptrace_in.pid = inferior_pid;
+
+ status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Killing VxWorks process");
+ }
+
+ /* If it gives good status, the process is *gone*, no events remain. */
+ inferior_pid = 0;
+ pop_target (); /* go back to non-executing VxWorks connection */
+}
+
+/* Clean up from the VxWorks process target as it goes away. */
+
+void
+vx_proc_close (quitting)
+ int quitting;
+{
+ inferior_pid = 0; /* No longer have a process. */
+ if (vx_running)
+ free (vx_running);
+ vx_running = 0;
+}
+\f
+/* Cross-net conversion of floats to and from extended form.
+ (This is needed because different target machines have different
+ extended floating point formats.) */
+
+/* Convert from an extended float to a double.
+
+ The extended float is stored as raw data pointed to by FROM.
+ Return the converted value as raw data in the double pointed to by TO.
+*/
+
+static void
+vx_convert_to_virtual (regno, from, to)
+ int regno;
+ char *from;
+ char *to;
+{
+ enum clnt_stat status;
+
+ if (REGISTER_CONVERTIBLE (regno))
+ {
+ if (!target_has_fp) {
+ *(double *)to = 0.0; /* Skip the trouble if no float anyway */
+ return;
+ }
+
+ status = net_clnt_call (VX_CONV_FROM_68881, xdr_ext_fp, from,
+ xdr_double, to);
+
+ if (status == RPC_SUCCESS)
+ return;
+ else
+ error (rpcerr);
+ }
+ else
+ bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
+}
+
+
+/* The converse: convert from a double to an extended float.
+
+ The double is stored as raw data pointed to by FROM.
+ Return the converted value as raw data in the extended
+ float pointed to by TO.
+*/
+
+static void
+vx_convert_from_virtual (regno, from, to)
+ int regno;
+ char *from;
+ char *to;
+{
+ enum clnt_stat status;
+
+ if (REGISTER_CONVERTIBLE (regno))
+ {
+ if (!target_has_fp) {
+ bzero (to, REGISTER_RAW_SIZE (FP0_REGNUM)); /* Shrug */
+ return;
+ }
+
+ status = net_clnt_call (VX_CONV_TO_68881, xdr_double, from,
+ xdr_ext_fp, to);
+ if (status == RPC_SUCCESS)
+ return;
+ else
+ error (rpcerr);
+ }
+ else
+ bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
+}
+\f
+/* Make an RPC call to the VxWorks target.
+ Returns RPC status. */
+
+static enum clnt_stat
+net_clnt_call (procNum, inProc, in, outProc, out)
+ enum ptracereq procNum;
+ xdrproc_t inProc;
+ char *in;
+ xdrproc_t outProc;
+ char *out;
+{
+ enum clnt_stat status;
+
+ status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
+
+ if (status != RPC_SUCCESS)
+ clnt_perrno (status);
+
+ return status;
+}
+
+/* Clean up before losing control. */
+
+void
+vx_close (quitting)
+ int quitting;
+{
+ if (pClient)
+ clnt_destroy (pClient); /* The net connection */
+ pClient = 0;
+
+ if (vx_host)
+ free (vx_host); /* The hostname */
+ vx_host = 0;
+}
+
+
+/* Target ops structure for accessing memory and such over the net */
+
+struct target_ops vx_ops = {
+ "vxworks", "VxWorks target memory via RPC over TCP/IP",
+ vx_open, vx_close, vx_attach, 0, /* vx_detach, */
+ 0, 0, /* resume, wait */
+ 0, 0, /* read_reg, write_reg */
+ 0, vx_convert_to_virtual, vx_convert_from_virtual, /* prep_to_store, */
+ vx_xfer_memory, vx_files_info,
+ 0, 0, /* insert_breakpoint, remove_breakpoint */
+ 0, 0, 0, 0, 0, /* terminal stuff */
+ 0, /* vx_kill, */
+ vx_load_command, add_syms_addr_command,
+ 0, /* call_function */
+ vx_lookup_symbol,
+ vx_create_inferior, 0, /* mourn_inferior */
+ core_stratum, 0, /* next */
+ 1, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+/* Target ops structure for accessing VxWorks child processes over the net */
+
+struct target_ops vx_run_ops = {
+ "vxprocess", "VxWorks process",
+ vx_open, vx_proc_close, 0, vx_detach, /* vx_attach */
+ vx_resume, vx_wait,
+ vx_read_register, vx_write_register,
+ vx_prepare_to_store, vx_convert_to_virtual, vx_convert_from_virtual,
+ vx_xfer_memory, vx_run_files_info,
+ vx_insert_breakpoint, vx_remove_breakpoint,
+ 0, 0, 0, 0, 0, /* terminal stuff */
+ vx_kill,
+ vx_load_command, add_syms_addr_command,
+ call_function_by_hand, /* FIXME, calling fns is maybe botched? */
+ vx_lookup_symbol,
+ 0, vx_mourn_inferior,
+ process_stratum, 0, /* next */
+ 0, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ /* all_mem is off to avoid spurious msg in "i files" */
+ OPS_MAGIC, /* Always the last thing */
+};
+/* ==> Remember when reading at end of file, there are two "ops" structs here. */
+\f
+void
+_initialize_vx ()
+{
+ add_target (&vx_ops);
+ add_target (&vx_run_ops);
+}
--- /dev/null
+
+
+/* Options for project */
+unsetopt ansi
+setopt auto_compile
+unsetopt auto_reload
+setopt auto_replace
+unsetopt batch_load
+unsetopt batch_run
+unsetopt cc_prog
+setopt ccargs -g
+unsetopt create_file
+unsetopt debug_child
+unsetopt echo
+setopt edit_jobs 5
+unsetopt eight_bit
+setopt line_edit
+setopt line_meta
+setopt lint_load 2
+setopt lint_run 2
+setopt list_action
+setopt load_flags -I. -g -I.. -I../vx-share
+unsetopt long_not_int
+unsetopt make_args
+setopt make_hfiles
+unsetopt make_offset
+unsetopt make_prog
+setopt make_symbol #
+setopt mem_config 16384
+unsetopt mem_trace
+setopt num_proc 1
+unsetopt page_cmds
+setopt page_list 19
+unsetopt page_load
+unsetopt path
+setopt proto_path . /s2/saber_dir30/sun4-40/proto /s2/saber_dir30/sun4-40/../common/proto
+unsetopt preprocessor
+setopt program_name a.out
+unsetopt print_custom
+setopt print_pointer
+setopt print_string 20
+unsetopt save_memory
+setopt sbrk_size 1048576
+setopt src_err 3
+setopt src_step 1
+setopt src_stop 3
+setopt sys_load_flags -L/lib -L/usr/lib -L/usr/local/lib -I/usr/include -Dunix -Dsun -Dsparc
+unsetopt tab_stop
+unsetopt terse_suppress
+unsetopt terse_where
+setopt unset_value 191
+unsetopt win_fork_nodup
+setopt win_no_raise
+unsetopt win_message_list
+unsetopt win_project_list
+/* Suppressions for project */
+suppress 6 in read_huge_number
+/* Over/underflow <plus> */
+suppress 8 in read_huge_number
+/* Over/underflow <multiply> */
+suppress 22
+/* Pointer subtraction */
+suppress 22 in free_all_psymtabs
+/* Pointer subtraction */
+suppress 22 in free_all_symtabs
+/* Pointer subtraction */
+suppress 56 in print_string
+/* Information lost <function> */
+suppress 65 "../bfd/bfd.c":379
+/* Too many function arguments */
+suppress 65 on printf_filtered
+/* Too many function arguments */
+suppress 65 on fprintf_filtered
+/* Too many function arguments */
+suppress 65 on vfprintf_filtered
+/* Too many function arguments */
+suppress 65 on query
+/* Too many function arguments */
+suppress 65 on fatal_dump_core
+/* Too many function arguments */
+suppress 65 on fatal
+/* Too many function arguments */
+suppress 65 on error
+/* Too many function arguments */
+suppress 65 on noprocess
+/* Too many function arguments */
+suppress 65
+/* Too many function arguments */
+suppress 66 on say
+/* Too few function arguments */
+suppress 66 on printf_filtered
+/* Too few function arguments */
+suppress 66 on fprintf_filtered
+/* Too few function arguments */
+suppress 66 on vfprintf_filtered
+/* Too few function arguments */
+suppress 66 on query
+/* Too few function arguments */
+suppress 66 on fatal_dump_core
+/* Too few function arguments */
+suppress 66 on fatal
+/* Too few function arguments */
+suppress 66 on error
+/* Too few function arguments */
+suppress 67 on printf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on fprintf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on vfprintf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on query
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal_dump_core
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal
+/* Signed/unsigned argument mismatch */
+suppress 67 on error
+/* Signed/unsigned argument mismatch */
+suppress 67
+/* Signed/unsigned argument mismatch */
+suppress 68 on bfd_get_section_contents
+/* Benign argument mismatch */
+suppress 68 on _do_getblong
+/* Benign argument mismatch */
+suppress 68 on supply_register
+/* Benign argument mismatch */
+suppress 68 on target_write_memory
+/* Benign argument mismatch */
+suppress 68 on write_register_bytes
+/* Benign argument mismatch */
+suppress 68 on read_register_bytes
+/* Benign argument mismatch */
+suppress 68 on read_memory
+/* Benign argument mismatch */
+suppress 68 on say
+/* Benign argument mismatch */
+suppress 68 on printf_filtered
+/* Benign argument mismatch */
+suppress 68 on fprintf_filtered
+/* Benign argument mismatch */
+suppress 68 on vfprintf_filtered
+/* Benign argument mismatch */
+suppress 68 on query
+/* Benign argument mismatch */
+suppress 68 on fatal_dump_core
+/* Benign argument mismatch */
+suppress 68 on fatal
+/* Benign argument mismatch */
+suppress 68 on error
+/* Benign argument mismatch */
+suppress 68 in find_solib
+/* Benign argument mismatch */
+suppress 68 on child_wait
+/* Benign argument mismatch */
+suppress 68 on xrealloc
+/* Benign argument mismatch */
+suppress 68 on myread
+/* Benign argument mismatch */
+suppress 68 in do_cleanups
+/* Benign argument mismatch */
+suppress 68 on make_cleanup
+/* Benign argument mismatch */
+suppress 68 on target_read_memory
+/* Benign argument mismatch */
+suppress 69 on printf_filtered
+/* Serious argument mismatch */
+suppress 69 on fprintf_filtered
+/* Serious argument mismatch */
+suppress 69 on vfprintf_filtered
+/* Serious argument mismatch */
+suppress 69 on query
+/* Serious argument mismatch */
+suppress 69 on fatal_dump_core
+/* Serious argument mismatch */
+suppress 69 on fatal
+/* Serious argument mismatch */
+suppress 69 on error
+/* Serious argument mismatch */
+suppress 70 on printf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on fprintf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on vfprintf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on query
+/* Passing illegal enumeration value */
+suppress 70 on fatal_dump_core
+/* Passing illegal enumeration value */
+suppress 70 on fatal
+/* Passing illegal enumeration value */
+suppress 70 on error
+/* Passing illegal enumeration value */
+suppress 110 in printf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in fprintf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in vfprintf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in query
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal_dump_core
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal
+/* Signed/unsigned memory retrieval */
+suppress 110 in error
+/* Signed/unsigned memory retrieval */
+suppress 112 in printf_filtered
+/* Memory retrieval */
+suppress 112 in fprintf_filtered
+/* Memory retrieval */
+suppress 112 in vfprintf_filtered
+/* Memory retrieval */
+suppress 112 in query
+/* Memory retrieval */
+suppress 112 in fatal_dump_core
+/* Memory retrieval */
+suppress 112 in fatal
+/* Memory retrieval */
+suppress 112 in error
+/* Memory retrieval */
+suppress 112
+/* Memory retrieval */
+suppress 112 ../symtab.c
+/* Memory retrieval */
+suppress 112 in child_xfer_memory
+/* Memory retrieval */
+suppress 165 in frame_saved_pc
+/* Dereference */
+suppress 165 in get_prev_frame_info
+/* Dereference */
+suppress 167 in get_prev_frame_info
+/* Selection */
+suppress 167 in frame_saved_pc
+/* Selection */
+suppress 442 in try_baudrate
+/* Escape has null value */
+suppress 529 in read_range_type
+/* Statement not reached */
+suppress 529 in process_one_symbol
+/* Statement not reached */
+suppress 529 in unpack_double
+/* Statement not reached */
+suppress 529 in wait_for_inferior
+/* Statement not reached */
+suppress 529 in do_registers_info
+/* Statement not reached */
+suppress 529 in value_from_register
+/* Statement not reached */
+suppress 530 "../environ.c":69
+/* Empty body of statement */
+suppress 530 "../remote-eb.c":333
+/* Empty body of statement */
+suppress 530 "../remote-eb.c":331
+/* Empty body of statement */
+suppress 530 "../remote-eb.c":324
+/* Empty body of statement */
+suppress 530 "../dbxread.c":792
+/* Empty body of statement */
+suppress 530
+/* Empty body of statement */
+suppress 530 "../dbxread.c":796
+/* Empty body of statement */
+suppress 546 in net_quit
+/* Function exits through bottom */
+suppress 546 in net_wait
+/* Function exits through bottom */
+suppress 546 in vx_remove_breakpoint
+/* Function exits through bottom */
+suppress 546 in vx_insert_breakpoint
+/* Function exits through bottom */
+suppress 546 in value_less
+/* Function exits through bottom */
+suppress 546 in value_equal
+/* Function exits through bottom */
+suppress 546 in unpack_long
+/* Function exits through bottom */
+suppress 558 in read_range_type
+/* Constant in conditional */
+suppress 558 in process_one_symbol
+/* Constant in conditional */
+suppress 558 in read_dbx_symtab
+/* Constant in conditional */
+suppress 558 in vx_write_register
+/* Constant in conditional */
+suppress 558 in vx_read_register
+/* Constant in conditional */
+suppress 558 in unpack_double
+/* Constant in conditional */
+suppress 558 in wait_for_inferior
+/* Constant in conditional */
+suppress 558 in do_registers_info
+/* Constant in conditional */
+suppress 558 in value_from_register
+/* Constant in conditional */
+suppress 560 in solib_address
+/* Assignment within conditional */
+suppress 560 in solib_info
+/* Assignment within conditional */
+suppress 560 in solib_add
+/* Assignment within conditional */
+suppress 560 in read_type
+/* Assignment within conditional */
+suppress 560 in type_print_base
+/* Assignment within conditional */
+suppress 560 in type_print_derivation_info
+/* Assignment within conditional */
+suppress 560 in block_depth
+/* Assignment within conditional */
+suppress 560 in select_source_symtab
+/* Assignment within conditional */
+suppress 560 in clear_value_history
+/* Assignment within conditional */
+suppress 560 in clear_displays
+/* Assignment within conditional */
+suppress 560 in initialize_main
+/* Assignment within conditional */
+suppress 560 in echo_command
+/* Assignment within conditional */
+suppress 560 in unset_in_environ
+/* Assignment within conditional */
+suppress 560 in set_in_environ
+/* Assignment within conditional */
+suppress 560 in get_in_environ
+/* Assignment within conditional */
+suppress 560 in do_setshow_command
+/* Assignment within conditional */
+suppress 560 in breakpoint_1
+/* Assignment within conditional */
+suppress 590 on sig
+/* Unused formal parameter */
+suppress 590 in nindy_create_inferior
+/* Unused formal parameter */
+suppress 590 in add_to_section_table
+/* Unused formal parameter */
+suppress 590 in vx_create_inferior
+/* Unused formal parameter */
+suppress 590 in host_convert_from_virtual
+/* Unused formal parameter */
+suppress 590 in host_convert_to_virtual
+/* Unused formal parameter */
+suppress 590 on siggnal
+/* Unused formal parameter */
+suppress 590 in init_sig
+/* Unused formal parameter */
+suppress 590 in nindy_resume
+/* Unused formal parameter */
+suppress 590 in set_history_size_command
+/* Unused formal parameter */
+suppress 590 in not_just_help_class_command
+/* Unused formal parameter */
+suppress 590 on regno
+/* Unused formal parameter */
+suppress 590 on from_tty
+/* Unused formal parameter */
+suppress 590 on args
+/* Unused formal parameter */
+suppress 590 in process_symbol_pair
+/* Unused formal parameter */
+suppress 591 in print_scalar_formatted
+/* Unused automatic variable */
+suppress 592 on rcsid
+/* Unused static */
+suppress 592 on check_break_insn_size
+/* Unused static */
+suppress 594 in call_function_by_hand
+/* Set but not used */
+suppress 594 in record_latest_value
+/* Set but not used */
+suppress 594 in bpstat_stop_status
+/* Set but not used */
+suppress 595 in coffstrip
+/* Used before set */
+suppress 652 ../bfd.h
+/* Declaration has no effect */
+suppress 652 /usr/include/machine/reg.h
+/* Declaration has no effect */
+
+/* Signals caught and ignored */
+catch HUP
+catch QUIT
+catch ILL
+catch TRAP
+catch IOT
+catch EMT
+catch FPE
+catch KILL
+catch BUS
+catch SEGV
+catch SYS
+catch PIPE
+catch TERM
+catch URG
+catch STOP
+catch TSTP
+catch TTIN
+catch TTOU
+catch IO
+catch XCPU
+catch XFSZ
+catch VTALRM
+catch PROF
+catch LOST
+catch USR1
+catch USR2
+ignore INT
+ignore ALRM
+ignore CONT
+ignore CHLD
+ignore WINCH
+
+/* Status of project */
--- /dev/null
+/* Signal handler definitions for GDB, the GNU Debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This file is almost the same as including <signal.h> except that it
+ eliminates certain signal names when job control is not supported,
+ (or, on some systems, when job control is there but doesn't work
+ the way GDB expects it to work). */
+
+#include <signal.h>
+
+#ifdef NO_JOB_CONTROL
+# undef SIGTSTP
+# undef SIGSTOP
+# undef SIGCONT
+# undef SIGTTIN
+# undef SIGTTOU
+#endif
--- /dev/null
+/* Convert between signal names and numbers.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <signal.h>
+#include "signame.h"
+
+#ifdef __STDC__
+#define CONST const
+#else
+#define CONST
+#endif
+
+#ifdef SYS_SIGLIST_MISSING
+/* There is too much variation in Sys V signal numbers and names, so
+ we must initialize them at runtime. */
+
+static CONST char undoc[] = "unknown signal";
+
+CONST char *sys_siglist[NSIG];
+#endif /* SYS_SIGLIST_MISSING */
+
+/* Table of abbreviations for signals. Note: A given number can
+ appear more than once with different abbreviations. */
+typedef struct
+ {
+ int number;
+ CONST char *abbrev;
+ } num_abbrev;
+static num_abbrev sig_table[NSIG*2];
+/* Number of elements of sig_table used. */
+static int sig_table_nelts = 0;
+
+/* Enter signal number NUMBER into the tables with ABBREV and NAME. */
+static void
+init_sig (number, abbrev, name)
+ int number;
+ CONST char *abbrev;
+ CONST char *name;
+{
+#ifdef SYS_SIGLIST_MISSING
+ sys_siglist[number] = name;
+#endif
+ sig_table[sig_table_nelts].number = number;
+ sig_table[sig_table_nelts++].abbrev = abbrev;
+}
+
+static void init_sigs ()
+{
+#ifdef SYS_SIGLIST_MISSING
+ /* Initialize signal names. */
+ for (i = 0; i < NSIG; i++)
+ sys_siglist[i] = undoc;
+#endif /* SYS_SIGLIST_MISSING */
+
+ /* Initialize signal names. */
+#if defined (SIGHUP)
+ init_sig (SIGHUP, "HUP", "Hangup");
+#endif
+#if defined (SIGINT)
+ init_sig (SIGINT, "INT", "Interrupt");
+#endif
+#if defined (SIGQUIT)
+ init_sig (SIGQUIT, "QUIT", "Quit");
+#endif
+#if defined (SIGILL)
+ init_sig (SIGILL, "ILL", "Illegal Instruction");
+#endif
+#if defined (SIGTRAP)
+ init_sig (SIGTRAP, "TRAP", "Trace/breakpoint trap");
+#endif
+ /* If SIGIOT == SIGABRT, we want to print it as SIGABRT because
+ SIGABRT is in ANSI and POSIX.1 and SIGIOT isn't. */
+#if defined (SIGABRT)
+ init_sig (SIGABRT, "ABRT", "Aborted");
+#endif
+#if defined (SIGIOT)
+ init_sig (SIGIOT, "IOT", "IOT trap");
+#endif
+#if defined (SIGEMT)
+ init_sig (SIGEMT, "EMT", "EMT trap");
+#endif
+#if defined (SIGFPE)
+ init_sig (SIGFPE, "FPE", "Floating point exception");
+#endif
+#if defined (SIGKILL)
+ init_sig (SIGKILL, "KILL", "Killed");
+#endif
+#if defined (SIGBUS)
+ init_sig (SIGBUS, "BUS", "Bus error");
+#endif
+#if defined (SIGSEGV)
+ init_sig (SIGSEGV, "SEGV", "Segmentation fault");
+#endif
+#if defined (SIGSYS)
+ init_sig (SIGSYS, "SYS", "Bad system call");
+#endif
+#if defined (SIGPIPE)
+ init_sig (SIGPIPE, "PIPE", "Broken pipe");
+#endif
+#if defined (SIGALRM)
+ init_sig (SIGALRM, "ALRM", "Alarm clock");
+#endif
+#if defined (SIGTERM)
+ init_sig (SIGTERM, "TERM", "Terminated");
+#endif
+#if defined (SIGUSR1)
+ init_sig (SIGUSR1, "USR1", "User defined signal 1");
+#endif
+#if defined (SIGUSR2)
+ init_sig (SIGUSR2, "USR2", "User defined signal 2");
+#endif
+ /* If SIGCLD == SIGCHLD, we want to print it as SIGCHLD because that
+ is what is in POSIX.1. */
+#if defined (SIGCHLD)
+ init_sig (SIGCHLD, "CHLD", "Child exited");
+#endif
+#if defined (SIGCLD)
+ init_sig (SIGCLD, "CLD", "Child exited");
+#endif
+#if defined (SIGPWR)
+ init_sig (SIGPWR, "PWR", "Power failure");
+#endif
+#if defined (SIGTSTP)
+ init_sig (SIGTSTP, "TSTP", "Stopped");
+#endif
+#if defined (SIGTTIN)
+ init_sig (SIGTTIN, "TTIN", "Stopped (tty input)");
+#endif
+#if defined (SIGTTOU)
+ init_sig (SIGTTOU, "TTOU", "Stopped (tty output)");
+#endif
+#if defined (SIGSTOP)
+ init_sig (SIGSTOP, "STOP", "Stopped (signal)");
+#endif
+#if defined (SIGXCPU)
+ init_sig (SIGXCPU, "XCPU", "CPU time limit exceeded");
+#endif
+#if defined (SIGXFSZ)
+ init_sig (SIGXFSZ, "XFSZ", "File size limit exceeded");
+#endif
+#if defined (SIGVTALRM)
+ init_sig (SIGVTALRM, "VTALRM", "Virtual timer expired");
+#endif
+#if defined (SIGPROF)
+ init_sig (SIGPROF, "PROF", "Profiling timer expired");
+#endif
+#if defined (SIGWINCH)
+ /* "Window size changed" might be more accurate, but even if that
+ is all that it means now, perhaps in the future it will be
+ extended to cover other kinds of window changes. */
+ init_sig (SIGWINCH, "WINCH", "Window changed");
+#endif
+#if defined (SIGCONT)
+ init_sig (SIGCONT, "CONT", "Continued");
+#endif
+#if defined (SIGURG)
+ init_sig (SIGURG, "URG", "Urgent I/O condition");
+#endif
+#if defined (SIGIO)
+ /* "I/O pending" has also been suggested. A disadvantage is
+ that signal only happens when the process has
+ asked for it, not everytime I/O is pending. Another disadvantage
+ is the confusion from giving it a different name than under Unix. */
+ init_sig (SIGIO, "IO", "I/O possible");
+#endif
+#if defined (SIGWIND)
+ init_sig (SIGWIND, "WIND", "SIGWIND");
+#endif
+#if defined (SIGPHONE)
+ init_sig (SIGPHONE, "PHONE", "SIGPHONE");
+#endif
+#if defined (SIGPOLL)
+ init_sig (SIGPOLL, "POLL", "I/O possible");
+#endif
+#if defined (SIGLOST)
+ init_sig (SIGLOST, "LOST", "Resource lost");
+#endif
+}
+
+/* Return the abbreviation for signal NUMBER. */
+char *
+sig_abbrev (number)
+ int number;
+{
+ int i;
+
+ for (i = 0; i < sig_table_nelts; i++)
+ if (sig_table[i].number == number)
+ return (char *)sig_table[i].abbrev;
+ return NULL;
+}
+
+/* Return the signal number for an ABBREV, or -1 if there is no
+ signal by that name. */
+int
+sig_number (abbrev)
+ CONST char *abbrev;
+{
+ int i;
+
+ /* Skip over "SIG" if present. */
+ if (abbrev[0] == 'S' && abbrev[1] == 'I' && abbrev[2] == 'G')
+ abbrev += 3;
+
+ for (i = 0; i < sig_table_nelts; i++)
+ if (abbrev[0] == sig_table[i].abbrev[0]
+ && strcmp (abbrev, sig_table[i].abbrev) == 0)
+ return sig_table[i].number;
+ return -1;
+}
+
+#if defined (SYS_SIGLIST_MISSING)
+/* Print to standard error the name of SIGNAL, preceded by MESSAGE and
+ a colon, and followed by a newline. */
+void
+psignal (signal, message)
+ unsigned signal;
+ CONST char *message;
+{
+ if (signal <= 0 || signal >= NSIG)
+ fprintf (stderr, "%s: unknown signal", message);
+ else
+ fprintf (stderr, "%s: %s\n", message, sys_siglist[signal]);
+}
+#endif
+
+void
+_initialize_signame ()
+{
+ init_sigs ();
+}
--- /dev/null
+/* Convert between signal names and numbers.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Names for signals from 0 to NSIG-1. */
+extern char *sys_siglist[];
+
+#ifdef __STDC__
+/* Return the abbreviation (e.g. ABRT, FPE, etc.) for signal NUMBER.
+ Do not return this as a const char *. The caller might want to
+ assign it to a char *. */
+char *sig_abbrev (int number);
+
+/* Return the signal number for an ABBREV, or -1 if there is no
+ signal by that name. */
+int sig_number (const char *abbrev);
+
+/* Print to standard error the name of SIGNAL, preceded by MESSAGE and
+ a colon, and followed by a newline. */
+void psignal (unsigned signal, const char *message);
+
+#else
+
+char *sig_abbrev ();
+int sig_number ();
+void psignal ();
+
+#endif
--- /dev/null
+/* Table of opcodes for the sparc.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+struct sparc_opcode
+{
+ const char *name;
+ unsigned long int match; /* Bits that must be set. */
+ unsigned long int lose; /* Bits that must not be set. */
+ const char *args;
+ char flags;
+};
+
+#define F_DELAYED 1 /* Delayed branch */
+#define F_ALIAS 2 /* Alias for a "real" instruction */
+
+/*
+ All sparc opcodes are 32 bits, except for the `set' instruction (really
+ a macro), which is 64 bits. It is handled as a special case.
+
+ The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing one character
+ for each operand of the instruction.
+
+Kinds of operands:
+ # Number used by optimizer. It is ignored.
+ 1 rs1 register.
+ 2 rs2 register.
+ d rd register.
+ e frs1 floating point register.
+ f frs2 floating point register.
+ g frsd floating point register.
+ b crs1 coprocessor register
+ c crs2 coprocessor register
+ D crsd coprocessor register
+ h 22 high bits.
+ i 13 bit Immediate.
+ l 22 bit PC relative immediate.
+ L 30 bit PC relative immediate.
+ a Annul. The annul bit is set.
+ A Alternate address space. Stored as 8 bits.
+ C Coprocessor state register.
+ F floating point state register.
+ p Processor state register.
+ q Floating point queue.
+ r Single register that is both rs1 and rsd.
+ Q Coprocessor queue.
+ S Special case.
+ t Trap base register.
+ w Window invalid mask register.
+ y Y register.
+
+*/
+
+/* The order of the opcodes in this table is significant:
+
+ * The assembler requires that all instances of the same mnemonic must be
+ consecutive. If they aren't, the assembler will bomb at runtime.
+
+ * The disassembler should not care about the order of the opcodes. */
+
+static struct sparc_opcode sparc_opcodes[] =
+{
+
+{ "ldd", 0xc1980000, 0x0060201f, "[1],D", 0 }, /* ldd [rs1+%g0],d */
+{ "ldd", 0xc1982000, 0x00601fff, "[1],D", 0 }, /* ldd [rs1+0],d */
+{ "ldd", 0xc1982000, 0x00600000, "[1+i],D", 0 },
+{ "ldd", 0xc1982000, 0x00600000, "[i+1],D", 0 },
+{ "ldd", 0xc1980000, 0x00602000, "[1+2],D", 0 },
+{ "ldd", 0xc1180000, 0x00e0201f, "[1],g", 0 }, /* ldd [rs1+%g0],d */
+{ "ldd", 0xc1182000, 0x00e01fff, "[1],g", 0 }, /* ldd [rs1+0],d */
+{ "ldd", 0xc1182000, 0x00e00000, "[1+i],g", 0 },
+{ "ldd", 0xc1182000, 0x00e00000, "[i+1],g", 0 },
+{ "ldd", 0xc1180000, 0x00e02000, "[1+2],g", 0 },
+{ "ldd", 0xc0180000, 0x01e0201f, "[1],d", 0 }, /* ldd [rs1+%g0],d */
+{ "ldd", 0xc0182000, 0x01e01fff, "[1],d", 0 }, /* ldd [rs1+0],d */
+{ "ldd", 0xc0182000, 0x01e00000, "[1+i],d", 0 },
+{ "ldd", 0xc0182000, 0x01e00000, "[i+1],d", 0 },
+{ "ldd", 0xc0180000, 0x01e02000, "[1+2],d", 0 },
+{ "ld", 0xc1880000, 0x0070201f, "[1],C", 0 }, /* ld [rs1+%g0],d */
+{ "ld", 0xc1882000, 0x00701fff, "[1],C", 0 }, /* ld [rs1+0],d */
+{ "ld", 0xc1882000, 0x00700000, "[1+i],C", 0 },
+{ "ld", 0xc1882000, 0x00700000, "[i+1],C", 0 },
+{ "ld", 0xc1880000, 0x00702000, "[1+2],C", 0 },
+{ "ld", 0xc1800000, 0x0078201f, "[1],D", 0 }, /* ld [rs1+%g0],d */
+{ "ld", 0xc1802000, 0x00781fff, "[1],D", 0 }, /* ld [rs1+0],d */
+{ "ld", 0xc1802000, 0x00780000, "[1+i],D", 0 },
+{ "ld", 0xc1802000, 0x00780000, "[i+1],D", 0 },
+{ "ld", 0xc1800000, 0x00782000, "[1+2],D", 0 },
+{ "ld", 0xc1080000, 0x00f0201f, "[1],F", 0 }, /* ld [rs1+%g0],d */
+{ "ld", 0xc1082000, 0x00f01fff, "[1],F", 0 }, /* ld [rs1+0],d */
+{ "ld", 0xc1082000, 0x00f00000, "[1+i],F", 0 },
+{ "ld", 0xc1082000, 0x00f00000, "[i+1],F", 0 },
+{ "ld", 0xc1080000, 0x00f02000, "[1+2],F", 0 },
+{ "ld", 0xc1000000, 0x00f8201f, "[1],g", 0 }, /* ld [rs1+%g0],d */
+{ "ld", 0xc1002000, 0x00f81fff, "[1],g", 0 }, /* ld [rs1+0],d */
+{ "ld", 0xc1002000, 0x00f80000, "[1+i],g", 0 },
+{ "ld", 0xc1002000, 0x00f80000, "[i+1],g", 0 },
+{ "ld", 0xc1000000, 0x00f82000, "[1+2],g", 0 },
+{ "ld", 0xc0000000, 0x01f8201f, "[1],d", 0 }, /* ld [rs1+%g0],d */
+{ "ld", 0xc0002000, 0x01f81fff, "[1],d", 0 }, /* ld [rs1+0],d */
+{ "ld", 0xc0002000, 0x01f80000, "[1+i],d", 0 },
+{ "ld", 0xc0002000, 0x01f80000, "[i+1],d", 0 },
+{ "ld", 0xc0000000, 0x01f82000, "[1+2],d", 0 },
+{ "ldstuba", 0xc0d80000, 0x0100201f, "[1]A,d", 0 }, /* ldstuba [rs1+%g0],d */
+{ "ldstuba", 0xc0d80000, 0x01002000, "[1+2]A,d", 0 },
+{ "ldsha", 0xc0d00000, 0x0128201f, "[1]A,d", 0 }, /* ldsha [rs1+%g0],d */
+{ "ldsha", 0xc0d00000, 0x01282000, "[1+2]A,d", 0 },
+{ "ldsba", 0xc0c80000, 0x0130201f, "[1]A,d", 0 }, /* ldsba [rs1+%g0],d */
+{ "ldsba", 0xc0c80000, 0x01302000, "[1+2]A,d", 0 },
+{ "ldda", 0xc0980000, 0x0160201f, "[1]A,d", 0 }, /* ldda [rs1+%g0],d */
+{ "ldda", 0xc0980000, 0x01602000, "[1+2]A,d", 0 },
+{ "lduha", 0xc0900000, 0x0168201f, "[1]A,d", 0 }, /* lduha [rs1+%g0],d */
+{ "lduha", 0xc0900000, 0x01682000, "[1+2]A,d", 0 },
+{ "ldstub", 0xc0680000, 0x0190201f, "[1],d", 0 }, /* ldstub [rs1+%g0],d */
+{ "ldstub", 0xc0682000, 0x01900000, "[1+i],d", 0 },
+{ "ldstub", 0xc0682000, 0x01900000, "[i+1],d", 0 },
+{ "ldstub", 0xc0680000, 0x01902000, "[1+2],d", 0 },
+{ "lda", 0xc0800000, 0x0178201f, "[1]A,d", 0 }, /* lda [rs1+%g0],d */
+{ "lda", 0xc0800000, 0x01782000, "[1+2]A,d", 0 },
+{ "ldsh", 0xc0500000, 0x0000000d, "[1],d", 0 }, /* ldsh [rs1+%g0],d */
+{ "ldsh", 0xc0502000, 0x01a81fff, "[1],d", 0 }, /* ldsh [rs1+0],d */
+{ "ldsh", 0xc0502000, 0x01a80000, "[1+i],d", 0 },
+{ "ldsh", 0xc0502000, 0x01a80000, "[i+1],d", 0 },
+{ "ldsh", 0xc0500000, 0x01a82000, "[1+2],d", 0 },
+{ "ldsb", 0xc0480000, 0x01b0201f, "[1],d", 0 }, /* ldsb [rs1+%g0],d */
+{ "ldsb", 0xc0482000, 0x01b01fff, "[1],d", 0 }, /* ldsb [rs1+0],d */
+{ "ldsb", 0xc0482000, 0x01b00000, "[1+i],d", 0 },
+{ "ldsb", 0xc0482000, 0x01b00000, "[i+1],d", 0 },
+{ "ldsb", 0xc0480000, 0x01b02000, "[1+2],d", 0 },
+{ "ldub", 0xc0080000, 0x01f0201f, "[1],d", 0 }, /* ldub [rs1+%g0],d */
+{ "ldub", 0xc0082000, 0x01f01fff, "[1],d", 0 }, /* ldub [rs1+0],d */
+{ "ldub", 0xc0082000, 0x01f00000, "[1+i],d", 0 },
+{ "ldub", 0xc0082000, 0x01f00000, "[i+1],d", 0 },
+{ "ldub", 0xc0080000, 0x01f02000, "[1+2],d", 0 },
+{ "lduba", 0xc0880000, 0x0170201f, "[1]A,d", 0 }, /* lduba [rs1+%g0],d */
+{ "lduba", 0xc0880000, 0x01702000, "[1+2]A,d", 0 },
+{ "lduh", 0xc0102000, 0x01e80000, "[1+i],d", 0 },
+{ "lduh", 0xc0102000, 0x01e80000, "[i+1],d", 0 },
+{ "lduh", 0xc0100000, 0x01e8201f, "[1],d", 0 }, /* lduh [rs1+%g0],d */
+{ "lduh", 0xc0102000, 0x01e81fff, "[1],d", 0 }, /* lduh [rs1+0],d */
+{ "lduh", 0xc0100000, 0x01e82000, "[1+2],d", 0 },
+
+{ "st", 0xc0200000, 0x01d8201f, "d,[1]", 0 }, /* st d,[rs1+%g0] */
+{ "st", 0xc0202000, 0x01d81fff, "d,[1]", 0 }, /* st d,[rs1+0] */
+{ "st", 0xc0202000, 0x01d80000, "d,[1+i]", 0 },
+{ "st", 0xc0202000, 0x01d80000, "d,[i+1]", 0 },
+{ "st", 0xc0200000, 0x01d82000, "d,[1+2]", 0 },
+{ "st", 0xc1200000, 0x00d8201f, "g,[1]", 0 }, /* st d[rs1+%g0] */
+{ "st", 0xc1202000, 0x00d81fff, "g,[1]", 0 }, /* st d,[rs1+0] */
+{ "st", 0xc1202000, 0x00d80000, "g,[1+i]", 0 },
+{ "st", 0xc1202000, 0x00d80000, "g,[i+1]", 0 },
+{ "st", 0xc1200000, 0x00d82000, "g,[1+2]", 0 },
+{ "st", 0xc1280000, 0x00d0201f, "F,[1]", 0 }, /* st %fsr,[rs1+%g0] */
+{ "st", 0xc1282000, 0x00d01fff, "F,[1]", 0 }, /* st %fsr,[rs1+0] */
+{ "st", 0xc1282000, 0x00d00000, "F,[1+i]", 0 },
+{ "st", 0xc1282000, 0x00d00000, "F,[i+1]", 0 },
+{ "st", 0xc1280000, 0x00d02000, "F,[1+2]", 0 },
+{ "st", 0xc1a00000, 0x0058201f, "D,[1]", 0 }, /* st d,[rs1+%g0] */
+{ "st", 0xc1a02000, 0x00581fff, "D,[1]", 0 }, /* st d,[rs1+0] */
+{ "st", 0xc1a02000, 0x00580000, "D,[1+i]", 0 },
+{ "st", 0xc1a02000, 0x00580000, "D,[i+1]", 0 },
+{ "st", 0xc1a00000, 0x00582000, "D,[1+2]", 0 },
+{ "st", 0xc1a80000, 0x0050201f, "C,[1]", 0 }, /* st d,[rs1+%g0] */
+{ "st", 0xc1a82000, 0x00501fff, "C,[1]", 0 }, /* st d,[rs1+0] */
+{ "st", 0xc1a82000, 0x00500000, "C,[1+i]", 0 },
+{ "st", 0xc1a82000, 0x00500000, "C,[i+1]", 0 },
+{ "st", 0xc1a80000, 0x00502000, "C,[1+2]", 0 },
+{ "sta", 0xc0a00000, 0x0108201f, "d,[1]A", 0 }, /* sta d,[rs1+%g0] */
+{ "sta", 0xc0a00000, 0x01082000, "d,[1+2]A", 0 },
+
+{ "stb", 0xc0280000, 0x01d0201f, "d,[1]", 0 }, /* stb d,[rs1+%g0] */
+{ "stb", 0xc0282000, 0x01d01fff, "d,[1]", 0 }, /* stb d,[rs1+0] */
+{ "stb", 0xc0282000, 0x01d00000, "d,[1+i]", 0 },
+{ "stb", 0xc0282000, 0x01d00000, "d,[i+1]", 0 },
+{ "stb", 0xc0280000, 0x01d02000, "d,[1+2]", 0 },
+{ "stba", 0xc0a80000, 0x01002000, "d,[1+2]A", 0 },
+{ "stba", 0xc0a80000, 0x0100201f, "d,[1]A", 0 }, /* stba d,[rs1+%g0] */
+
+{ "std", 0xc0380000, 0x01c0201f, "d,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std", 0xc0382000, 0x01c01fff, "d,[1]", 0 }, /* std d,[rs1+0] */
+{ "std", 0xc0382000, 0x01c00000, "d,[1+i]", 0 },
+{ "std", 0xc0382000, 0x01c00000, "d,[i+1]", 0 },
+{ "std", 0xc0380000, 0x01c02000, "d,[1+2]", 0 },
+{ "std", 0xc1380000, 0x00c0201f, "g,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std", 0xc1382000, 0x00c01fff, "g,[1]", 0 }, /* std d,[rs1+0] */
+{ "std", 0xc1382000, 0x00c00000, "g,[1+i]", 0 },
+{ "std", 0xc1382000, 0x00c00000, "g,[i+1]", 0 },
+{ "std", 0xc1380000, 0x00c02000, "g,[1+2]", 0 },
+{ "std", 0xc1300000, 0x00c8201f, "q,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std", 0xc1302000, 0x00c81fff, "q,[1]", 0 }, /* std d,[rs1+0] */
+{ "std", 0xc1302000, 0x00c80000, "q,[1+i]", 0 },
+{ "std", 0xc1302000, 0x00c80000, "q,[i+1]", 0 },
+{ "std", 0xc1300000, 0x00c82000, "q,[1+2]", 0 },
+{ "std", 0xc1b80000, 0x0040201f, "D,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std", 0xc1b82000, 0x00401fff, "D,[1]", 0 }, /* std d,[rs1+0] */
+{ "std", 0xc1b82000, 0x00400000, "D,[1+i]", 0 },
+{ "std", 0xc1b82000, 0x00400000, "D,[i+1]", 0 },
+{ "std", 0xc1b80000, 0x00402000, "D,[1+2]", 0 },
+{ "std", 0xc1b00000, 0x0048201f, "Q,[1]", 0 }, /* std d,[rs1+%g0] */
+{ "std", 0xc1b02000, 0x00481fff, "Q,[1]", 0 }, /* std d,[rs1+0] */
+{ "std", 0xc1b02000, 0x00480000, "Q,[1+i]", 0 },
+{ "std", 0xc1b02000, 0x00480000, "Q,[i+1]", 0 },
+{ "std", 0xc1b00000, 0x00482000, "Q,[1+2]", 0 },
+{ "stda", 0xc0b80000, 0x01402000, "d,[1+2]A", 0 },
+{ "stda", 0xc0b80000, 0x0140201f, "d,[1]A", 0 }, /* stda d,[rs1+%g0] */
+
+{ "sth", 0xc0300000, 0x01c8201f, "d,[1]", 0 }, /* sth d,[rs1+%g0] */
+{ "sth", 0xc0302000, 0x01c81fff, "d,[1]", 0 }, /* sth d,[rs1+0] */
+{ "sth", 0xc0300000, 0x01c82000, "d,[1+2]", 0 },
+{ "sth", 0xc0302000, 0x01c80000, "d,[1+i]", 0 },
+{ "sth", 0xc0302000, 0x01c80000, "d,[i+1]", 0 },
+{ "stha", 0xc0b00000, 0x0148201f, "d,[1]A", 0 }, /* stha d,[rs1+%g0] */
+{ "stha", 0xc0b00000, 0x01482000, "d,[1+2]A", 0 },
+
+{ "swap", 0xc0780000, 0x0180201f, "[1],d", 0 }, /* swap [rs1+%g0],d */
+{ "swap", 0xc0782000, 0x01801fff, "[1],d", 0 }, /* swap [rs1+0],d */
+{ "swap", 0xc0782000, 0x01800000, "[1+i],d", 0 },
+{ "swap", 0xc0782000, 0x01800000, "[i+1],d", 0 },
+{ "swap", 0xc0780000, 0x01802000, "[1+2],d", 0 },
+{ "swapa", 0xc0f80000, 0x01002000, "[1+2]A,d", 0 },
+{ "swapa", 0xc0f80000, 0x0100201f, "[1]A,d", 0 }, /* swapa [rs1+%g0],d */
+
+{ "restore", 0x81e80000, 0x7e17e01f, "", 0 }, /* restore %g0,%g0,%g0 */
+{ "restore", 0x81e82000, 0x7e14dfff, "", 0 }, /* restore %g0,0,%g0 */
+{ "restore", 0x81e82000, 0x00000000, "1,i,d", 0 },
+{ "restore", 0x81e80000, 0x00000000, "1,2,d", 0 },
+{ "rett", 0x81c82000, 0x40300000, "1+i", F_DELAYED },
+{ "rett", 0x81c82000, 0x40300000, "i+1", F_DELAYED },
+{ "rett", 0x81c80000, 0x40302000, "1+2", F_DELAYED },
+{ "rett", 0x81c82000, 0x40301fff, "1", F_DELAYED}, /* rett X,0 */
+{ "rett", 0x81c80000, 0x4030201f, "1", F_DELAYED}, /* rett X,%g0 */
+{ "save", 0x81e02000, 0x40180000, "1,i,d", 0 },
+{ "save", 0x81e00000, 0x40180000, "1,2,d", 0 },
+
+{ "ret", 0x81c7e008, 0x00001ff7, "", F_DELAYED }, /* jmpl %i7+8,%g0 */
+{ "retl", 0x81c3e008, 0x00001ff7, "", F_DELAYED }, /* jmpl %o7+8,%g0 */
+
+{ "jmpl", 0x81c00000, 0x4038201f, "1,d", F_DELAYED }, /* jmpl rs1+%g0,d */
+{ "jmpl", 0x81c02000, 0x4037c000, "i,d", F_DELAYED }, /* jmpl %g0+i,d */
+{ "jmpl", 0x81c02000, 0x40380000, "1+i,d", F_DELAYED },
+{ "jmpl", 0x81c02000, 0x40380000, "i+1,d", F_DELAYED },
+{ "jmpl", 0x81c00000, 0x40382000, "1+2,d", F_DELAYED },
+{ "wr", 0x81982000, 0x40600000, "1,i,t", 0 },
+{ "wr", 0x81980000, 0x40600000, "1,2,t", 0 },
+{ "wr", 0x81902000, 0x40680000, "1,i,w", 0 },
+{ "wr", 0x81900000, 0x40680000, "1,2,w", 0 },
+{ "wr", 0x81882000, 0x40700000, "1,i,p", 0 },
+{ "wr", 0x81880000, 0x40700000, "1,2,p", 0 },
+{ "wr", 0x81802000, 0x40780000, "1,i,y", 0 },
+{ "wr", 0x81800000, 0x40780000, "1,2,y", 0 },
+
+{ "rd", 0x81580000, 0x40a00000, "t,d", 0 },
+{ "rd", 0x81500000, 0x40a80000, "w,d", 0 },
+{ "rd", 0x81480000, 0x40b00000, "p,d", 0 },
+{ "rd", 0x81400000, 0x40b80000, "y,d", 0 },
+
+{ "sra", 0x81382000, 0x00000000, "1,i,d", 0 },
+{ "sra", 0x81380000, 0x00000000, "1,2,d", 0 },
+{ "srl", 0x81302000, 0x40c80000, "1,i,d", 0 },
+{ "srl", 0x81300000, 0x40c80000, "1,2,d", 0 },
+{ "sll", 0x81282000, 0x40d00000, "1,i,d", 0 },
+{ "sll", 0x81280000, 0x40d00000, "1,2,d", 0 },
+
+{ "mulscc", 0x81202000, 0x40d80000, "1,i,d", 0 },
+{ "mulscc", 0x81200000, 0x40d80000, "1,2,d", 0 },
+
+{ "clr", 0x80100000, 0x4e87e01f, "d", F_ALIAS }, /* or %g0,%g0,d */
+{ "clr", 0x80102000, 0x41efdfff, "d", F_ALIAS }, /* or %g0,0,d */
+{ "clr", 0xc0200000, 0x3fd8001f, "[1]", F_ALIAS }, /* st %g0,[rs1+%g0] */
+{ "clr", 0xc0202000, 0x3fd81fff, "[1]", F_ALIAS }, /* st %g0,[rs1+0] */
+{ "clr", 0xc0202000, 0x3fd80000, "[1+i]", F_ALIAS },
+{ "clr", 0xc0202000, 0x3fd80000, "[i+1]", F_ALIAS },
+{ "clr", 0xc0200000, 0x3fd80000, "[1+2]", F_ALIAS },
+
+{ "clrb", 0xc0280000, 0x3fd0001f, "[1]", F_ALIAS },/* stb %g0,[rs1+%g0] */
+{ "clrb", 0xc0282000, 0x3fd00000, "[1+i]", F_ALIAS },
+{ "clrb", 0xc0282000, 0x3fd00000, "[i+1]", F_ALIAS },
+{ "clrb", 0xc0280000, 0x3fd00000, "[1+2]", F_ALIAS },
+
+{ "clrh", 0xc0300000, 0x3fc8001f, "[1]", F_ALIAS },/* sth %g0,[rs1+%g0] */
+{ "clrh", 0xc0300000, 0x3fc80000, "[1+2]", F_ALIAS },
+{ "clrh", 0xc0302000, 0x3fc80000, "[1+i]", F_ALIAS },
+{ "clrh", 0xc0302000, 0x3fc80000, "[i+1]", F_ALIAS },
+
+{ "orncc", 0x80b02000, 0x04048000, "1,i,d", 0 },
+{ "orncc", 0x80b00000, 0x04048000, "1,2,d", 0 },
+
+{ "tst", 0x80900000, 0x7f6fe000, "2", 0 }, /* orcc %g0, rs2, %g0 */
+{ "tst", 0x80900000, 0x7f68201f, "1", 0 }, /* orcc rs1, %g0, %g0 */
+{ "tst", 0x80902000, 0x7f681fff, "1", 0 }, /* orcc rs1, 0, %g0 */
+
+{ "orcc", 0x80902000, 0x41680000, "1,i,d", 0 },
+{ "orcc", 0x80902000, 0x41680000, "i,1,d", 0 },
+{ "orcc", 0x80900000, 0x41680000, "1,2,d", 0 },
+{ "orn", 0x80302000, 0x41c80000, "1,i,d", 0 },
+{ "orn", 0x80300000, 0x41c80000, "1,2,d", 0 },
+
+{ "mov", 0x81800000, 0x4078201f, "1,y", F_ALIAS }, /* wr rs1,%g0,%y */
+{ "mov", 0x81802000, 0x40781fff, "1,y", F_ALIAS }, /* wr rs1,0,%y */
+{ "mov", 0x81802000, 0x40780000, "i,y", F_ALIAS },
+{ "mov", 0x81400000, 0x40b80000, "y,d", F_ALIAS }, /* rd %y,d */
+{ "mov", 0x81980000, 0x4060201f, "1,t", F_ALIAS }, /* wr rs1,%g0,%tbr */
+{ "mov", 0x81982000, 0x40601fff, "1,t", F_ALIAS }, /* wr rs1,0,%tbr */
+{ "mov", 0x81982000, 0x40600000, "i,t", F_ALIAS },
+{ "mov", 0x81580000, 0x40a00000, "t,d", F_ALIAS }, /* rd %tbr,d */
+{ "mov", 0x81900000, 0x4068201f, "1,w", F_ALIAS }, /* wr rs1,%g0,%wim */
+{ "mov", 0x81902000, 0x40681fff, "1,w", F_ALIAS }, /* wr rs1,0,%wim */
+{ "mov", 0x81902000, 0x40680000, "i,w", F_ALIAS },
+{ "mov", 0x81500000, 0x40a80000, "w,d", F_ALIAS }, /* rd %wim,d */
+{ "mov", 0x81880000, 0x4070201f, "1,p", F_ALIAS }, /* wr rs1,%g0,%psr */
+{ "mov", 0x81882000, 0x40701fff, "1,p", F_ALIAS }, /* wr rs1,0,%psr */
+{ "mov", 0x81882000, 0x40700000, "i,p", F_ALIAS },
+{ "mov", 0x81480000, 0x40b00000, "p,d", F_ALIAS }, /* rd %psr,d */
+
+{ "mov", 0x80102000, 0x41efc000, "i,d", 0 }, /* or %g0,i,d */
+{ "mov", 0x80100000, 0x41efe000, "2,d", 0 }, /* or %g0,rs2,d */
+{ "mov", 0x80102000, 0x41e81fff, "1,d", 0 }, /* or rs1,0,d */
+{ "mov", 0x80100000, 0x41e8201f, "1,d", 0 }, /* or rs1,%g0,d */
+
+{ "or", 0x80102000, 0x40800000, "1,i,d", 0 },
+{ "or", 0x80102000, 0x40800000, "i,1,d", 0 },
+{ "or", 0x80100000, 0x40800000, "1,2,d", 0 },
+
+{ "bset", 0x80102000, 0x40800000, "i,r", F_ALIAS },/* or rd,i,rd */
+{ "bset", 0x80100000, 0x40800000, "2,r", F_ALIAS },/* or rd,rs2,rd */
+
+{ "andncc", 0x80a82000, 0x41500000, "1,i,d", 0 },
+{ "andncc", 0x80a80000, 0x41500000, "1,2,d", 0 },
+{ "andn", 0x80282000, 0x41d00000, "1,i,d", 0 },
+{ "andn", 0x80280000, 0x41d00000, "1,2,d", 0 },
+
+{ "bclr", 0x80282000, 0x41d00000, "i,r", F_ALIAS },/* andn rd,i,rd */
+{ "bclr", 0x80280000, 0x41d00000, "2,r", F_ALIAS },/* andn rd,rs2,rd */
+
+{ "cmp", 0x80a02000, 0x7d580000, "1,i", 0 }, /* subcc rs1,i,%g0 */
+{ "cmp", 0x80a00000, 0x7d580000, "1,2", 0 }, /* subcc rs1,rs2,%g0 */
+
+{ "subcc", 0x80a02000, 0x41580000, "1,i,d", 0 },
+{ "subcc", 0x80a00000, 0x41580000, "1,2,d", 0 },
+{ "sub", 0x80202000, 0x41d80000, "1,i,d", 0 },
+{ "sub", 0x80200000, 0x41d80000, "1,2,d", 0 },
+{ "subx", 0x80602000, 0x41980000, "1,i,d", 0 },
+{ "subx", 0x80600000, 0x41980000, "1,2,d", 0 },
+{ "subxcc", 0x80e02000, 0x41180000, "1,i,d", 0 },
+{ "subxcc", 0x80e00000, 0x41180000, "1,2,d", 0 },
+
+{ "andcc", 0x80882000, 0x41700000, "1,i,d", 0 },
+{ "andcc", 0x80882000, 0x41700000, "i,1,d", 0 },
+{ "andcc", 0x80880000, 0x41700000, "1,2,d", 0 },
+{ "and", 0x80082000, 0x41f00000, "1,i,d", 0 },
+{ "and", 0x80082000, 0x41f00000, "i,1,d", 0 },
+{ "and", 0x80080000, 0x41f00000, "1,2,d", 0 },
+
+{ "inc", 0x80002001, 0x41f81ffe, "r", F_ALIAS }, /* add rs1,1,rsd */
+{ "inccc", 0x80802001, 0x41781ffe, "r", F_ALIAS }, /* addcc rd,1,rd */
+{ "dec", 0x80202001, 0x41d81ffe, "r", F_ALIAS }, /* sub rd,1,rd */
+{ "deccc", 0x80a02001, 0x41581ffe, "r", F_ALIAS }, /* subcc rd,1,rd */
+
+{ "btst", 0x80882000, 0x41700000, "i,1", F_ALIAS },/* andcc rs1,i,%g0 */
+{ "btst", 0x80880000, 0x41700000, "1,2", F_ALIAS },/* andcc rs1,rs2,%0 */
+
+{ "neg", 0x80200000, 0x41d80000, "r", F_ALIAS }, /* sub %0,rd,rd */
+{ "neg", 0x80200000, 0x41d80000, "2,d", F_ALIAS }, /* sub %0,rs2,rd */
+
+{ "addxcc", 0x80c02000, 0x41380000, "1,i,d", 0 },
+{ "addxcc", 0x80c02000, 0x41380000, "i,1,d", 0 },
+{ "addxcc", 0x80c00000, 0x41380000, "1,2,d", 0 },
+{ "addcc", 0x80802000, 0x41780000, "1,i,d", 0 },
+{ "addcc", 0x80802000, 0x41780000, "i,1,d", 0 },
+{ "addcc", 0x80800000, 0x41780000, "1,2,d", 0 },
+{ "addx", 0x80402000, 0x41b80000, "1,i,d", 0 },
+{ "addx", 0x80402000, 0x41b80000, "i,1,d", 0 },
+{ "addx", 0x80400000, 0x41b80000, "1,2,d", 0 },
+{ "add", 0x80002000, 0x41f80000, "1,i,d", 0 },
+{ "add", 0x80002000, 0x41f80000, "i,1,d", 0 },
+{ "add", 0x80000000, 0x41f80000, "1,2,d", 0 },
+
+{ "call", 0x9fc00000, 0x4038201f, "1", F_DELAYED }, /* jmpl rs1+%g0, %o7 */
+{ "call", 0x9fc00000, 0x4038201f, "1,#", F_DELAYED },
+{ "call", 0x40000000, 0x80000000, "L", F_DELAYED },
+{ "call", 0x40000000, 0x80000000, "L,#", F_DELAYED },
+
+{ "jmp", 0x81c00000, 0x7e38201f, "1", F_DELAYED }, /* jmpl rs1+%g0,%g0 */
+{ "jmp", 0x81c02000, 0x7e3fc000, "i", F_DELAYED }, /* jmpl %g0+i,%g0 */
+{ "jmp", 0x81c00000, 0x7e382000, "1+2", F_DELAYED }, /* jmpl rs1+rs2,%g0 */
+{ "jmp", 0x81c02000, 0x7e380000, "1+i", F_DELAYED }, /* jmpl rs1+i,%g0 */
+{ "jmp", 0x81c02000, 0x7e380000, "i+1", F_DELAYED }, /* jmpl i+rs1,%g0 */
+
+{ "nop", 0x01000000, 0xfeffffff, "", 0 }, /* sethi 0, %g0 */
+
+{ "set", 0x01000000, 0xc0c00000, "Sh,d", F_ALIAS },
+
+{ "sethi", 0x01000000, 0xc0c00000, "h,d", 0 },
+
+{ "taddcctv", 0x81102000, 0x40e00000, "1,i,d", 0 },
+{ "taddcctv", 0x81100000, 0x40e00000, "1,2,d", 0 },
+{ "taddcc", 0x81002000, 0x40f80000, "1,i,d", 0 },
+{ "taddcc", 0x81000000, 0x40f80000, "1,2,d", 0 },
+
+/* Conditional instructions.
+
+ Because this part of the table was such a mess earlier, I have
+ macrofied it so that all the branches and traps are generated from
+ a single-line description of each condition value. */
+
+#define ANNUL 0x20000000
+#define IMMED 0x00002000
+#define RS1_G0 0x0007C000
+#define RS2_G0 0x0000001F
+
+/* Define two branches -- one annulled, one without */
+#define br(opcode, mask, lose, flags) \
+ { opcode, mask+ANNUL, lose, ",al", flags }, \
+ { opcode, mask , lose, "l", flags }
+
+/* Define four traps: reg+reg, reg + immediate, immediate alone, reg alone. */
+#define tr(opcode, mask, lose, flags) \
+ {opcode, mask+IMMED, lose+RS1_G0 , "i", flags }, /* %g0 + imm */ \
+ {opcode, mask+IMMED, lose , "1+i", flags }, /* rs1 + imm */ \
+ {opcode, mask , lose+IMMED , "1+2", flags }, /* rs1 + rs2 */ \
+ {opcode, mask , lose+IMMED+RS2_G0, "1", flags } /* rs1 + %g0 */
+
+/* Define both branches and traps based on condition mask */
+#ifdef __STDC__
+#define cond(bop, top, mask, flags) \
+ br(#bop, 0x00800000+(mask << 25), 0xC1400000, F_DELAYED|flags), \
+ tr(#top, 0x81d00000+(mask << 25), 0x40280000, flags)
+#else
+#define cond(bop, top, mask, flags) \
+ br("bop", 0x00800000+(mask << 25), 0xC1400000, F_DELAYED|flags), \
+ tr("top", 0x81d00000+(mask << 25), 0x40280000, flags)
+#endif
+
+/* Define all the conditions, all the branches, all the traps. */
+cond (bvc, tvc, 0xF, 0),
+cond (bvs, tvs, 0x7, 0),
+cond (bpos, tpos, 0xE, 0),
+cond (bneg, tneg, 0x6, 0),
+cond (bcc, tcc, 0xD, 0),
+cond (bcs, tcs, 0x5, 0),
+cond (blu, tlu, 0x5, F_ALIAS), /* for cs */
+cond (bgeu, tgeu, 0xD, F_ALIAS), /* for cc */
+cond (bgu, tgu, 0xC, 0),
+cond (bleu, tleu, 0x4, 0),
+cond (bge, tge, 0xB, 0),
+cond (bl, tl, 0x3, 0),
+cond (bg, tg, 0xA, 0),
+cond (ble, tle, 0x2, 0),
+cond (be, te, 0x1, 0),
+cond (bz, tz, 0x1, F_ALIAS), /* for e */
+cond (bne, tne, 0x9, 0),
+cond (bnz, tnz, 0x9, F_ALIAS), /* for ne */
+cond (b, t, 0x8, 0),
+cond (ba, ta, 0x8, F_ALIAS), /* for nothing */
+cond (bn, tn, 0x0, 0),
+
+#undef cond
+#undef br
+#undef tr
+
+{ "tsubcc", 0x81080000, 0x40f00000, "1,2,d", 0 },
+{ "tsubcc", 0x81082000, 0x40f00000, "1,i,d", 0 },
+{ "tsubcctv", 0x80580000, 0x40a00000, "1,2,d", 0 },
+{ "tsubcctv", 0x80582000, 0x40a00000, "1,i,d", 0 },
+
+{ "unimp", 0x00000000, 0xFFFFFFFF, "l", 0 },
+
+{ "iflush", 0x81d80000, 0x40202000, "1+2", 0 },
+{ "iflush", 0x81d82000, 0x40200000, "1+i", 0 },
+
+{ "xnorcc", 0x80b80000, 0x41400000, "1,2,d", 0 },
+{ "xnorcc", 0x80b82000, 0x41400000, "1,i,d", 0 },
+{ "xnorcc", 0x80b82000, 0x41400000, "i,1,d", 0 },
+{ "xorcc", 0x80980000, 0x41600000, "1,2,d", 0 },
+{ "xorcc", 0x80982000, 0x41600000, "1,i,d", 0 },
+{ "xorcc", 0x80982000, 0x41600000, "i,1,d", 0 },
+{ "xnor", 0x80380000, 0x41c00000, "1,2,d", 0 },
+{ "xnor", 0x80382000, 0x41c00000, "1,i,d", 0 },
+{ "xnor", 0x80382000, 0x41c00000, "i,1,d", 0 },
+{ "xor", 0x80180000, 0x41e00000, "1,2,d", 0 },
+{ "xor", 0x80182000, 0x41e00000, "1,i,d", 0 },
+{ "xor", 0x80182000, 0x41e00000, "i,1,d", 0 },
+
+{ "not", 0x80380000, 0x41c00000, "r", F_ALIAS }, /* xnor rd,%0,rd */
+{ "not", 0x80380000, 0x41c00000, "1,d", F_ALIAS }, /* xnor rs1,%0,rd */
+
+{ "btog", 0x80180000, 0x41e02000, "2,r", F_ALIAS }, /* xor rd,rs2,rd */
+{ "btog", 0x80182000, 0x41e00000, "i,r", F_ALIAS }, /* xor rd,i,rd */
+
+{ "fpop1", 0x81a00000, 0x40580000, "[1+2],d", 0 },
+{ "fpop2", 0x81a80000, 0x40500000, "[1+2],d", 0 },
+
+/* Someday somebody should give these the same treatment as the branches
+ above. FIXME someday. */
+
+{ "fb", 0x31800000, 0xc0400000, ",al", F_DELAYED },
+{ "fb", 0x11800000, 0xc0400000, "l", F_DELAYED },
+{ "fba", 0x31800000, 0xc0400000, ",al", F_DELAYED|F_ALIAS },
+{ "fba", 0x11800000, 0xc0400000, "l", F_DELAYED|F_ALIAS },
+{ "fbn", 0x21800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbn", 0x01800000, 0xc0400000, "l", F_DELAYED },
+{ "fbu", 0x2f800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbu", 0x0f800000, 0xc0400000, "l", F_DELAYED },
+{ "fbg", 0x2d800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbg", 0x0d800000, 0xc0400000, "l", F_DELAYED },
+{ "fbug", 0x2b800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbug", 0x0b800000, 0xc0400000, "l", F_DELAYED },
+{ "fbl", 0x29800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbl", 0x09800000, 0xc0400000, "l", F_DELAYED },
+{ "fbul", 0x27800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbul", 0x07800000, 0xc0400000, "l", F_DELAYED },
+{ "fblg", 0x25800000, 0xc0400000, ",al", F_DELAYED },
+{ "fblg", 0x05800000, 0xc0400000, "l", F_DELAYED },
+{ "fbne", 0x23800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbne", 0x03800000, 0xc0400000, "l", F_DELAYED },
+{ "fbe", 0x33800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbe", 0x13800000, 0xc0400000, "l", F_DELAYED },
+{ "fbue", 0x35800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbue", 0x15800000, 0xc0400000, "l", F_DELAYED },
+{ "fbge", 0x37800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbge", 0x17800000, 0xc0400000, "l", F_DELAYED },
+{ "fbuge", 0x39800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbuge", 0x19800000, 0xc0400000, "l", F_DELAYED },
+{ "fble", 0x3b800000, 0xc0400000, ",al", F_DELAYED },
+{ "fble", 0x1b800000, 0xc0400000, "l", F_DELAYED },
+{ "fbule", 0x3d800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbule", 0x1d800000, 0xc0400000, "l", F_DELAYED },
+{ "fbo", 0x3f800000, 0xc0400000, ",al", F_DELAYED },
+{ "fbo", 0x1f800000, 0xc0400000, "l", F_DELAYED },
+
+{ "cba", 0x31c00000, 0xce000000, ",al", F_DELAYED },
+{ "cba", 0x11c00000, 0xce000000, "l", F_DELAYED },
+{ "cbn", 0x21c00000, 0xde000000, ",al", F_DELAYED },
+{ "cbn", 0x01c00000, 0xde000000, "l", F_DELAYED },
+{ "cb3", 0x2fc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb3", 0x0fc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb2", 0x2dc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb2", 0x0dc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb23", 0x2bc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb23", 0x0bc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb1", 0x29c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb1", 0x09c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb13", 0x27c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb13", 0x07c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb12", 0x25c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb12", 0x05c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb123", 0x23c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb123", 0x03c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb0", 0x33c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb0", 0x13c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb03", 0x35c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb03", 0x15c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb02", 0x37c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb02", 0x17c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb023", 0x39c00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb023", 0x19c00000, 0xc0000000, "l", F_DELAYED },
+{ "cb01", 0x3bc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb01", 0x1bc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb013", 0x3dc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb013", 0x1dc00000, 0xc0000000, "l", F_DELAYED },
+{ "cb012", 0x3fc00000, 0xc0000000, ",al", F_DELAYED },
+{ "cb012", 0x1fc00000, 0xc0000000, "l", F_DELAYED },
+
+{ "fstoi", 0x81a01a20, 0x400025c0, "f,g", 0 },
+{ "fdtoi", 0x81a01a40, 0x400025a0, "f,g", 0 },
+{ "fxtoi", 0x81a01a60, 0x40002580, "f,g", 0 },
+
+{ "fitox", 0x81a01980, 0x40002660, "f,g", 0 },
+{ "fitod", 0x81a01900, 0x400026e0, "f,g", 0 },
+{ "fitos", 0x81a01880, 0x40002660, "f,g", 0 },
+
+{ "fstod", 0x81a01920, 0x400026c0, "f,g", 0 },
+{ "fstox", 0x81a019a0, 0x40002640, "f,g", 0 },
+{ "fdtos", 0x81a018c0, 0x40002720, "f,g", 0 },
+{ "fdtox", 0x81a019c0, 0x40002620, "f,g", 0 },
+{ "fxtos", 0x81a018e0, 0x40002700, "f,g", 0 },
+{ "fxtod", 0x81a01960, 0x40002680, "f,g", 0 },
+
+{ "fdivx", 0x81a009e0, 0x40083600, "e,f,g", 0 },
+{ "fdivd", 0x81a009c0, 0x40003620, "e,f,g", 0 },
+{ "fdivs", 0x81a009a0, 0x40003640, "e,f,g", 0 },
+
+{ "fmuls", 0x81a00920, 0x400036c0, "e,f,g", 0 },
+{ "fmuld", 0x81a00940, 0x400036a0, "e,f,g", 0 },
+{ "fmulx", 0x81a00960, 0x40003680, "e,f,g", 0 },
+
+{ "fsqrts", 0x81a00520, 0x40003ac0, "f,g", 0 },
+{ "fsqrtd", 0x81a00540, 0x40003aa8, "f,g", 0 },
+{ "fsqrtx", 0x81a00560, 0x40003a80, "f,g", 0 },
+
+{ "fabss", 0x81a00120, 0x40003ec0, "f,g", 0 },
+{ "fnegs", 0x81a000a0, 0x40003f40, "f,g", 0 },
+{ "fmovs", 0x81a00020, 0x40003fc0, "f,g", 0 },
+
+{ "fsubx", 0x81a008e0, 0x40003700, "e,f,g", 0 },
+{ "fsubd", 0x81a008c0, 0x40003720, "e,f,g", 0 },
+{ "fsubs", 0x81a008a0, 0x40003740, "e,f,g", 0 },
+
+{ "faddx", 0x81a00860, 0x40003780, "e,f,g", 0 },
+{ "faddd", 0x81a00840, 0x400037a0, "e,f,g", 0 },
+{ "fadds", 0x81a00820, 0x400037c0, "e,f,g", 0 },
+
+{ "fcmpex", 0x81a80ae0, 0x40003500, "e,f", 0 },
+{ "fcmped", 0x81a80ac0, 0x40003520, "e,f", 0 },
+{ "fcmpes", 0x81a80aa0, 0x40003540, "e,f", 0 },
+{ "fcmpx", 0x81a80a60, 0x40003580, "e,f", 0 },
+{ "fcmpd", 0x81a80a40, 0x400035a0, "e,f", 0 },
+{ "fcmps", 0x81a80a20, 0x400035c0, "e,f", 0 },
+
+{ "cpop1", 0x81b00000, 0x40480000, "[1+2],d", 0 },
+{ "cpop2", 0x81b80000, 0x40400000, "[1+2],d", 0 },
+};
+
+#define NUMOPCODES ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]))
+
--- /dev/null
+/* Disassembler for the sparc.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB, the GNU disassembler.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "sparc-opcode.h"
+#include "gdbcore.h"
+#include "string.h"
+#include "target.h"
+
+extern void qsort ();
+
+
+extern char *reg_names[];
+#define freg_names (®_names[4 * 8])
+
+union sparc_insn
+ {
+ unsigned long int code;
+ struct
+ {
+ unsigned int OP:2;
+#define op ldst.OP
+ unsigned int RD:5;
+#define rd ldst.RD
+ unsigned int op3:6;
+ unsigned int RS1:5;
+#define rs1 ldst.RS1
+ unsigned int i:1;
+ unsigned int ASI:8;
+#define asi ldst.ASI
+ unsigned int RS2:5;
+#define rs2 ldst.RS2
+#define shcnt rs2
+ } ldst;
+ struct
+ {
+ unsigned int OP:2, RD:5, op3:6, RS1:5, i:1;
+ unsigned int IMM13:13;
+#define imm13 IMM13.IMM13
+ } IMM13;
+ struct
+ {
+ unsigned int OP:2;
+ unsigned int a:1;
+ unsigned int cond:4;
+ unsigned int op2:3;
+ unsigned int DISP22:22;
+#define disp22 branch.DISP22
+ } branch;
+#define imm22 disp22
+ struct
+ {
+ unsigned int OP:2;
+ unsigned int DISP30:30;
+#define disp30 call.DISP30
+ } call;
+ };
+
+/* Nonzero if INSN is the opcode for a delayed branch. */
+static int
+is_delayed_branch (insn)
+ union sparc_insn insn;
+{
+ unsigned int i;
+
+ for (i = 0; i < NUMOPCODES; ++i)
+ {
+ const struct sparc_opcode *opcode = &sparc_opcodes[i];
+ if ((opcode->match & insn.code) == opcode->match
+ && (opcode->lose & insn.code) == 0)
+ return (opcode->flags & F_DELAYED);
+ }
+ return 0;
+}
+
+static int opcodes_sorted = 0;
+
+/* Print one instruction from MEMADDR on STREAM. */
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ union sparc_insn insn;
+
+ register unsigned int i;
+
+ if (!opcodes_sorted)
+ {
+ static int compare_opcodes ();
+ qsort ((char *) sparc_opcodes, NUMOPCODES,
+ sizeof (sparc_opcodes[0]), compare_opcodes);
+ opcodes_sorted = 1;
+ }
+
+ read_memory (memaddr, &insn, sizeof (insn));
+
+ for (i = 0; i < NUMOPCODES; ++i)
+ {
+ const struct sparc_opcode *opcode = &sparc_opcodes[i];
+ if ((opcode->match & insn.code) == opcode->match
+ && (opcode->lose & insn.code) == 0)
+ {
+ /* Nonzero means that we have found an instruction which has
+ the effect of adding or or'ing the imm13 field to rs1. */
+ int imm_added_to_rs1 = 0;
+
+ /* Nonzero means that we have found a plus sign in the args
+ field of the opcode table. */
+ int found_plus = 0;
+
+ /* Do we have an 'or' instruction where rs1 is the same
+ as rsd, and which has the i bit set? */
+ if (opcode->match == 0x80102000
+ && insn.rs1 == insn.rd)
+ imm_added_to_rs1 = 1;
+
+ if (insn.rs1 != insn.rd
+ && strchr (opcode->args, 'r') != 0)
+ /* Can't do simple format if source and dest are different. */
+ continue;
+
+ fputs_filtered (opcode->name, stream);
+
+ {
+ register const char *s;
+
+ if (opcode->args[0] != ',')
+ fputs_filtered (" ", stream);
+ for (s = opcode->args; *s != '\0'; ++s)
+ {
+ if (*s == ',')
+ {
+ fputs_filtered (",", stream);
+ ++s;
+ if (*s == 'a')
+ {
+ fputs_filtered ("a", stream);
+ ++s;
+ }
+ fputs_filtered (" ", stream);
+ }
+
+ switch (*s)
+ {
+ case '+':
+ found_plus = 1;
+
+ /* note fall-through */
+ default:
+ fprintf_filtered (stream, "%c", *s);
+ break;
+
+ case '#':
+ fputs_filtered ("0", stream);
+ break;
+
+#define reg(n) fprintf_filtered (stream, "%%%s", reg_names[n])
+ case '1':
+ case 'r':
+ reg (insn.rs1);
+ break;
+
+ case '2':
+ reg (insn.rs2);
+ break;
+
+ case 'd':
+ reg (insn.rd);
+ break;
+#undef reg
+
+#define freg(n) fprintf_filtered (stream, "%%%s", freg_names[n])
+ case 'e':
+ freg (insn.rs1);
+ break;
+
+ case 'f':
+ freg (insn.rs2);
+ break;
+
+ case 'g':
+ freg (insn.rd);
+ break;
+#undef freg
+
+#define creg(n) fprintf_filtered (stream, "%%c%u", (unsigned int) (n))
+ case 'b':
+ creg (insn.rs1);
+ break;
+
+ case 'c':
+ creg (insn.rs2);
+ break;
+
+ case 'D':
+ creg (insn.rd);
+ break;
+#undef creg
+
+ case 'h':
+ fprintf_filtered (stream, "%%hi(%#x)",
+ (int) insn.imm22 << 10);
+ break;
+
+ case 'i':
+ {
+ /* We cannot trust the compiler to sign-extend
+ when extracting the bitfield, hence the shifts. */
+ int imm = ((int) insn.imm13 << 19) >> 19;
+
+ /* Check to see whether we have a 1+i, and take
+ note of that fact.
+
+ Note: because of the way we sort the table,
+ we will be matching 1+i rather than i+1,
+ so it is OK to assume that i is after +,
+ not before it. */
+ if (found_plus)
+ imm_added_to_rs1 = 1;
+
+ if (imm <= 9)
+ fprintf_filtered (stream, "%d", imm);
+ else
+ fprintf_filtered (stream, "%#x", imm);
+ }
+ break;
+
+ case 'L':
+ print_address ((CORE_ADDR) memaddr + insn.disp30 * 4,
+ stream);
+ break;
+
+ case 'l':
+ if ((insn.code >> 22) == 0)
+ /* Special case for `unimp'. Don't try to turn
+ it's operand into a function offset. */
+ fprintf_filtered (stream, "%#x",
+ (int) (((int) insn.disp22 << 10) >> 10));
+ else
+ /* We cannot trust the compiler to sign-extend
+ when extracting the bitfield, hence the shifts. */
+ print_address ((CORE_ADDR)
+ (memaddr
+ + (((int) insn.disp22 << 10) >> 10) * 4),
+ stream);
+ break;
+
+ case 'A':
+ fprintf_filtered (stream, "(%d)", (int) insn.asi);
+ break;
+
+ case 'C':
+ fputs_filtered ("%csr", stream);
+ break;
+
+ case 'F':
+ fputs_filtered ("%fsr", stream);
+ break;
+
+ case 'p':
+ fputs_filtered ("%psr", stream);
+ break;
+
+ case 'q':
+ fputs_filtered ("%fq", stream);
+ break;
+
+ case 'Q':
+ fputs_filtered ("%cq", stream);
+ break;
+
+ case 't':
+ fputs_filtered ("%tbr", stream);
+ break;
+
+ case 'w':
+ fputs_filtered ("%wim", stream);
+ break;
+
+ case 'y':
+ fputs_filtered ("%y", stream);
+ break;
+ }
+ }
+ }
+
+ /* If we are adding or or'ing something to rs1, then
+ check to see whether the previous instruction was
+ a sethi to the same register as in the sethi.
+ If so, attempt to print the result of the add or
+ or (in this context add and or do the same thing)
+ and its symbolic value. */
+ if (imm_added_to_rs1)
+ {
+ union sparc_insn prev_insn;
+ int errcode;
+
+ errcode = target_read_memory (memaddr - 4,
+ (char *)&prev_insn, sizeof (prev_insn));
+
+ if (errcode == 0)
+ {
+ /* If it is a delayed branch, we need to look at the
+ instruction before the delayed branch. This handles
+ sequences such as
+
+ sethi %o1, %hi(_foo), %o1
+ call _printf
+ or %o1, %lo(_foo), %o1
+ */
+
+ if (is_delayed_branch (prev_insn))
+ errcode = target_read_memory
+ (memaddr - 8, (char *)&prev_insn, sizeof (prev_insn));
+ }
+
+ /* If there was a problem reading memory, then assume
+ the previous instruction was not sethi. */
+ if (errcode == 0)
+ {
+ /* Is it sethi to the same register? */
+ if ((prev_insn.code & 0xc1c00000) == 0x01000000
+ && prev_insn.rd == insn.rs1)
+ {
+ fprintf_filtered (stream, "\t! ");
+ /* We cannot trust the compiler to sign-extend
+ when extracting the bitfield, hence the shifts. */
+ print_address (((int) prev_insn.imm22 << 10)
+ | (insn.imm13 << 19) >> 19, stream);
+ }
+ }
+ }
+
+ return sizeof (insn);
+ }
+ }
+
+ printf_filtered ("%#8x", insn.code);
+ return sizeof (insn);
+}
+
+
+/* Compare opcodes A and B. */
+
+static int
+compare_opcodes (a, b)
+ char *a, *b;
+{
+ struct sparc_opcode *op0 = (struct sparc_opcode *) a;
+ struct sparc_opcode *op1 = (struct sparc_opcode *) b;
+ unsigned long int match0 = op0->match, match1 = op1->match;
+ unsigned long int lose0 = op0->lose, lose1 = op1->lose;
+ register unsigned int i;
+
+ /* If a bit is set in both match and lose, there is something
+ wrong with the opcode table. */
+ if (match0 & lose0)
+ {
+ fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+ op0->name, match0, lose0);
+ op0->lose &= ~op0->match;
+ lose0 = op0->lose;
+ }
+
+ if (match1 & lose1)
+ {
+ fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
+ op1->name, match1, lose1);
+ op1->lose &= ~op1->match;
+ lose1 = op1->lose;
+ }
+
+ /* Because the bits that are variable in one opcode are constant in
+ another, it is important to order the opcodes in the right order. */
+ for (i = 0; i < 32; ++i)
+ {
+ unsigned long int x = 1 << i;
+ int x0 = (match0 & x) != 0;
+ int x1 = (match1 & x) != 0;
+
+ if (x0 != x1)
+ return x1 - x0;
+ }
+
+ for (i = 0; i < 32; ++i)
+ {
+ unsigned long int x = 1 << i;
+ int x0 = (lose0 & x) != 0;
+ int x1 = (lose1 & x) != 0;
+
+ if (x0 != x1)
+ return x1 - x0;
+ }
+
+ /* They are functionally equal. So as long as the opcode table is
+ valid, we can put whichever one first we want, on aesthetic grounds. */
+
+ /* Our first aesthetic ground is that aliases defer to real insns. */
+ {
+ int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
+ if (alias_diff != 0)
+ /* Put the one that isn't an alias first. */
+ return alias_diff;
+ }
+
+ /* Except for the above aliases, two "identical" instructions had
+ better have the same opcode. This is a sanity check on the table. */
+ if (0 != strcmp (op0->name, op1->name))
+ fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
+ op0->name, op1->name);
+
+ /* Fewer arguments are preferred. */
+ {
+ int length_diff = strlen (op0->args) - strlen (op1->args);
+ if (length_diff != 0)
+ /* Put the one with fewer arguments first. */
+ return length_diff;
+ }
+
+ /* Put 1+i before i+1. */
+ {
+ char *p0 = (char *) strchr(op0->args, '+');
+ char *p1 = (char *) strchr(op1->args, '+');
+
+ if (p0 && p1)
+ {
+ /* There is a plus in both operands. Note that a plus
+ sign cannot be the first character in args,
+ so the following [-1]'s are valid. */
+ if (p0[-1] == 'i' && p1[1] == 'i')
+ /* op0 is i+1 and op1 is 1+i, so op1 goes first. */
+ return 1;
+ if (p0[1] == 'i' && p1[-1] == 'i')
+ /* op0 is 1+i and op1 is i+1, so op0 goes first. */
+ return -1;
+ }
+ }
+
+ /* They are, as far as we can tell, identical.
+ Since qsort may have rearranged the table partially, there is
+ no way to tell which one was first in the opcode table as
+ written, so just say there are equal. */
+ return 0;
+}
--- /dev/null
+/* Machine-dependent code which would otherwise be in inflow.c and core.c,
+ for GDB, the GNU debugger, for SPARC host systems.
+
+ Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "tm-sparc.h"
+#include "param-no-tm.h"
+#include "inferior.h"
+#include "target.h"
+
+#include <sys/param.h>
+#include <sys/file.h> /* For L_SET */
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include "gdbcore.h"
+#include <sys/core.h>
+
+extern char register_valid[];
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ int i;
+
+ /* We should never be called with deferred stores, because a prerequisite
+ for writing regs is to have fetched them all (PREPARE_TO_STORE), sigh. */
+ if (deferred_stores) abort();
+
+ DO_DEFERRED_STORES;
+
+ /* Global and Out regs are fetched directly, as well as the control
+ registers. If we're getting one of the in or local regs,
+ and the stack pointer has not yet been fetched,
+ we have to do that first, since they're found in memory relative
+ to the stack pointer. */
+ if (regno < O7_REGNUM /* including -1 */
+ || regno >= Y_REGNUM
+ || (!register_valid[SP_REGNUM] && regno < I7_REGNUM))
+ {
+ if (0 != ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers))
+ perror("ptrace_getregs");
+
+ registers[REGISTER_BYTE (0)] = 0;
+ bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * REGISTER_RAW_SIZE (G0_REGNUM));
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
+ *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
+
+ for (i = G0_REGNUM; i <= O7_REGNUM; i++)
+ register_valid[i] = 1;
+ register_valid[Y_REGNUM] = 1;
+ register_valid[PS_REGNUM] = 1;
+ register_valid[PC_REGNUM] = 1;
+ register_valid[NPC_REGNUM] = 1;
+ /* If we don't set these valid, read_register_bytes() rereads
+ all the regs every time it is called! FIXME. */
+ register_valid[WIM_REGNUM] = 1; /* Not true yet, FIXME */
+ register_valid[TBR_REGNUM] = 1; /* Not true yet, FIXME */
+ register_valid[FPS_REGNUM] = 1; /* Not true yet, FIXME */
+ register_valid[CPS_REGNUM] = 1; /* Not true yet, FIXME */
+ }
+
+ /* Floating point registers */
+ if (regno == -1 || (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31))
+ {
+ if (0 != ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers))
+ perror("ptrace_getfpregs");
+ bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fpu_fr);
+ /* bcopy (&inferior_fp_registers.Fpu_fsr,
+ ®isters[REGISTER_BYTE (FPS_REGNUM)],
+ sizeof (FPU_FSR_TYPE)); FIXME??? -- gnu@cyg */
+ for (i = FP0_REGNUM; i <= FP0_REGNUM+31; i++)
+ register_valid[i] = 1;
+ register_valid[FPS_REGNUM] = 1;
+ }
+
+ /* These regs are saved on the stack by the kernel. Only read them
+ all (16 ptrace calls!) if we really need them. */
+ if (regno == -1)
+ {
+ target_xfer_memory (*(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)],
+ ®isters[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM), 0);
+ for (i = L0_REGNUM; i <= I7_REGNUM; i++)
+ register_valid[i] = 1;
+ }
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ {
+ CORE_ADDR sp = *(CORE_ADDR*)®isters[REGISTER_BYTE (SP_REGNUM)];
+ i = REGISTER_BYTE (regno);
+ if (register_valid[regno])
+ printf("register %d valid and read\n", regno);
+ target_xfer_memory (sp + i - REGISTER_BYTE (L0_REGNUM),
+ ®isters[i], REGISTER_RAW_SIZE (regno), 0);
+ register_valid[regno] = 1;
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+#define INT_REGS 1
+#define STACK_REGS 2
+#define FP_REGS 4
+int deferred_stores = 0; /* Cumulates stores we want to do eventually. */
+
+int
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ int wanna_store = INT_REGS + STACK_REGS + FP_REGS;
+
+ /* First decide which pieces of machine-state we need to modify.
+ Default for regno == -1 case is all pieces. */
+ if (regno >= 0)
+ if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32)
+ {
+ wanna_store = FP_REGS;
+ }
+ else
+ {
+ if (regno == SP_REGNUM)
+ wanna_store = INT_REGS + STACK_REGS;
+ else if (regno < L0_REGNUM || regno > I7_REGNUM)
+ wanna_store = INT_REGS;
+ else
+ wanna_store = STACK_REGS;
+ }
+
+ /* See if we're forcing the stores to happen now, or deferring. */
+ if (regno == -2)
+ {
+ wanna_store = deferred_stores;
+ deferred_stores = 0;
+ }
+ else
+ {
+ if (wanna_store == STACK_REGS)
+ {
+ /* Fall through and just store one stack reg. If we deferred
+ it, we'd have to store them all, or remember more info. */
+ }
+ else
+ {
+ deferred_stores |= wanna_store;
+ return 0;
+ }
+ }
+
+ if (wanna_store & STACK_REGS)
+ {
+ CORE_ADDR sp = *(CORE_ADDR *)®isters[REGISTER_BYTE (SP_REGNUM)];
+
+ if (regno < 0 || regno == SP_REGNUM)
+ {
+ if (!register_valid[L0_REGNUM+5]) abort();
+ target_xfer_memory (sp,
+ ®isters[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM), 1);
+ }
+ else
+ {
+ if (!register_valid[regno]) abort();
+ target_xfer_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
+ ®isters[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno), 1);
+ }
+
+ }
+
+ if (wanna_store & INT_REGS)
+ {
+ if (!register_valid[G1_REGNUM]) abort();
+
+ bcopy (®isters[REGISTER_BYTE (G1_REGNUM)],
+ &inferior_registers.r_g1, 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ inferior_registers.r_ps =
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc =
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+ inferior_registers.r_npc =
+ *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)];
+ inferior_registers.r_y =
+ *(int *)®isters[REGISTER_BYTE (Y_REGNUM)];
+
+ if (0 != ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers))
+ perror("ptrace_setregs");
+ }
+
+ if (wanna_store & FP_REGS)
+ {
+ if (!register_valid[FP0_REGNUM+9]) abort();
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)],
+ &inferior_fp_registers,
+ sizeof inferior_fp_registers.fpu_fr);
+
+/* bcopy (®isters[REGISTER_BYTE (FPS_REGNUM)],
+ &inferior_fp_registers.Fpu_fsr,
+ sizeof (FPU_FSR_TYPE));
+****/
+ if (0 !=
+ ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers))
+ perror("ptrace_setfpregs");
+ }
+ return 0;
+}
+\f
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+{
+
+ if (which == 0) {
+
+ /* Integer registers */
+
+#define gregs ((struct regs *)core_reg_sect)
+ /* G0 *always* holds 0. */
+ *(int *)®isters[REGISTER_BYTE (0)] = 0;
+
+ /* The globals and output registers. */
+ bcopy (&gregs->r_g1,
+ ®isters[REGISTER_BYTE (G1_REGNUM)],
+ 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
+ *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
+ *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
+
+ /* My best guess at where to get the locals and input
+ registers is exactly where they usually are, right above
+ the stack pointer. If the core dump was caused by a bus error
+ from blowing away the stack pointer (as is possible) then this
+ won't work, but it's worth the try. */
+ {
+ int sp;
+
+ sp = *(int *)®isters[REGISTER_BYTE (SP_REGNUM)];
+ if (0 != target_read_memory (sp, ®isters[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM)))
+ {
+ /* fprintf so user can still use gdb */
+ fprintf (stderr,
+ "Couldn't read input and local registers from core file\n");
+ }
+ }
+ } else if (which == 2) {
+
+ /* Floating point registers */
+
+#define fpuregs ((struct fpu *) core_reg_sect)
+ if (core_reg_size >= sizeof (struct fpu))
+ {
+ bcopy (fpuregs->fpu_regs,
+ ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof (fpuregs->fpu_regs));
+ bcopy (&fpuregs->fpu_fsr,
+ ®isters[REGISTER_BYTE (FPS_REGNUM)],
+ sizeof (FPU_FSR_TYPE));
+ }
+ else
+ fprintf (stderr, "Couldn't read float regs from core file\n");
+ }
+}
--- /dev/null
+/* Table of DBX symbol codes for the GNU system.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+\f
+/* Global variable. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_GSYM, 0x20, "GSYM")
+
+/* Function name for BSD Fortran. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_FNAME, 0x22, "FNAME")
+
+/* Function name or text-segment variable for C. Value is its address.
+ Desc is supposedly starting line number, but GCC doesn't set it
+ and DBX seems not to miss it. */
+__define_stab (N_FUN, 0x24, "FUN")
+
+/* Data-segment variable with internal linkage. Value is its address. */
+__define_stab (N_STSYM, 0x26, "STSYM")
+
+/* BSS-segment variable with internal linkage. Value is its address. */
+__define_stab (N_LCSYM, 0x28, "LCSYM")
+
+/* Name of main routine. Only the name is significant.
+ This is not used in C. */
+__define_stab (N_MAIN, 0x2a, "MAIN")
+
+/* Register variable. Value is number of register. */
+__define_stab (N_RSYM, 0x40, "RSYM")
+
+/* Structure or union element. Value is offset in the structure. */
+__define_stab (N_SSYM, 0x60, "SSYM")
+
+/* Parameter variable. Value is offset from argument pointer.
+ (On most machines the argument pointer is the same as the frame pointer. */
+__define_stab (N_PSYM, 0xa0, "PSYM")
+
+/* Automatic variable in the stack. Value is offset from frame pointer.
+ Also used for type descriptions. */
+__define_stab (N_LSYM, 0x80, "LSYM")
+
+/* Alternate entry point. Value is its address. */
+__define_stab (N_ENTRY, 0xa4, "ENTRY")
+
+/* Name of main source file.
+ Value is starting text address of the compilation. */
+__define_stab (N_SO, 0x64, "SO")
+
+/* Name of sub-source file.
+ Value is starting text address of the compilation. */
+__define_stab (N_SOL, 0x84, "SOL")
+
+/* Line number in text segment. Desc is the line number;
+ value is corresponding address. */
+__define_stab (N_SLINE, 0x44, "SLINE")
+/* Similar, for data segment. */
+__define_stab (N_DSLINE, 0x66, "DSLINE")
+/* Similar, for bss segment. */
+__define_stab (N_BSLINE, 0x68, "BSLINE")
+
+/* Beginning of an include file. Only Sun uses this.
+ In an object file, only the name is significant.
+ The Sun linker puts data into some of the other fields. */
+__define_stab (N_BINCL, 0x82, "BINCL")
+/* End of an include file. No name.
+ These two act as brackets around the file's output.
+ In an object file, there is no significant data in this entry.
+ The Sun linker puts data into some of the fields. */
+__define_stab (N_EINCL, 0xa2, "EINCL")
+/* Place holder for deleted include file.
+ This appears only in output from the Sun linker. */
+__define_stab (N_EXCL, 0xc2, "EXCL")
+
+/* Beginning of lexical block.
+ The desc is the nesting level in lexical blocks.
+ The value is the address of the start of the text for the block.
+ The variables declared inside the block *precede* the N_LBRAC symbol. */
+__define_stab (N_LBRAC, 0xc0, "LBRAC")
+/* End of a lexical block. Desc matches the N_LBRAC's desc.
+ The value is the address of the end of the text for the block. */
+__define_stab (N_RBRAC, 0xe0, "RBRAC")
+
+/* Begin named common block. Only the name is significant. */
+__define_stab (N_BCOMM, 0xe2, "BCOMM")
+/* Begin named common block. Only the name is significant
+ (and it should match the N_BCOMM). */
+__define_stab (N_ECOMM, 0xe4, "ECOMM")
+/* End common (local name): value is address.
+ I'm not sure how this is used. */
+__define_stab (N_ECOML, 0xe8, "ECOML")
+/* Second symbol entry containing a length-value for the preceding entry.
+ The value is the length. */
+__define_stab (N_LENG, 0xfe, "LENG")
+
+/* Global symbol in Pascal.
+ Supposedly the value is its line number; I'm skeptical. */
+__define_stab (N_PC, 0x30, "PC")
+
+/* Modula-2 compilation unit. Can someone say what info it contains? */
+__define_stab (N_M2C, 0x42, "M2C")
+/* Modula-2 scope information. Can someone say what info it contains? */
+__define_stab (N_SCOPE, 0xc4, "SCOPE")
+
+/* Sun's source-code browser stabs. ?? Don't know what the fields are.
+ Supposedly the field is "path to associated .cb file". */
+__define_stab (N_BROWS, 0x48, "BROWS")
+
+/* GNU C++ exception stabs. */
+
+/* GNU C++ exception variable. Name is variable name. */
+__define_stab (N_EHDECL, 0x50, "EHDECL")
+
+/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
+ this entry is immediately followed by a CAUGHT stab saying what exception
+ was caught. Multiple CAUGHT stabs means that multiple exceptions
+ can be caught here. If Desc is 0, it means all exceptions are caught
+ here. */
+__define_stab (N_CATCH, 0x54, "CATCH")
+
+/* These STAB's are used on Gould systems for Non-Base register symbols
+ or something like that. FIXME. I have assigned the values at random
+ since I don't have a Gould here. Fixups from Gould folk welcome... */
+__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
+__define_stab (N_NBDATA, 0xF2, "NBDATA")
+__define_stab (N_NBBSS, 0xF4, "NBBSS")
+__define_stab (N_NBSTS, 0xF6, "NBSTS")
+__define_stab (N_NBLCS, 0xF8, "NBLCS")
+__define_stab (N_NSYMS, 0xFA, "NSYMS")
+\f
+/* The above information, in matrix format.
+
+ STAB MATRIX
+ _________________________________________________
+ | 00 - 1F are not dbx stab symbols |
+ | Entries with bits 01 set are external symbols |
+ | N_UNDEF | N_ABS | N_TEXT | N_DATA |
+ | N_BSS | N_COMM | | N_FN |
+ |_______________________________________________|
+ | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
+ | 28 LCSYM | 2A MAIN | 2C | 2E |
+ | 30 PC | 32 | 34 | 36 |
+ | 38 | 3A | 3C | 3E |
+ | 40 RSYM | 42 M2C | 44 SLINE | 46 |
+ | 48 BROWS | 4A | 4C | 4E |
+ | 50 EHDECL | 52 | 54 CATCH | 56 |
+ | 58 | 5A | 5C | 5E |
+ | 60 SSYM | 62 | 64 SO | 66 DSLINE |
+ | 68 BSLINE | 6A | 6C | 6E |
+ | 70 | 72 | 74 | 76 |
+ | 78 | 7A | 7C | 7E |
+ | 80 LSYM | 82 BINCL | 84 SOL | 86 |
+ | 88 | 8A | 8C | 8E |
+ | 90 | 92 | 94 | 96 |
+ | 98 | 9A | 9C | 9E |
+ | A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
+ | A8 | AA | AC | AE |
+ | B0 | B2 | B4 | B6 |
+ | B8 | BA | BC | BE |
+ | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
+ | C8 | CA | CC | CE |
+ | D0 | D2 | D4 | D6 |
+ | D8 | DA | DC | DE |
+ | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
+ | E8 ECOML | EA | EC | EE |
+ | F0 | F2 | F4 | F6 |
+ | F8 | FA | FC | FE LENG |
+ +-----------------------------------------------+
+
+*/
--- /dev/null
+/* Interface to bare machine for GDB running as kernel debugger.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined (SIGTSTP) && defined (SIGIO)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* SIGTSTP and SIGIO defined (must be 4.2) */
+
+#include "defs.h"
+#include "param.h"
+#include "signals.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+\f
+/* Random system calls, mostly no-ops to prevent link problems */
+
+ioctl (desc, code, arg)
+{}
+
+int (* signal ()) ()
+{}
+
+kill ()
+{}
+
+getpid ()
+{
+ return 0;
+}
+
+sigsetmask ()
+{}
+
+chdir ()
+{}
+
+char *
+getwd (buf)
+ char *buf;
+{
+ buf[0] = '/';
+ buf[1] = 0;
+ return buf;
+}
+
+/* Used to check for existence of .gdbinit. Say no. */
+
+access ()
+{
+ return -1;
+}
+
+exit ()
+{
+ error ("Fatal error; restarting.");
+}
+\f
+/* Reading "files". The contents of some files are written into kdb's
+ data area before it is run. These files are used to contain the
+ symbol table for kdb to load, and the source files (in case the
+ kdb user wants to print them). The symbols are stored in a file
+ named "kdb-symbols" in a.out format (except that all the text and
+ data have been stripped to save room).
+
+ The files are stored in the following format:
+ int number of bytes of data for this file, including these four.
+ char[] name of the file, ending with a null.
+ padding to multiple of 4 boundary.
+ char[] file contents. The length can be deduced from what was
+ specified before. There is no terminating null here.
+
+ If the int at the front is zero, it means there are no more files.
+
+ Opening a file in kdb returns a nonzero value to indicate success,
+ but the value does not matter. Only one file can be open, and only
+ for reading. All the primitives for input from the file know
+ which file is open and ignore what is specified for the descriptor
+ or for the stdio stream.
+
+ Input with fgetc can be done either on the file that is open
+ or on stdin (which reads from the terminal through tty_input () */
+
+/* Address of data for the files stored in format described above. */
+char *files_start;
+
+/* The file stream currently open: */
+
+char *sourcebeg; /* beginning of contents */
+int sourcesize; /* size of contents */
+char *sourceptr; /* current read pointer */
+int sourceleft; /* number of bytes to eof */
+
+/* "descriptor" for the file now open.
+ Incremented at each close.
+ If specified descriptor does not match this,
+ it means the program is trying to use a closed descriptor.
+ We report an error for that. */
+
+int sourcedesc;
+
+open (filename, modes)
+ char *filename;
+ int modes;
+{
+ register char *next;
+
+ if (modes)
+ {
+ errno = EROFS;
+ return -1;
+ }
+
+ if (sourceptr)
+ {
+ errno = EMFILE;
+ return -1;
+ }
+
+ for (next - files_start; * (int *) next;
+ next += * (int *) next)
+ {
+ if (!strcmp (next + 4, filename))
+ {
+ sourcebeg = next + 4 + strlen (next + 4) + 1;
+ sourcebeg = (char *) (((int) sourcebeg + 3) & (-4));
+ sourceptr = sourcebeg;
+ sourcesize = next + * (int *) next - sourceptr;
+ sourceleft = sourcesize;
+ return sourcedesc;
+ }
+ }
+ return 0;
+}
+
+close (desc)
+ int desc;
+{
+ sourceptr = 0;
+ sourcedesc++;
+ /* Don't let sourcedesc get big enough to be confused with stdin. */
+ if (sourcedesc == 100)
+ sourcedesc = 5;
+}
+
+FILE *
+fopen (filename, modes)
+ char *filename;
+ char *modes;
+{
+ return (FILE *) open (filename, *modes == 'w');
+}
+
+FILE *
+fdopen (desc)
+ int desc;
+{
+ return (FILE *) desc;
+}
+
+fclose (desc)
+ int desc;
+{
+ close (desc);
+}
+
+fstat (desc, statbuf)
+ struct stat *statbuf;
+{
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ statbuf->st_size = sourcesize;
+}
+
+myread (desc, destptr, size, filename)
+ int desc;
+ char *destptr;
+ int size;
+ char *filename;
+{
+ int len = min (sourceleft, size);
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ bcopy (sourceptr, destptr, len);
+ sourceleft -= len;
+ return len;
+}
+
+int
+fread (bufp, numelts, eltsize, stream)
+{
+ register int elts = min (numelts, sourceleft / eltsize);
+ register int len = elts * eltsize;
+
+ if (stream != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ bcopy (sourceptr, bufp, len);
+ sourceleft -= len;
+ return elts;
+}
+
+int
+fgetc (desc)
+ int desc;
+{
+
+ if (desc == (int) stdin)
+ return tty_input ();
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (sourceleft-- <= 0)
+ return EOF;
+ return *sourceptr++;
+}
+
+lseek (desc, pos)
+ int desc;
+ int pos;
+{
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (pos < 0 || pos > sourcesize)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sourceptr = sourcebeg + pos;
+ sourceleft = sourcesize - pos;
+}
+\f
+/* Output in kdb can go only to the terminal, so the stream
+ specified may be ignored. */
+
+printf (a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+ char buffer[1024];
+ sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ display_string (buffer);
+}
+
+fprintf (ign, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+ char buffer[1024];
+ sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ display_string (buffer);
+}
+
+fwrite (buf, numelts, size, stream)
+ register char *buf;
+ int numelts, size;
+{
+ register int i = numelts * size;
+ while (i-- > 0)
+ fputc (*buf++, stream);
+}
+
+fputc (c, ign)
+{
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ display_string (buf);
+}
+
+/* sprintf refers to this, but loading this from the
+ library would cause fflush to be loaded from it too.
+ In fact there should be no need to call this (I hope). */
+
+_flsbuf ()
+{
+ error ("_flsbuf was actually called.");
+}
+
+fflush (ign)
+{
+}
+\f
+/* Entries into core and inflow, needed only to make things link ok. */
+
+exec_file_command ()
+{}
+
+core_file_command ()
+{}
+
+char *
+get_exec_file (err)
+ int err;
+{
+ /* Makes one printout look reasonable; value does not matter otherwise. */
+ return "run";
+}
+
+have_core_file_p ()
+{
+ return 0;
+}
+
+kill_command ()
+{
+ inferior_pid = 0;
+}
+
+terminal_inferior ()
+{}
+
+terminal_ours ()
+{}
+
+terminal_init_inferior ()
+{}
+
+write_inferior_register ()
+{}
+
+read_inferior_register ()
+{}
+
+read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ bcopy (memaddr, myaddr, len);
+}
+
+/* Always return 0 indicating success. */
+
+write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ bcopy (myaddr, memaddr, len);
+ return 0;
+}
+
+static REGISTER_TYPE saved_regs[NUM_REGS];
+
+REGISTER_TYPE
+read_register (regno)
+ int regno;
+{
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Register number %d out of range.", regno);
+ return saved_regs[regno];
+}
+
+void
+write_register (regno, value)
+ int regno;
+ REGISTER_TYPE value;
+{
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Register number %d out of range.", regno);
+ saved_regs[regno] = value;
+}
+\f
+/* System calls needed in relation to running the "inferior". */
+
+vfork ()
+{
+ /* Just appear to "succeed". Say the inferior's pid is 1. */
+ return 1;
+}
+
+/* These are called by code that normally runs in the inferior
+ that has just been forked. That code never runs, when standalone,
+ and these definitions are so it will link without errors. */
+
+ptrace ()
+{}
+
+setpgrp ()
+{}
+
+execle ()
+{}
+
+_exit ()
+{}
+\f
+/* Malloc calls these. */
+
+malloc_warning (str)
+ char *str;
+{
+ printf ("\n%s.\n\n", str);
+}
+
+char *next_free;
+char *memory_limit;
+
+char *
+sbrk (amount)
+ int amount;
+{
+ if (next_free + amount > memory_limit)
+ return (char *) -1;
+ next_free += amount;
+ return next_free - amount;
+}
+
+/* Various ways malloc might ask where end of memory is. */
+
+char *
+ulimit ()
+{
+ return memory_limit;
+}
+
+int
+vlimit ()
+{
+ return memory_limit - next_free;
+}
+
+getrlimit (addr)
+ struct rlimit *addr;
+{
+ addr->rlim_cur = memory_limit - next_free;
+}
+\f
+/* Context switching to and from program being debugged. */
+
+/* GDB calls here to run the user program.
+ The frame pointer for this function is saved in
+ gdb_stack by save_frame_pointer; then we restore
+ all of the user program's registers, including PC and PS. */
+
+static int fault_code;
+static REGISTER_TYPE gdb_stack;
+
+resume ()
+{
+ REGISTER_TYPE restore[NUM_REGS];
+
+ PUSH_FRAME_PTR;
+ save_frame_pointer ();
+
+ bcopy (saved_regs, restore, sizeof restore);
+ POP_REGISTERS;
+ /* Control does not drop through here! */
+}
+
+save_frame_pointer (val)
+ CORE_ADDR val;
+{
+ gdb_stack = val;
+}
+
+/* Fault handlers call here, running in the user program stack.
+ They must first push a fault code,
+ old PC, old PS, and any other info about the fault.
+ The exact format is machine-dependent and is known only
+ in the definition of PUSH_REGISTERS. */
+
+fault ()
+{
+ /* Transfer all registers and fault code to the stack
+ in canonical order: registers in order of GDB register number,
+ followed by fault code. */
+ PUSH_REGISTERS;
+
+ /* Transfer them to saved_regs and fault_code. */
+ save_registers ();
+
+ restore_gdb ();
+ /* Control does not reach here */
+}
+
+restore_gdb ()
+{
+ CORE_ADDR new_fp = gdb_stack;
+ /* Switch to GDB's stack */
+ POP_FRAME_PTR;
+ /* Return from the function `resume'. */
+}
+
+/* Assuming register contents and fault code have been pushed on the stack as
+ arguments to this function, copy them into the standard place
+ for the program's registers while GDB is running. */
+
+save_registers (firstreg)
+ int firstreg;
+{
+ bcopy (&firstreg, saved_regs, sizeof saved_regs);
+ fault_code = (&firstreg)[NUM_REGS];
+}
+
+/* Store into the structure such as `wait' would return
+ the information on why the program faulted,
+ converted into a machine-independent signal number. */
+
+static int fault_table[] = FAULT_TABLE;
+
+int
+wait (w)
+ WAITTYPE *w;
+{
+ WSETSTOP (*w, fault_table[fault_code / FAULT_CODE_UNITS]);
+ return inferior_pid;
+}
+\f
+/* Allocate a big space in which files for kdb to read will be stored.
+ Whatever is left is where malloc can allocate storage.
+
+ Initialize it, so that there will be space in the executable file
+ for it. Then the files can be put into kdb by writing them into
+ kdb's executable file. */
+
+/* The default size is as much space as we expect to be available
+ for kdb to use! */
+
+#ifndef HEAP_SIZE
+#define HEAP_SIZE 400000
+#endif
+
+char heap[HEAP_SIZE] = {0};
+
+#ifndef STACK_SIZE
+#define STACK_SIZE 100000
+#endif
+
+int kdb_stack_beg[STACK_SIZE / sizeof (int)];
+int kdb_stack_end;
+
+_initialize_standalone ()
+{
+ register char *next;
+
+ /* Find start of data on files. */
+
+ files_start = heap;
+
+ /* Find the end of the data on files. */
+
+ for (next - files_start; * (int *) next;
+ next += * (int *) next)
+ {}
+
+ /* That is where free storage starts for sbrk to give out. */
+ next_free = next;
+
+ memory_limit = heap + sizeof heap;
+}
+
--- /dev/null
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+/* Signed type of difference of two pointers. */
+
+typedef long ptrdiff_t;
+
+/* Unsigned type of `sizeof' something. */
+
+#ifndef _SIZE_T /* in case <sys/types.h> has defined it. */
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif /* _SIZE_T */
+
+/* A null pointer constant. */
+
+#undef NULL /* in case <stdio.h> has defined it. */
+#define NULL 0
+
+/* Offset of member MEMBER in a struct of type TYPE. */
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* _STDDEF_H */
--- /dev/null
+/* Fake stdlib.h supplying the stuff needed by malloc. */
+
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern void EXFUN(abort, (void));
+extern void EXFUN(free, (PTR));
+extern PTR EXFUN(malloc, (size_t));
+extern PTR EXFUN(realloc, (PTR, size_t));
--- /dev/null
+/* Program to stuff files into a specially prepared space in kdb.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written 13-Mar-86 by David Bridgham. */
+
+#include <stdio.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <varargs.h>
+
+extern char *sys_errlist[];
+
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ register char *cp;
+ char *outfile;
+ register int i;
+ int offset;
+ int out_fd, in_fd;
+ struct stat stat_buf;
+ int size, pad;
+ char buf[1024];
+ static char zeros[4] = {0};
+
+ if (argc < 4)
+ err("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n",
+ argv[0]);
+
+ outfile = 0;
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp (argv[i], "-o") == 0)
+ outfile = argv[++i];
+ }
+ if (outfile == 0)
+ err("Output file not specified\n");
+
+ offset = get_offset (outfile, "_heap");
+
+ out_fd = open (outfile, O_WRONLY);
+ if (out_fd < 0)
+ err ("Error opening %s for write: %s\n", outfile, sys_errlist[errno]);
+ if (lseek (out_fd, offset, 0) < 0)
+ err ("Error seeking to heap in %s: %s\n", outfile, sys_errlist[errno]);
+
+ /* For each file listed on the command line, write it into the
+ * 'heap' of the output file. Make sure to skip the arguments
+ * that name the output file. */
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp (argv[i], "-o") == 0)
+ continue;
+ if ((in_fd = open (argv[i], O_RDONLY)) < 0)
+ err ("Error opening %s for read: %s\n", argv[i], sys_errlist[errno]);
+ if (fstat (in_fd, &stat_buf) < 0)
+ err ("Error stat'ing %s: %s\n", argv[i], sys_errlist[errno]);
+ size = strlen (argv[i]);
+ pad = 4 - (size & 3);
+ size += pad + stat_buf.st_size + sizeof (int);
+ write (out_fd, &size, sizeof (int));
+ write (out_fd, argv[i], strlen (argv[i]));
+ write (out_fd, zeros, pad);
+ while ((size = read (in_fd, buf, sizeof (buf))) > 0)
+ write (out_fd, buf, size);
+ close (in_fd);
+ }
+ size = 0;
+ write (out_fd, &size, sizeof (int));
+ close (out_fd);
+ return (0);
+}
+
+/* Read symbol table from file and returns the offset into the file
+ * where symbol sym_name is located. If error, print message and
+ * exit. */
+get_offset (file, sym_name)
+ char *file;
+ char *sym_name;
+{
+ int f;
+ struct exec file_hdr;
+ struct nlist *symbol_table;
+ int size;
+ char *strings;
+
+ f = open (file, O_RDONLY);
+ if (f < 0)
+ err ("Error opening %s: %s\n", file, sys_errlist[errno]);
+ if (read (f, &file_hdr, sizeof (file_hdr)) < 0)
+ err ("Error reading exec structure: %s\n", sys_errlist[errno]);
+ if (N_BADMAG (file_hdr))
+ err ("File %s not an a.out file\n", file);
+
+ /* read in symbol table */
+ if ((symbol_table = (struct nlist *)malloc (file_hdr.a_syms)) == 0)
+ err ("Couldn't allocate space for symbol table\n");
+ if (lseek (f, N_SYMOFF (file_hdr), 0) == -1)
+ err ("lseek error: %s\n", sys_errlist[errno]);
+ if (read (f, symbol_table, file_hdr.a_syms) == -1)
+ err ("Error reading symbol table from %s: %s\n", file, sys_errlist[errno]);
+
+ /* read in string table */
+ if (read (f, &size, 4) == -1)
+ err ("reading string table size: %s\n", sys_errlist[errno]);
+ if ((strings = (char *)malloc (size)) == 0)
+ err ("Couldn't allocate memory for string table\n");
+ if (read (f, strings, size - 4) == -1)
+ err ("reading string table: %s\n", sys_errlist[errno]);
+
+ /* Find the core address at which the first byte of kdb text segment
+ should be loaded into core when kdb is run. */
+ origin = find_symbol ("_etext", symbol_table, file_hdr.a_syms, strings)
+ - file_hdr.a_text;
+ /* Find the core address at which the heap will appear. */
+ coreaddr = find_symbol (sym_name, symbol_table, file_hdr.a_syms, strings);
+ /* Return address in file of the heap data space. */
+ return (N_TXTOFF (file_hdr) + core_addr - origin);
+}
+
+find_symbol (sym_name, symbol_table, length, strings)
+ char *sym_name;
+ struct nlist *symbol_table;
+ int length;
+ char *strings;
+{
+ register struct nlist *sym;
+
+ /* Find symbol in question */
+ for (sym = symbol_table;
+ sym != (struct nlist *)((char *)symbol_table + length);
+ sym++)
+ {
+ if ((sym->n_type & N_TYPE) != N_DATA) continue;
+ if (sym->n_un.n_strx == 0) continue;
+ if (strcmp (sym_name, strings + sym->n_un.n_strx - 4) == 0)
+ return sym->n_value;
+ }
+ err ("Data symbol %s not found in %s\n", sym_name, file);
+}
+
+/* VARARGS */
+void
+err (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+ vfprintf (stderr, string, args);
+ va_end (args);
+ exit (-1);
+}
--- /dev/null
+/* Sun-3 Machine-dependent code which would otherwise be in inflow.c and core.c,
+ for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "inferior.h"
+
+#include <sys/ptrace.h>
+#define KERNEL /* To get floating point reg definitions */
+#include <machine/reg.h>
+
+#include "gdbcore.h"
+
+extern int errno;
+
+void
+fetch_inferior_registers ()
+{
+ struct regs inferior_registers;
+#ifdef FP0_REGNUM
+ struct fp_status inferior_fp_registers;
+#endif
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+#ifdef FP0_REGNUM
+ ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+#endif
+
+ bcopy (&inferior_registers, registers, 16 * 4);
+#ifdef FP0_REGNUM
+ bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+#ifdef FP0_REGNUM
+ bcopy (&inferior_fp_registers.fps_control,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+#ifdef FP0_REGNUM
+ struct fp_status inferior_fp_registers;
+#endif
+ extern char registers[];
+
+ bcopy (registers, &inferior_registers, 16 * 4);
+#ifdef FP0_REGNUM
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)];
+
+#ifdef FP0_REGNUM
+ bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif
+
+ ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+#if FP0_REGNUM
+ ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+#endif
+}
+
+/* Machine-dependent code for pulling registers out of a Sun-3 core file. */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+{
+ extern char registers[];
+ struct regs *regs = (struct regs *) core_reg_sect;
+
+ if (which == 0) {
+ if (core_reg_size < sizeof (struct regs))
+ error ("Can't find registers in core file");
+
+ bcopy ((char *)regs, registers, 16 * 4);
+ supply_register (PS_REGNUM, ®s->r_ps);
+ supply_register (PC_REGNUM, ®s->r_pc);
+
+ } else if (which == 2) {
+
+#define fpustruct ((struct fpu *) core_reg_sect)
+
+ if (core_reg_size >= sizeof (struct fpu))
+ {
+ bcopy (fpustruct->f_fpstatus.fps_regs,
+ ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof fpustruct->f_fpstatus.fps_regs);
+ bcopy (&fpustruct->f_fpstatus.fps_control,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof fpustruct->f_fpstatus -
+ sizeof fpustruct->f_fpstatus.fps_regs);
+ }
+ else
+ fprintf (stderr, "Couldn't read float regs from core file\n");
+ }
+}
--- /dev/null
+/* Machine-dependent code for host Sun 386i's for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+ Changes for sun386i by Jean Daniel Fekete (jdf@litp.univ-p6-7.fr),
+ C2V Paris, April 89.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "signame.h"
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/core.h>
+\f
+void
+fetch_inferior_registers ()
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+ ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+
+ bcopy (&inferior_registers, registers, sizeof inferior_registers);
+
+ bcopy (inferior_fp_registers.f_st,®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.f_st);
+ bcopy (&inferior_fp_registers.f_ctrl,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ bcopy (registers, &inferior_registers, 20 * 4);
+
+ bcopy (®isters[REGISTER_BYTE (FP0_REGNUM)],inferior_fp_registers.f_st,
+ sizeof inferior_fp_registers.f_st);
+ bcopy (®isters[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.f_ctrl,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+
+#ifdef PTRACE_FP_BUG
+ if (regno == FP_REGNUM || regno == -1)
+ /* Storing the frame pointer requires a gross hack, in which an
+ instruction that moves eax into ebp gets single-stepped. */
+ {
+ int stack = inferior_registers.r_reg[SP_REGNUM];
+ int stuff = ptrace (PTRACE_PEEKDATA, inferior_pid, stack);
+ int reg = inferior_registers.r_reg[EAX];
+ inferior_registers.r_reg[EAX] =
+ inferior_registers.r_reg[FP_REGNUM];
+ ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+ ptrace (PTRACE_POKEDATA, inferior_pid, stack, 0xc589);
+ ptrace (PTRACE_SINGLESTEP, inferior_pid, stack, 0);
+ wait (0);
+ ptrace (PTRACE_POKEDATA, inferior_pid, stack, stuff);
+ inferior_registers.r_reg[EAX] = reg;
+ }
+#endif
+ ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+ ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+}
+
+/* Machine-dependent code which would otherwise be in core.c */
+/* Work with core files, for GDB. */
+
+\f
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+
+ {
+ struct core corestr;
+
+ val = myread (corechan, &corestr, sizeof corestr);
+ if (val < 0)
+ perror_with_name (filename);
+ if (corestr.c_magic != CORE_MAGIC)
+ error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)",
+ filename, corestr.c_magic, (int) CORE_MAGIC);
+ else if (sizeof (struct core) != corestr.c_len)
+ error ("\"%s\" has an invalid struct core length (%d, expected %d)",
+ filename, corestr.c_len, (int) sizeof (struct core));
+
+ data_start = exec_data_start;
+ data_end = data_start + corestr.c_dsize;
+ stack_start = stack_end - corestr.c_ssize;
+ data_offset = sizeof corestr;
+ stack_offset = sizeof corestr + corestr.c_dsize;
+
+ bcopy (&corestr.c_regs, registers, sizeof corestr.c_regs);
+
+ bcopy (corestr.c_fpu.f_fpstatus.f_st,
+ ®isters[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof corestr.c_fpu.f_fpstatus.f_st);
+ bcopy (&corestr.c_fpu.f_fpstatus.f_ctrl,
+ ®isters[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof corestr.c_fpu.f_fpstatus -
+ sizeof corestr.c_fpu.f_fpstatus.f_st);
+
+ /* the struct aouthdr of sun coff is not the struct exec stored
+ in the core file. */
+ bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
+#ifndef COFF_ENCAPSULATE
+ core_aouthdr.magic = corestr.c_aouthdr.a_info;
+ core_aouthdr.vstamp = /*SUNVERSION*/ 31252;
+#endif
+ printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
+ if (corestr.c_signo > 0)
+ printf ("Program terminated with signal %d, %s.\n",
+ corestr.c_signo,
+ corestr.c_signo < NSIG
+ ? sys_siglist[corestr.c_signo]
+ : "(undocumented)");
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
+
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ long *lp;
+ /* push extended mode on 387 stack, then pop in double mode
+ *
+ * first, set exception masks so no error is generated -
+ * number will be rounded to inf or 0, if necessary
+ */
+ asm ("pushl %eax"); /* grab a stack slot */
+ asm ("fstcw (%esp)"); /* get 387 control word */
+ asm ("movl (%esp),%eax"); /* save old value */
+ asm ("orl $0x3f,%eax"); /* mask all exceptions */
+ asm ("pushl %eax");
+ asm ("fldcw (%esp)"); /* load new value into 387 */
+
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldt (%eax)"); /* push extended number on 387 stack */
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpl (%eax)"); /* pop double */
+ asm ("fwait");
+
+ asm ("popl %eax"); /* flush modified control word */
+ asm ("fnclex"); /* clear exceptions */
+ asm ("fldcw (%esp)"); /* restore original control word */
+ asm ("popl %eax"); /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ /* push double mode on 387 stack, then pop in extended mode
+ * no errors are possible because every 64-bit pattern
+ * can be converted to an extended
+ */
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldl (%eax)");
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpt (%eax)");
+ asm ("fwait");
+}
--- /dev/null
+/* Sequent Symmetry target interface, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "gdbcore.h"
+#include <fcntl.h>
+
+static long i386_get_frame_setup ();
+static i386_follow_jump ();
+
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end -= exec_data_start;
+ text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+#ifdef COFF_FORMAT
+ {
+ int aout_hdrsize;
+ int num_sections;
+
+ if (read_file_hdr (execchan, &file_hdr) < 0)
+ error ("\"%s\": not in executable format.", execfile);
+
+ aout_hdrsize = file_hdr.f_opthdr;
+ num_sections = file_hdr.f_nscns;
+
+ if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
+ error ("\"%s\": can't read optional aouthdr", execfile);
+
+ if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
+ aout_hdrsize) < 0)
+ error ("\"%s\": can't read text section header", execfile);
+
+ if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
+ aout_hdrsize) < 0)
+ error ("\"%s\": can't read data section header", execfile);
+
+ text_start = exec_aouthdr.text_start;
+ text_end = text_start + exec_aouthdr.tsize;
+ text_offset = text_hdr.s_scnptr;
+ exec_data_start = exec_aouthdr.data_start;
+ exec_data_end = exec_data_start + exec_aouthdr.dsize;
+ exec_data_offset = data_hdr.s_scnptr;
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+ exec_mtime = file_hdr.f_timdat;
+ }
+#else /* not COFF_FORMAT */
+ {
+ struct stat st_exec;
+
+ val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
+
+ if (val < 0)
+ perror_with_name (filename);
+
+ text_start = N_ADDRADJ(exec_aouthdr);
+ exec_data_start = round(exec_aouthdr.a_text, NBPG*CLSIZE);
+ text_offset = N_TXTOFF (exec_aouthdr);
+ exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+ text_end = exec_aouthdr.a_text;
+ exec_data_end = exec_data_start + exec_aouthdr.a_data;
+ data_start = exec_data_start;
+ data_end = data_start + exec_aouthdr.a_data;
+ exec_data_offset = N_TXTOFF(exec_aouthdr);
+ fstat (execchan, &st_exec);
+ exec_mtime = st_exec.st_mtime;
+ }
+#endif /* not COFF_FORMAT */
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No exec file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
+
+/* rounds 'one' up to divide evenly by 'two' */
+
+int
+round(one,two)
+register int one, two;
+
+{
+ register int temp;
+ temp = (one/two)*two;
+ if (one != temp) {
+ temp += two;
+ }
+ return temp;
+}
+
+
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[sizeof (int)];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() (codestream_addr + codestream_off)
+#define codestream_peek() (codestream_cnt == 0 ? \
+ codestream_fill(1): codestream_buf[codestream_off])
+#define codestream_get() (codestream_cnt-- == 0 ? \
+ codestream_fill(0) : codestream_buf[codestream_off++])
+
+
+static unsigned char
+codestream_fill (peek_flag)
+{
+ codestream_addr = codestream_next_addr;
+ codestream_next_addr += sizeof (int);
+ codestream_off = 0;
+ codestream_cnt = sizeof (int);
+ read_memory (codestream_addr,
+ (unsigned char *)codestream_buf,
+ sizeof (int));
+
+ if (peek_flag)
+ return (codestream_peek());
+ else
+ return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+{
+ codestream_next_addr = place & -sizeof (int);
+ codestream_cnt = 0;
+ codestream_fill (1);
+ while (codestream_tell() != place)
+ codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+ unsigned char *buf;
+{
+ unsigned char *p;
+ int i;
+ p = buf;
+ for (i = 0; i < count; i++)
+ *p++ = codestream_get ();
+}
+
+/*
+ * Following macro translates i386 opcode register numbers to Symmetry
+ * register numbers. This is used by FRAME_FIND_SAVED_REGS.
+ *
+ * %eax %ecx %edx %ebx %esp %ebp %esi %edi
+ * i386 0 1 2 3 4 5 6 7
+ * Symmetry 0 2 1 5 14 15 6 7
+ *
+ */
+#define I386_REGNO_TO_SYMMETRY(n) \
+((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
+
+/* from i386-dep.c */
+i386_frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ unsigned long locals;
+ unsigned char *p;
+ unsigned char op;
+ CORE_ADDR dummy_bottom;
+ CORE_ADDR adr;
+ int i;
+
+ bzero (fsrp, sizeof *fsrp);
+
+ /* if frame is the end of a dummy, compute where the
+ * beginning would be
+ */
+ dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
+
+ /* check if the PC is in the stack, in a dummy frame */
+ if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
+ {
+ /* all regs were saved by push_call_dummy () */
+ adr = fip->frame - 4;
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ fsrp->regs[i] = adr;
+ adr -= 4;
+ }
+ return;
+ }
+
+ locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
+
+ if (locals >= 0)
+ {
+ adr = fip->frame - 4 - locals;
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_get ();
+ if (op < 0x50 || op > 0x57)
+ break;
+ fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
+ adr -= 4;
+ }
+ }
+
+ fsrp->regs[PC_REGNUM] = fip->frame + 4;
+ fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+static long
+i386_get_frame_setup (pc)
+{
+ unsigned char op;
+
+ codestream_seek (pc);
+
+ i386_follow_jump ();
+
+ op = codestream_get ();
+
+ if (op == 0x58) /* popl %eax */
+ {
+ /*
+ * this function must start with
+ *
+ * popl %eax 0x58
+ * xchgl %eax, (%esp) 0x87 0x04 0x24
+ * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
+ *
+ * (the system 5 compiler puts out the second xchg
+ * inst, and the assembler doesn't try to optimize it,
+ * so the 'sib' form gets generated)
+ *
+ * this sequence is used to get the address of the return
+ * buffer for a function that returns a structure
+ */
+ int pos;
+ unsigned char buf[4];
+ static unsigned char proto1[3] = { 0x87,0x04,0x24 };
+ static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
+ pos = codestream_tell ();
+ codestream_read (buf, 4);
+ if (bcmp (buf, proto1, 3) == 0)
+ pos += 3;
+ else if (bcmp (buf, proto2, 4) == 0)
+ pos += 4;
+
+ codestream_seek (pos);
+ op = codestream_get (); /* update next opcode */
+ }
+
+ if (op == 0x55) /* pushl %esp */
+ {
+ if (codestream_get () != 0x8b) /* movl %esp, %ebp (2bytes) */
+ return (-1);
+ if (codestream_get () != 0xec)
+ return (-1);
+ /*
+ * check for stack adjustment
+ *
+ * subl $XXX, %esp
+ *
+ * note: you can't subtract a 16 bit immediate
+ * from a 32 bit reg, so we don't have to worry
+ * about a data16 prefix
+ */
+ op = codestream_peek ();
+ if (op == 0x83) /* subl with 8 bit immed */
+ {
+ codestream_get ();
+ if (codestream_get () != 0xec)
+ return (-1);
+ /* subl with signed byte immediate
+ * (though it wouldn't make sense to be negative)
+ */
+ return (codestream_get());
+ }
+ else if (op == 0x81) /* subl with 32 bit immed */
+ {
+ int locals;
+ if (codestream_get () != 0xec)
+ return (-1);
+ /* subl with 32 bit immediate */
+ codestream_read ((unsigned char *)&locals, 4);
+ return (locals);
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ else if (op == 0xc8)
+ {
+ /* enter instruction: arg is 16 unsigned immed */
+ unsigned short slocals;
+ codestream_read ((unsigned char *)&slocals, 2);
+ codestream_get (); /* flush final byte of enter instruction */
+ return (slocals);
+ }
+ return (-1);
+}
+
+/* next instruction is a jump, move to target */
+static
+i386_follow_jump ()
+{
+ int long_delta;
+ short short_delta;
+ char byte_delta;
+ int data16;
+ int pos;
+
+ pos = codestream_tell ();
+
+ data16 = 0;
+ if (codestream_peek () == 0x66)
+ {
+ codestream_get ();
+ data16 = 1;
+ }
+
+ switch (codestream_get ())
+ {
+ case 0xe9:
+ /* relative jump: if data16 == 0, disp32, else disp16 */
+ if (data16)
+ {
+ codestream_read ((unsigned char *)&short_delta, 2);
+ pos += short_delta + 3; /* include size of jmp inst */
+ }
+ else
+ {
+ codestream_read ((unsigned char *)&long_delta, 4);
+ pos += long_delta + 5;
+ }
+ break;
+ case 0xeb:
+ /* relative jump, disp8 (ignore data16) */
+ codestream_read ((unsigned char *)&byte_delta, 1);
+ pos += byte_delta + 2;
+ break;
+ }
+ codestream_seek (pos + data16);
+}
+
+/* return pc of first real instruction */
+/* from i386-dep.c */
+
+i386_skip_prologue (pc)
+{
+ unsigned char op;
+ int i;
+
+ if (i386_get_frame_setup (pc) < 0)
+ return (pc);
+
+ /* found valid frame setup - codestream now points to
+ * start of push instructions for saving registers
+ */
+
+ /* skip over register saves */
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_peek ();
+ /* break if not pushl inst */
+ if (op < 0x50 || op > 0x57)
+ break;
+ codestream_get ();
+ }
+
+ i386_follow_jump ();
+
+ return (codestream_tell ());
+}
+
+symmetry_extract_return_value(type, regbuf, valbuf)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+{
+ union {
+ double d;
+ int l[2];
+ } xd;
+ int i;
+ float f;
+
+ if (TYPE_CODE_FLT == TYPE_CODE(type)) {
+ for (i = 0; i < misc_function_count; i++) {
+ if (!strcmp(misc_function_vector[i].name, "1167_flt"))
+ break;
+ }
+ if (i < misc_function_count) {
+ /* found "1167_flt" means 1167, %fp2-%fp3 */
+ /* float & double; 19= %fp2, 20= %fp3 */
+ /* no single precision on 1167 */
+ xd.l[1] = *((int *)®buf[REGISTER_BYTE(19)]);
+ xd.l[0] = *((int *)®buf[REGISTER_BYTE(20)]);
+ switch (TYPE_LENGTH(type)) {
+ case 4:
+ f = (float) xd.d;
+ bcopy(&f, valbuf, TYPE_LENGTH(type));
+ break;
+ case 8:
+ bcopy(&xd.d, valbuf, TYPE_LENGTH(type));
+ break;
+ default:
+ error("Unknown floating point size");
+ break;
+ }
+ } else {
+ /* 387 %st(0), gcc uses this */
+ i387_to_double(((int *)®buf[REGISTER_BYTE(3)]),
+ &xd.d);
+ switch (TYPE_LENGTH(type)) {
+ case 4: /* float */
+ f = (float) xd.d;
+ bcopy(&f, valbuf, 4);
+ break;
+ case 8: /* double */
+ bcopy(&xd.d, valbuf, 8);
+ break;
+ default:
+ error("Unknown floating point size");
+ break;
+ }
+ }
+ } else {
+ bcopy (regbuf, valbuf, TYPE_LENGTH (type));
+ }
+}
--- /dev/null
+/* Sequent Symmetry host interface, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include "gdbcore.h"
+#include <fcntl.h>
+
+static long i386_get_frame_setup ();
+static i386_follow_jump ();
+
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+store_inferior_registers(regno)
+int regno;
+{
+ struct pt_regset regs;
+ int reg_tmp, i;
+ extern char registers[];
+
+#if 0
+ /* PREPARE_TO_STORE deals with this. */
+ if (-1 == regno)
+ {
+#endif
+ regs.pr_eax = *(int *)®isters[REGISTER_BYTE(0)];
+ regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)];
+ regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)];
+ regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)];
+ regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)];
+ regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)];
+ regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)];
+ regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)];
+ regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)];
+ regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)];
+ for (i = 0; i < 31; i++) {
+ regs.pr_fpa.fpa_regs[i] =
+ *(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)];
+ }
+#if 0
+ }
+ else
+ {
+ reg_tmp = *(int *)®isters[REGISTER_BYTE(regno)];
+ ptrace(XPT_RREGS, inferior_pid, ®s, 0);
+ switch (regno)
+ {
+ case 0:
+ regs.pr_eax = *(int *)®isters[REGISTER_BYTE(0)];
+ break;
+ case 5:
+ regs.pr_ebx = *(int *)®isters[REGISTER_BYTE(5)];
+ break;
+ case 2:
+ regs.pr_ecx = *(int *)®isters[REGISTER_BYTE(2)];
+ break;
+ case 1:
+ regs.pr_edx = *(int *)®isters[REGISTER_BYTE(1)];
+ break;
+ case 6:
+ regs.pr_esi = *(int *)®isters[REGISTER_BYTE(6)];
+ break;
+ case 7:
+ regs.pr_edi = *(int *)®isters[REGISTER_BYTE(7)];
+ break;
+ case 15:
+ regs.pr_ebp = *(int *)®isters[REGISTER_BYTE(15)];
+ break;
+ case 14:
+ regs.pr_esp = *(int *)®isters[REGISTER_BYTE(14)];
+ break;
+ case 16:
+ regs.pr_eip = *(int *)®isters[REGISTER_BYTE(16)];
+ break;
+ case 17:
+ regs.pr_flags = *(int *)®isters[REGISTER_BYTE(17)];
+ break;
+ }
+ }
+#endif /* 0 */
+ ptrace(XPT_WREGS, inferior_pid, ®s, 0);
+}
+
+void
+fetch_inferior_registers()
+{
+ int i;
+ struct pt_regset regs;
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace(XPT_RREGS, inferior_pid, ®s, 0);
+ *(int *)®isters[REGISTER_BYTE(0)] = regs.pr_eax;
+ *(int *)®isters[REGISTER_BYTE(5)] = regs.pr_ebx;
+ *(int *)®isters[REGISTER_BYTE(2)] = regs.pr_ecx;
+ *(int *)®isters[REGISTER_BYTE(1)] = regs.pr_edx;
+ *(int *)®isters[REGISTER_BYTE(6)] = regs.pr_esi;
+ *(int *)®isters[REGISTER_BYTE(7)] = regs.pr_edi;
+ *(int *)®isters[REGISTER_BYTE(15)] = regs.pr_ebp;
+ *(int *)®isters[REGISTER_BYTE(14)] = regs.pr_esp;
+ *(int *)®isters[REGISTER_BYTE(16)] = regs.pr_eip;
+ *(int *)®isters[REGISTER_BYTE(17)] = regs.pr_flags;
+ for (i = 0; i < FPA_NREGS; i++) {
+ *(int *)®isters[REGISTER_BYTE(FP1_REGNUM+i)] = regs.pr_fpa.fpa_regs[i];
+ }
+ bcopy(regs.pr_fpu.fpu_stack[0], ®isters[REGISTER_BYTE(3)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[1], ®isters[REGISTER_BYTE(4)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[2], ®isters[REGISTER_BYTE(8)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[3], ®isters[REGISTER_BYTE(9)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[4], ®isters[REGISTER_BYTE(10)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[5], ®isters[REGISTER_BYTE(11)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[6], ®isters[REGISTER_BYTE(12)], 10);
+ bcopy(regs.pr_fpu.fpu_stack[7], ®isters[REGISTER_BYTE(13)], 10);
+}
+
+\f
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+#include "gdbcore.h"
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+ int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name (filename);
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * (u.u_dsize - u.u_tsize);
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = ctob(UPAGES + u.u_dsize - u.u_tsize);
+ reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+printf("u.u_tsize= %#x, u.u_dsize= %#x, u.u_ssize= %#x, stack_off= %#x\n",
+ u.u_tsize, u.u_dsize, u.u_ssize, stack_offset);
+
+ core_aouthdr.a_magic = 0;
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0)
+ perror_with_name (filename);
+
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame(create_new_frame(read_register(FP_REGNUM),
+ read_pc()));
+/* set_current_frame (read_register (FP_REGNUM));*/
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
+
+/* from i386-dep.c */
+static
+print_387_control_word (control)
+unsigned short control;
+{
+ printf ("control 0x%04x: ", control);
+ printf ("compute to ");
+ switch ((control >> 8) & 3)
+ {
+ case 0: printf ("24 bits; "); break;
+ case 1: printf ("(bad); "); break;
+ case 2: printf ("53 bits; "); break;
+ case 3: printf ("64 bits; "); break;
+ }
+ printf ("round ");
+ switch ((control >> 10) & 3)
+ {
+ case 0: printf ("NEAREST; "); break;
+ case 1: printf ("DOWN; "); break;
+ case 2: printf ("UP; "); break;
+ case 3: printf ("CHOP; "); break;
+ }
+ if (control & 0x3f)
+ {
+ printf ("mask:");
+ if (control & 0x0001) printf (" INVALID");
+ if (control & 0x0002) printf (" DENORM");
+ if (control & 0x0004) printf (" DIVZ");
+ if (control & 0x0008) printf (" OVERF");
+ if (control & 0x0010) printf (" UNDERF");
+ if (control & 0x0020) printf (" LOS");
+ printf (";");
+ }
+ printf ("\n");
+ if (control & 0xe080) printf ("warning: reserved bits on 0x%x\n",
+ control & 0xe080);
+}
+
+static
+print_387_status_word (status)
+ unsigned short status;
+{
+ printf ("status %#04x: ", status);
+ if (status & 0xff) {
+ printf ("exceptions:"); /* exception names match <machine/fpu.h> */
+ if (status & 0x0001) printf (" FLTINV");
+ if (status & 0x0002) printf (" FLTDEN");
+ if (status & 0x0004) printf (" FLTDIV");
+ if (status & 0x0008) printf (" FLTOVF");
+ if (status & 0x0010) printf (" FLTUND");
+ if (status & 0x0020) printf (" FLTPRE");
+ if (status & 0x0040) printf (" FLTSTK");
+ printf ("; ");
+ }
+ printf ("flags: %d%d%d%d; ",
+ (status & 0x4000) != 0,
+ (status & 0x0400) != 0,
+ (status & 0x0200) != 0,
+ (status & 0x0100) != 0);
+
+ printf ("top %d\n", (status >> 11) & 7);
+}
+
+static
+print_fpu_status(ep)
+struct pt_regset ep;
+
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ printf("80387:");
+ if (ep.pr_fpu.fpu_ip == 0) {
+ printf(" not in use.\n");
+ return;
+ } else {
+ printf("\n");
+ }
+ if (ep.pr_fpu.fpu_status != 0) {
+ print_387_status_word (ep.pr_fpu.fpu_status);
+ }
+ print_387_control_word (ep.pr_fpu.fpu_control);
+ printf ("last exception: ");
+ printf ("opcode 0x%x; ", ep.pr_fpu.fpu_rsvd4);
+ printf ("pc 0x%x:0x%x; ", ep.pr_fpu.fpu_cs, ep.pr_fpu.fpu_ip);
+ printf ("operand 0x%x:0x%x\n", ep.pr_fpu.fpu_data_offset, ep.pr_fpu.fpu_op_sel);
+
+ top = (ep.pr_fpu.fpu_status >> 11) & 7;
+
+ printf ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep.pr_fpu.fpu_tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf ("valid "); break;
+ case 1: printf ("zero "); break;
+ case 2: printf ("trap "); break;
+ case 3: printf ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf ("%02x", ep.pr_fpu.fpu_stack[fpreg][i]);
+
+ i387_to_double (ep.pr_fpu.fpu_stack[fpreg], (char *)&val);
+ printf (" %g\n", val);
+ }
+ if (ep.pr_fpu.fpu_rsvd1)
+ printf ("warning: rsvd1 is 0x%x\n", ep.pr_fpu.fpu_rsvd1);
+ if (ep.pr_fpu.fpu_rsvd2)
+ printf ("warning: rsvd2 is 0x%x\n", ep.pr_fpu.fpu_rsvd2);
+ if (ep.pr_fpu.fpu_rsvd3)
+ printf ("warning: rsvd3 is 0x%x\n", ep.pr_fpu.fpu_rsvd3);
+ if (ep.pr_fpu.fpu_rsvd5)
+ printf ("warning: rsvd5 is 0x%x\n", ep.pr_fpu.fpu_rsvd5);
+}
+
+
+print_1167_control_word(pcr)
+unsigned int pcr;
+
+{
+ int pcr_tmp;
+
+ pcr_tmp = pcr & FPA_PCR_MODE;
+ printf("\tMODE= %#x; RND= %#x ", pcr_tmp, pcr_tmp & 12);
+ switch (pcr_tmp & 12) {
+ case 0:
+ printf("RN (Nearest Value)");
+ break;
+ case 1:
+ printf("RZ (Zero)");
+ break;
+ case 2:
+ printf("RP (Positive Infinity)");
+ break;
+ case 3:
+ printf("RM (Negative Infinity)");
+ break;
+ }
+ printf("; IRND= %d ", pcr_tmp & 2);
+ if (0 == pcr_tmp & 2) {
+ printf("(same as RND)\n");
+ } else {
+ printf("(toward zero)\n");
+ }
+ pcr_tmp = pcr & FPA_PCR_EM;
+ printf("\tEM= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_EM_DM) printf(" DM");
+ if (pcr_tmp & FPA_PCR_EM_UOM) printf(" UOM");
+ if (pcr_tmp & FPA_PCR_EM_PM) printf(" PM");
+ if (pcr_tmp & FPA_PCR_EM_UM) printf(" UM");
+ if (pcr_tmp & FPA_PCR_EM_OM) printf(" OM");
+ if (pcr_tmp & FPA_PCR_EM_ZM) printf(" ZM");
+ if (pcr_tmp & FPA_PCR_EM_IM) printf(" IM");
+ printf("\n");
+ pcr_tmp = FPA_PCR_CC;
+ printf("\tCC= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_20MHZ) printf(" 20MHZ");
+ if (pcr_tmp & FPA_PCR_CC_Z) printf(" Z");
+ if (pcr_tmp & FPA_PCR_CC_C2) printf(" C2");
+ if (pcr_tmp & FPA_PCR_CC_C1) printf(" C1");
+ switch (pcr_tmp) {
+ case FPA_PCR_CC_Z:
+ printf(" (Equal)");
+ break;
+ case FPA_PCR_CC_C1:
+ printf(" (Less than)");
+ break;
+ case 0:
+ printf(" (Greater than)");
+ break;
+ case FPA_PCR_CC_Z | FPA_PCR_CC_C1 | FPA_PCR_CC_C2:
+ printf(" (Unordered)");
+ break;
+ default:
+ printf(" (Undefined)");
+ break;
+ }
+ printf("\n");
+ pcr_tmp = pcr & FPA_PCR_AE;
+ printf("\tAE= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_AE_DE) printf(" DE");
+ if (pcr_tmp & FPA_PCR_AE_UOE) printf(" UOE");
+ if (pcr_tmp & FPA_PCR_AE_PE) printf(" PE");
+ if (pcr_tmp & FPA_PCR_AE_UE) printf(" UE");
+ if (pcr_tmp & FPA_PCR_AE_OE) printf(" OE");
+ if (pcr_tmp & FPA_PCR_AE_ZE) printf(" ZE");
+ if (pcr_tmp & FPA_PCR_AE_EE) printf(" EE");
+ if (pcr_tmp & FPA_PCR_AE_IE) printf(" IE");
+ printf("\n");
+}
+
+print_1167_regs(regs)
+long regs[FPA_NREGS];
+
+{
+ int i;
+
+ union {
+ double d;
+ long l[2];
+ } xd;
+ union {
+ float f;
+ long l;
+ } xf;
+
+
+ for (i = 0; i < FPA_NREGS; i++) {
+ xf.l = regs[i];
+ printf("%%fp%d: raw= %#x, single= %f", i+1, regs[i], xf.f);
+ if (!(i & 1)) {
+ printf("\n");
+ } else {
+ xd.l[1] = regs[i];
+ xd.l[0] = regs[i+1];
+ printf(", double= %f\n", xd.d);
+ }
+ }
+}
+
+print_fpa_status(ep)
+struct pt_regset ep;
+
+{
+
+ printf("WTL 1167:");
+ if (ep.pr_fpa.fpa_pcr !=0) {
+ printf("\n");
+ print_1167_control_word(ep.pr_fpa.fpa_pcr);
+ print_1167_regs(ep.pr_fpa.fpa_regs);
+ } else {
+ printf(" not in use.\n");
+ }
+}
+
+i386_float_info ()
+
+{
+ char ubuf[UPAGES*NBPG];
+ struct pt_regset regset;
+ extern int corechan;
+
+ if (have_inferior_p()) {
+ call_ptrace(XPT_RREGS, inferior_pid, ®set, 0);
+ } else {
+ if (lseek (corechan, 0, 0) < 0) {
+ perror ("seek on core file");
+ }
+ if (myread (corechan, ubuf, UPAGES*NBPG) < 0) {
+ perror ("read on core file");
+ }
+ /* only interested in the floating point registers */
+ regset.pr_fpu = ((struct user *) ubuf)->u_fpusave;
+ regset.pr_fpa = ((struct user *) ubuf)->u_fpasave;
+ }
+ print_fpu_status(regset);
+ print_fpa_status(regset);
+}
+
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ long *lp;
+ /* push extended mode on 387 stack, then pop in double mode
+ *
+ * first, set exception masks so no error is generated -
+ * number will be rounded to inf or 0, if necessary
+ */
+ asm ("pushl %eax"); /* grab a stack slot */
+ asm ("fstcw (%esp)"); /* get 387 control word */
+ asm ("movl (%esp),%eax"); /* save old value */
+ asm ("orl $0x3f,%eax"); /* mask all exceptions */
+ asm ("pushl %eax");
+ asm ("fldcw (%esp)"); /* load new value into 387 */
+
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldt (%eax)"); /* push extended number on 387 stack */
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpl (%eax)"); /* pop double */
+ asm ("fwait");
+
+ asm ("popl %eax"); /* flush modified control word */
+ asm ("fnclex"); /* clear exceptions */
+ asm ("fldcw (%esp)"); /* restore original control word */
+ asm ("popl %eax"); /* flush saved copy */
+}
+
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ /* push double mode on 387 stack, then pop in extended mode
+ * no errors are possible because every 64-bit pattern
+ * can be converted to an extended
+ */
+ asm ("movl 8(%ebp),%eax");
+ asm ("fldl (%eax)");
+ asm ("fwait");
+ asm ("movl 12(%ebp),%eax");
+ asm ("fstpt (%eax)");
+ asm ("fwait");
+}
--- /dev/null
+/* This file has been modified by Data General Corporation, November 1989. */
+
+/*
+This file provides an abstract interface to "tdesc" information.
+ It is designed to be used in a uniform manner by several kinds
+ of debuggers:
+ (1) code in live debugged process (e.g., a traceback routine)
+ (2) a separate-process debugger debugging a live process
+ (3) a separate-process debugger debugging a memory dump
+
+ Dcontext model notes
+ * captures machine context
+ * partial: excludes memory
+ * frames
+ * kinds
+ * make one for starters, chain in reverse order to previous ones
+ * representation: pointer to opaque
+ * alloc/free protocol
+
+ Overall model
+ * access functions
+ * handle
+ * error handling
+*/
+
+
+
+typedef int dc_boolean_t; /* range 0 .. 1 */
+#define DC_FALSE 0
+#define DC_TRUE 1
+
+
+typedef int dc_tristate_t; /* range 0 .. 2 */
+#define DC_NO 0
+#define DC_YES 1
+#define DC_MAYBE 2
+
+
+/*
+ A word is 32 bits of information. In memory, a word is word-aligned.
+
+ A common and important use of dc_word_t is to represent values in the
+ target process, including (byte) addresses in the target process.
+ In this case, C arithmetic can be used to simulate machine address
+ arithmetic on the target. (Unsigned arithmetic is actually modulus
+ arithmetic.)
+*/
+typedef unsigned int dc_word_t;
+
+
+/* These bit operations number bits from 0 at the least significant end. */
+#define bit_test(word,bit) ((word) & (1 << (bit))) /* returns 0 or other */
+#define bit_value(word,bit) (((word) >> (bit)) & 1) /* returns 0 or 1 */
+#define bit_set(word,bit) ((word) |= (1 << (bit)))
+#define bit_clear(word,bit) ((word) &= ~(1 << (bit)))
+#define bit_assign(word, bit, bool) \
+ if (bool) bit_set(word, bit); else bit_clear(word, bit)
+
+
+/*----------------*/
+
+
+/* The exactness of locations may not be certainly known. */
+typedef dc_tristate_t dc_exactness_t;
+
+
+/*
+ The model includes five kinds of contexts. Because each context
+ has an associated region and frame, these describe region kinds
+ and frame kinds as well.
+ [more description needed]
+ Currently, only call contexts exist.
+*/
+
+typedef int dc_kind_t; /* range 0 .. 4 */
+#define DC_CALL_KIND 0
+#define DC_SAVE_KIND 1
+#define DC_EXCEPTION_KIND 2
+#define DC_PROTECTION_KIND 3
+#define DC_SPECIAL_KIND 4
+#define DC_NUM_KINDS 5
+
+#define DC_MIO_ENTRY_POINT (1<< 0)
+#define DC_MIO_PROLOGUE_END (1<< 1)
+#define DC_MIO_EPILOGUE_START (1<< 2)
+#define DC_MIO_IMPLICIT_PROLOGUE_END (1<<16)
+#define DC_MIO_LITERAL_ENTRY_POINT (1<<17)
+#define DC_MIO_LITERAL_EPILOGUE_START (1<<18)
+
+#define DC_MII_PRECEDING_TDESC_END (1<<0)
+#define DC_MII_FOLLOWING_TDESC_START (1<<1)
+
+typedef struct dc_debug_info {
+ unsigned int protocol; /* 1 for this structure */
+ dc_word_t tdesc_ptr;
+ unsigned int text_words_count;
+ dc_word_t text_words_ptr;
+ unsigned int data_words_count;
+ dc_word_t data_words_ptr;
+} dc_debug_info_t;
+
+
+typedef struct tdesc_hdr {
+ unsigned int map_protocol; /* 1 for this structure */
+ unsigned int end; /* address beyond end */
+} tdesc_hdr_t;
+
+
+typedef struct tdesc_chunk_hdr {
+ int zeroes : 8;
+ int info_length : 22;
+ int info_alignment : 2;
+ unsigned int info_protocol;
+ dc_word_t start_address;
+ dc_word_t end_address;
+} tdesc_chunk_hdr_t;
+
+
+typedef struct tdesc_chunk_info1 {
+ int variant : 8; /* 1 for this structure */
+ int register_save_mask : 17;
+ int pad1 : 1;
+ int return_address_info_discriminant : 1;
+ int frame_address_register : 5;
+ unsigned int frame_address_offset;
+ unsigned int return_address_info;
+ unsigned int register_save_offset;
+} tdesc_chunk_info1_t;
+
+
+typedef struct tdesc_chunk1 {
+ tdesc_chunk_hdr_t hdr;
+ tdesc_chunk_info1_t info;
+} tdesc_chunk1_t;
+
+
+typedef struct dc_mstate {
+ dc_word_t reg[32]; /* general registers */
+ dc_word_t xip;
+ dc_word_t nip;
+ dc_word_t fip;
+ dc_word_t fpsr;
+ dc_word_t fpcr;
+ dc_word_t psr;
+} dc_mstate_t;
+
+
+typedef struct dc_map_info_in {
+ dc_word_t flags;
+ dc_word_t preceding_tdesc_end;
+ dc_word_t following_tdesc_start;
+} dc_map_info_in_t;
+
+
+typedef struct dc_map_info_out {
+ dc_word_t flags;
+ dc_word_t entry_point;
+ dc_word_t prologue_end;
+ dc_word_t epilogue_start;
+} dc_map_info_out_t;
+
+
+#if 0
+
+ void error_fcn (env, continuable, message)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_boolean_t continuable; /* whether error function may return */
+ char *message; /* string (no trailing newline) */
+
+ /* In the future, we probably want the error_fcn to be: */
+ void error_fcn (env, continuable, code, ...)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_boolean_t continuable; /* whether error function may return */
+ int code; /* error code */
+ ... /* parameters to message associated
+ with the code */
+
+ void read_fcn (env, memory, length, buffer)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_word_t memory; /* start address in image */
+ int length; /* in bytes */
+ char *buffer; /* start address of buffer */
+ /* There are no alignment assumptions for the read function. */
+
+ void write_fcn (env, memory, length, buffer)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_word_t memory; /* start address in image */
+ int length; /* in bytes */
+ char *buffer; /* start address of buffer */
+ /* There are no alignment assumptions for the write function. */
+ /* The write function is optional. It must be provided if changes
+ to writable registers are to be made. */
+
+ void exec_fcn (env, mstate)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_mstate_t *mstate; /* machine state (read-write) */
+ /* The execute function is optional. It would be used (in the future)
+ by the implementation of a procedurally specified tdesc mechanism. */
+
+#endif
+
+/*----------------*/
+
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+extern char *malloc();
+extern char *calloc();
+extern void qsort();
+
+
+/*
+ At initialization, create a tdesc table from the tdesc info.
+ A tdesc table is simply a sorted array of tdesc elements.
+ A tdesc element is the last 6 words of the tdesc chunk.
+ We require that all tdesc chunks have info protocol 1.
+*/
+
+typedef struct tdesc_elem {
+ dc_word_t start_address;
+ dc_word_t end_address;
+ tdesc_chunk_info1_t info;
+} tdesc_elem_t;
+
+typedef tdesc_elem_t *tdesc_table_t;
+
+void dc_correct_cr_data();
+
+int dc_compare_tdesc_elems (elem1, elem2)
+ char *elem1, *elem2;
+{
+ dc_word_t s1, s2, e1, e2;
+ s1 = ((tdesc_elem_t *) elem1)->start_address;
+ s2 = ((tdesc_elem_t *) elem2)->start_address;
+ if (s1 < s2) return -1;
+ if (s1 > s2) return +1;
+ e1 = ((tdesc_elem_t *) elem1)->end_address;
+ e2 = ((tdesc_elem_t *) elem2)->end_address;
+ if (e1 < e2) return -1;
+ if (e1 > e2) return +1;
+ return 0;
+}
+
+
+typedef struct handle_info {
+ dc_word_t debug_info_ptr;
+ void (*error_fcn)();
+ dc_word_t error_env;
+ void (*read_fcn)();
+ dc_word_t read_env;
+ void (*write_fcn)(); /* NULL => absent */
+ dc_word_t write_env;
+ void (*exec_fcn)(); /* NULL => absent */
+ dc_word_t exec_env;
+ void (*map_fcn)(); /* NULL => absent */
+ dc_word_t map_env;
+ tdesc_table_t tdesc_table;
+ int tdesc_table_size;
+} handle_info_t;
+
+typedef handle_info_t *dc_handle_t;
+
+
+/*
+ Errors detected in this module are funnelled through dc_error or dc_warn,
+ as appropriate. Both routines call dc_exception, which invokes the error
+ handler supplied by the user.
+
+ Currently, dc_exception substitutes parameters into the message given
+ it and passes the resulting string to the user error handler.
+ In the future, dc_exception should simply pass an error code and
+ the parameters on to the user error handler.
+*/
+
+#include <varargs.h>
+extern int vsprintf();
+
+/* Exit status for exception-processing machinery failure */
+#define DC_EXCEPTION_FAILURE 250
+
+void dc_exception(continuable, args)
+ dc_boolean_t continuable;
+ va_list args;
+{
+ dc_handle_t handle;
+ char *format;
+ char buffer[1024];
+
+ handle = va_arg(args, dc_handle_t);
+ format = va_arg(args, char *);
+ (void) vsprintf(buffer, format, args);
+ (*(handle->error_fcn)) (handle->error_env, continuable, buffer);
+ if (!continuable)
+ exit(DC_EXCEPTION_FAILURE); /* User error handler should never return in this case. */
+}
+
+
+void dc_error(va_alist) /* (handle, format, args... ) */
+ va_dcl
+{
+ va_list args;
+
+ va_start(args);
+ dc_exception(DC_FALSE, args);
+ va_end(args);
+}
+
+
+void dc_warn(va_alist) /* (handle, format, args... ) */
+ va_dcl
+{
+ va_list args;
+
+ va_start(args);
+ dc_exception(DC_TRUE, args);
+ va_end(args);
+}
+
+
+
+#define MALLOC_FAILURE_MESSAGE "Heap space exhausted (malloc failed)."
+#define CALLOC_FAILURE_MESSAGE "Heap space exhausted (Calloc failed)."
+
+
+/* Commonize memory allocation call so failure diagnosis is easier */
+
+char* dc_malloc( handle, size )
+ dc_handle_t handle;
+ int size;
+{
+ char* space = malloc( size );
+ if (space == (char *)NULL)
+ dc_error( handle, MALLOC_FAILURE_MESSAGE );
+
+ return space;
+}
+
+
+/* Commonize memory allocation call so failure diagnosis is easier */
+
+char* dc_calloc( handle,nelem, size )
+ dc_handle_t handle;
+ int nelem;
+ int size;
+{
+ char* space = calloc( nelem, size );
+ if (space == (char *)NULL)
+ dc_error( handle, CALLOC_FAILURE_MESSAGE );
+
+ return space;
+}
+
+
+dc_word_t dc_read_word (handle, address)
+ dc_handle_t handle;
+ dc_word_t address;
+{
+ dc_word_t word;
+ (*(handle->read_fcn)) (handle->read_env, address,
+ sizeof(dc_word_t), (char *)(&(word)));
+ return word;
+}
+
+
+void dc_write_word (handle, address, value)
+ dc_handle_t handle;
+ dc_word_t address;
+ dc_word_t value;
+{
+ dc_word_t word;
+ word = value;
+ if (handle->write_fcn) {
+ (*(handle->write_fcn)) (handle->write_env, address,
+ sizeof(dc_word_t), (char *)(&(word)));
+ } else {
+ dc_error (handle, "Writing is disabled.");
+ }
+}
+
+
+void dc_write_masked_word (handle, address, mask, value)
+ dc_handle_t handle;
+ dc_word_t address;
+ dc_word_t mask;
+ dc_word_t value;
+{
+ dc_write_word (handle, address,
+ (value & mask) | (dc_read_word(handle, address) & ~mask));
+}
+
+
+dc_handle_t dc_initiate (debug_info_ptr,
+ error_fcn, error_env,
+ read_fcn, read_env,
+ write_fcn, write_env,
+ exec_fcn, exec_env,
+ map_fcn, map_env)
+ dc_word_t debug_info_ptr;
+ void (*error_fcn)();
+ dc_word_t error_env;
+ void (*read_fcn)();
+ dc_word_t read_env;
+ void (*write_fcn)(); /* NULL => absent */
+ dc_word_t write_env;
+ void (*exec_fcn)(); /* NULL => absent */
+ dc_word_t exec_env;
+ void (*map_fcn)(); /* NULL => absent */
+ dc_word_t map_env;
+ /* write_fcn may be given as NULL if no writing is required. */
+ /* exec_fcn may be given as NULL if no execution is required.
+ Currently, no execution is required. It would be if the
+ implementation needed to invoke procedures in the debugged process. */
+{
+ dc_handle_t handle;
+ unsigned int debug_info_protocol;
+ dc_debug_info_t debug_info;
+ unsigned int tdesc_map_protocol;
+ tdesc_hdr_t tdesc_hdr;
+ dc_word_t tdesc_info_start;
+ dc_word_t tdesc_info_end;
+ dc_word_t tdesc_info_length;
+
+ /* Set up handle enough for dc_error. */
+ handle = (dc_handle_t) malloc(sizeof(handle_info_t));
+ /* Cant use dc_malloc() as handle is being created ... */
+ /* if (handle == NULL) (*error_fcn)( error_env, MALLOC_FAILURE_MESSAGE ) */
+ handle->error_fcn = error_fcn;
+ handle->error_env = error_env;
+ handle->read_fcn = read_fcn;
+ handle->read_env = read_env;
+ handle->write_fcn = write_fcn;
+ handle->write_env = write_env;
+ handle->exec_fcn = exec_fcn;
+ handle->exec_env = exec_env;
+/****************************************************************/
+/* BUG 9/19/89 Found by hls. Map functions not initialized. */
+/****************************************************************/
+ handle->map_fcn = map_fcn;
+ handle->map_env = map_env;
+ handle->debug_info_ptr = debug_info_ptr;
+ handle->tdesc_table = (tdesc_table_t)NULL;
+
+ /* Find tdesc info. */
+ if (debug_info_ptr) {
+ (*read_fcn) (read_env, debug_info_ptr, sizeof(unsigned int),
+ (char *)(&debug_info_protocol));
+ if (debug_info_protocol != 1)
+ dc_error (handle, "Unrecognized debug info protocol: %d",
+ debug_info_protocol);
+ (*read_fcn) (read_env, debug_info_ptr, sizeof(dc_debug_info_t),
+ (char *)(&debug_info));
+ (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(unsigned int),
+ (char *)(&tdesc_map_protocol));
+ if (tdesc_map_protocol != 1)
+ dc_error (handle, "Unrecognized tdesc map protocol: %d",
+ tdesc_map_protocol);
+ (*read_fcn) (read_env, debug_info.tdesc_ptr, sizeof(tdesc_hdr_t),
+ (char *)(&tdesc_hdr));
+ tdesc_info_start = debug_info.tdesc_ptr + sizeof(tdesc_hdr_t);
+ tdesc_info_end = tdesc_hdr.end;
+ tdesc_info_length = tdesc_info_end - tdesc_info_start;
+
+ /* Create tdesc table from tdesc info. */
+ {
+ /* Over-allocate in order to avoid second pass over tdesc info. */
+ tdesc_table_t tt = (tdesc_table_t) dc_malloc(handle, tdesc_info_length);
+ dc_word_t p = tdesc_info_start;
+ dc_word_t q = tdesc_info_end - sizeof(tdesc_chunk1_t);
+ int n = 0;
+ tdesc_chunk1_t chunk;
+ dc_word_t start_address, end_address;
+ int i;
+
+ for (; p <= q; ) {
+ (*read_fcn) (read_env, p, sizeof(tdesc_chunk1_t), (char *)(&chunk));
+ if (chunk.hdr.zeroes != 0) {
+ /* Skip padding. */
+ p += sizeof(dc_word_t);
+ continue;
+ }
+ if (chunk.hdr.info_protocol != 1) {
+ dc_warn (handle, "Unrecognized tdesc info protocol: %d",
+ chunk.hdr.info_protocol);
+ goto next_chunk;
+ }
+ if (chunk.hdr.info_length != 16) {
+ dc_warn (handle, "Incorrect tdesc info length: %d",
+ chunk.hdr.info_length);
+ goto next_chunk;
+ }
+ if (chunk.hdr.info_alignment > 2) {
+ dc_warn (handle, "Incorrect tdesc info alignment: %d",
+ chunk.hdr.info_alignment);
+ goto next_chunk;
+ }
+ start_address = chunk.hdr.start_address;
+ end_address = chunk.hdr.end_address;
+ if ((start_address&3)!=0) {
+ dc_warn (handle,
+ "Tdesc start address is not word-aligned: %#.8X",
+ start_address);
+ goto next_chunk;
+ }
+ if ((end_address&3)!=0) {
+ dc_warn (handle,
+ "Tdesc end address is not word-aligned: %#.8X",
+ end_address);
+ goto next_chunk;
+ }
+ if (start_address > end_address) {
+ /* Note that the range may be null. */
+ dc_warn (handle,
+ "Tdesc start address (%#.8X) follows end address (%#.8X).",
+ start_address, end_address);
+ goto next_chunk;
+ }
+ if (chunk.info.variant != 1) {
+ dc_warn (handle, "Invalid tdesc chunk variant: %d",
+ chunk.info.variant);
+ goto next_chunk;
+ }
+ if (chunk.info.pad1 != 0) {
+ dc_warn (handle, "Tdesc chunk padding is not zero.");
+ goto next_chunk;
+ }
+ if (chunk.info.return_address_info_discriminant != 0) {
+ if ((chunk.info.return_address_info & 3) != 0) {
+ dc_warn (handle,
+ "Tdesc return address offset is not word-aligned: %#.8X",
+ chunk.info.return_address_info);
+ goto next_chunk;
+ }
+ } else {
+ if ((chunk.info.return_address_info & ~31) != 0) {
+ dc_warn (handle,
+ "Invalid tdesc return address register: %d",
+ chunk.info.return_address_info);
+ goto next_chunk;
+ }
+ }
+ if ((chunk.info.register_save_offset & 3) != 0) {
+ dc_warn (handle,
+ "Tdesc register save offset is not word-aligned: %#.8X",
+ chunk.info.register_save_offset);
+ goto next_chunk;
+ }
+
+ tt[n].start_address = start_address;
+ tt[n].end_address = end_address;
+ tt[n].info = chunk.info;
+ n++;
+
+ next_chunk:
+ p += sizeof(tdesc_chunk1_t);
+ }
+ /* Leftover (less than a tdesc_chunk1_t in size) is padding or
+ in error. Ignore it in either case. */
+
+ if (n != 0) {
+
+ /* Sort table by start address. */
+ qsort ((char *)tt, n, sizeof(tdesc_elem_t), dc_compare_tdesc_elems);
+
+ /* Check for overlap among tdesc chunks. */
+ for (i=0; i<(n-1); i++) {
+ if (tt[i].end_address > tt[i+1].start_address)
+ dc_error (handle, "Text chunks overlap.");
+ }
+ }
+
+ /* Finish setting up handle. */
+ handle->tdesc_table = tt;
+ handle->tdesc_table_size = n;
+ }
+ } else {
+ handle->tdesc_table_size = 0;
+ }
+
+ return (dc_handle_t) handle;
+}
+
+
+void dc_terminate (handle)
+ dc_handle_t handle;
+{
+ if (((dc_handle_t)handle)->tdesc_table) {
+ free((char *)(((dc_handle_t)handle)->tdesc_table));
+ }
+ free((char *)handle);
+}
+
+
+
+/*
+
+ Dcontext Model
+
+ For each interesting register (word-sized piece of machine state),
+ a word of value information is kept. This word may
+ be either the value of the register, or the address in
+ subject memory where the value can be found (and changed). In
+ addition, the register may be invalid (in which case the value
+ information is undefined). These three cases are encoded for
+ a given register in the same-numbered bit of two words of flags:
+
+ flags[0] bit flags[1] bit meaning
+ ------------ ------------ -------
+ 0 0 register is invalid; info is undefined
+ 0 1 register is readable; info is value
+ 1 0 register is writable; info is address
+ 1 1 (reserved)
+
+ The general registers (r0-r31) are handled by reg_info and
+ reg_flags. The bit number for a register is that register's number.
+ The other registers are grouped together for convenience and are
+ handled by aux_info and aux_flags. The bit numbers for these
+ registers are:
+
+ bit number register
+ ---------- --------
+ 0 location
+ 1 SXIP
+ 2 SNIP
+ 3 SFIP
+ 4 FPSR
+ 5 FPCR
+
+ The SXIP, SNIP, and SFIP are the exception-time values of the
+ XIP, NIP, and FIP registers. They are valid only in the topmost frame.
+ (That is, in any context obtained from dc_previous_context, they
+ are invalid.)
+
+ "location" is a pseudo-register of this model and represents the
+ location of the context. It is always valid. It also has an
+ exactness associated with it. The location and its exactness of a
+ context obtained from dc_previous_context are taken from the
+ return address and its exactness of the context given as an argument
+ to dc_previous_context.
+
+ The following model is recommended for dealing with the partial
+ redundancy between location and the SXIP, SNIP, and SFIP values
+ in the topmost frame. The location should be set to either the
+ SNIP or SXIP value, and its exactness should be set to DC_NO. A
+ change to the register whose value the location is set to should
+ be accompanied by an identical change to the location.
+
+ The PSR is handled separately, because it is a diverse collection
+ of flags. The PSR, as a whole, is always valid. A separate
+ psr_ind flag tells whether the psr_info data is a value or
+ an address. Each bit of the PSR has its own pair of flag bits to
+ mark validity and writability.
+
+*/
+
+
+/* The following value means "other", because state is stored in 2 bits. */
+#define DC_RESERVED 3
+
+
+#define RSTATE(flags, bit) \
+ ((bit_value((flags)[0], bit) << 1) + bit_value((flags)[1], bit))
+
+#define REG_STATE(dcontext, reg) RSTATE(dcontext->reg_flags, reg)
+#define AUX_STATE(dcontext, reg) RSTATE(dcontext->aux_flags, reg)
+#define PSR_STATE(dcontext, reg) RSTATE(dcontext->psr_flags, reg)
+
+
+#define SET_INVALID(flags, bit) \
+ { bit_clear ((flags)[0], bit); bit_clear ((flags)[1], bit); }
+
+#define SET_READABLE(flags, bit) \
+ { bit_clear ((flags)[0], bit); bit_set ((flags)[1], bit); }
+
+#define SET_WRITABLE(flags, bit) \
+ { bit_set ((flags)[0], bit); bit_clear ((flags)[1], bit); }
+
+#define ASSIGN_RSTATE(to_flags, to_bit, from_flags, from_bit) \
+ { bit_assign ((to_flags)[0], to_bit, bit_value((from_flags)[0], from_bit));\
+ bit_assign ((to_flags)[1], to_bit, bit_value((from_flags)[1], from_bit));}
+
+
+#define CHECK_REG_READ(dcontext, reg) \
+ if (REG_STATE(dcontext, reg) == DC_INVALID) \
+ dc_error (dcontext->handle, \
+ "General register %d is not readable.", reg)
+
+#define CHECK_REG_WRITE(dcontext, reg) \
+ if (REG_STATE(dcontext, reg) != DC_WRITABLE) \
+ dc_error (dcontext->handle, \
+ "General register %d is not writable.", reg)
+
+#define CHECK_AUX_READ(dcontext, reg) \
+ if (AUX_STATE(dcontext, reg) == DC_INVALID) \
+ dc_error (dcontext->handle, \
+ "Auxiliary register %d is not readable.", reg)
+
+#define CHECK_AUX_WRITE(dcontext, reg) \
+ if (AUX_STATE(dcontext, reg) != DC_WRITABLE) \
+ dc_error (dcontext->handle, \
+ "Auxiliary register %d is not writable.", reg)
+
+
+
+#define DC_REG_RA 1
+#define DC_REG_FP 30
+#define DC_REG_SP 31
+#define DC_NUM_REG 32
+
+#define DC_AUX_LOC 0
+ /* DC_AUX_LOC must be first, with value 0 */
+#define DC_AUX_SXIP 1
+#define DC_AUX_SNIP 2
+#define DC_AUX_SFIP 3
+#define DC_AUX_FPSR 4
+#define DC_AUX_FPCR 5
+#define DC_NUM_AUX 6
+
+
+
+#define CHECK_REG(dcontext, reg) \
+ if ((reg < 0) || (reg >= DC_NUM_REG)) \
+ dc_error (dcontext->handle, \
+ "Bad general register number: %d", reg)
+
+#define CHECK_AUX(dcontext, reg) \
+ if ((reg < 1) || (reg >= DC_NUM_AUX)) \
+ dc_error (dcontext->handle, \
+ "Bad auxiliary register number: %d", reg)
+ /* CHECK_AUX is not used for location pseudo-register. */
+
+#define CHECK_BIT(dcontext, bit) \
+ if ((bit < 0) || (bit >= 32)) \
+ dc_error (dcontext->handle, \
+ "Bad bit number: %d", bit)
+
+
+
+typedef struct cr_value {
+ int reg;
+ unsigned int off;
+ } dc_cr_value_t;
+
+#define DC_UNDEF 32
+
+/*
+ A "dc_cr_value" represents an execution-time value symbolically, in
+ terms of the initial value of a register (the value on entry to
+ the procedure being analyzed) and a known offset. A value with
+ a 'reg' field value of 0 through 31 represents the value obtained
+ by summing (using 32-bit modulus arithmetic) the initial value of
+ register 'reg' and the value 'off'. Note that the value (0,k)
+ represents the constant value k, that (31,0) represents the CFA, and
+ that (1,0) represents the return address. A value with a 'reg' field
+ of DC_UNDEF represents an indeterminable value; in this case the
+ 'off' field is undefined. Other values of 'reg' are erroneous.
+*/
+
+typedef struct cr_data {
+ dc_cr_value_t reg_val[DC_NUM_REG];
+ dc_word_t saved;
+ dc_word_t how;
+ unsigned int where[DC_NUM_REG];
+} dc_cr_data_t;
+
+/*
+ 'cr_data' collects all the information needed to represent the
+ symbolic machine state during code reading.
+
+ The 'reg_val' array gives the current dc_cr_value for each register.
+
+ The 'saved', 'how', and 'where' fields combine to describe what
+ registers have been saved, and where. The 'saved' and 'how' fields
+ are implicitly bit arrays over 0..31, where the numbering is from
+ 0 on the right. (Hence, 1<<r gives the mask for register r.)
+ If saved[r] is 0, the register is not saved, and how[r] and where[r]
+ are undefined. If saved[r] is 1, then how[r] tells whether register r
+ was saved in another register (how[r]==0) or in the frame (how[r]==1).
+ In the former case, where[r] gives the register number; in the latter
+ case, where[r] gives the frame position.
+*/
+
+
+typedef int dc_register_state_t; /* range 0 to 2 */
+
+#define DC_INVALID 0
+#define DC_READABLE 1
+#define DC_WRITABLE 2
+
+
+
+
+typedef struct dcontext_info {
+ dc_handle_t handle; /* environment of context */
+ dc_word_t reg_info[DC_NUM_REG];
+ dc_word_t reg_flags[2];
+ dc_word_t aux_info[DC_NUM_AUX];
+ dc_word_t aux_flags[2];
+ dc_exactness_t loc_exact;
+ dc_word_t psr_info; /* value or address */
+ dc_word_t psr_ind; /* DC_TRUE iff address */
+ dc_word_t psr_flags[2]; /* per-PSR-bit flags */
+ unsigned int code_reading; /* no tdesc therefore must read code*/
+ union {
+ tdesc_elem_t *tdesc_elem_ptr; /* locates tdesc chunk */
+ dc_cr_data_t *cr_data_ptr; /* or code reading data */
+ } info_ptr;
+} dcontext_info_t;
+
+typedef dcontext_info_t *dc_dcontext_t;
+
+dc_word_t dc_get_value (handle, info, flags, pos)
+ dc_handle_t handle;
+ dc_word_t info[];
+ dc_word_t flags[2];
+ int pos;
+ /* Assumes either DC_READABLE or DC_WRITABLE. */
+{
+ if (bit_test(flags[0], pos)) {
+ /* DC_WRITABLE case */
+ return dc_read_word(handle, info[pos]);
+ } else {
+ /* DC_READABLE case */
+ return info[pos];
+ }
+}
+
+void dc_set_value (handle, info, flags, pos, value)
+ dc_handle_t handle;
+ dc_word_t info[];
+ dc_word_t flags[2];
+ int pos;
+ dc_word_t value;
+ /* Assumes DC_WRITABLE. */
+{
+ dc_write_word(handle, info[pos], value);
+}
+
+
+#define GET_REG_VALUE(dcontext, reg) \
+ dc_get_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg)
+
+#define SET_REG_VALUE(dcontext, reg, value) \
+ dc_set_value(dcontext->handle, dcontext->reg_info, dcontext->reg_flags, reg, \
+ value)
+
+#define GET_AUX_VALUE(dcontext, reg) \
+ dc_get_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg)
+
+#define SET_AUX_VALUE(dcontext, reg, value) \
+ dc_set_value(dcontext->handle, dcontext->aux_info, dcontext->aux_flags, reg, \
+ value)
+
+
+
+void dc_check_dcontext (dc)
+ dc_dcontext_t dc;
+ /* Check consistency of information supplied to make a dcontext. */
+{
+ int i;
+
+ if ((REG_STATE(dc, 0) != DC_READABLE) || (dc->reg_info[0] != 0))
+ dc_error (dc->handle, "Register 0 is misspecified");
+ for (i = 1; i < DC_NUM_REG; i++)
+ if (REG_STATE(dc, i) == DC_RESERVED)
+ dc_error (dc->handle,
+ "State for general register %d is incorrect", i);
+ for (i = 0; i < DC_NUM_AUX; i++)
+ if (AUX_STATE(dc, i) == DC_RESERVED)
+ dc_error (dc->handle,
+ "State for auxiliary register %d is incorrect", i);
+ if (AUX_STATE(dc, DC_AUX_LOC) == DC_INVALID)
+ dc_error (dc->handle, "Location is specified as invalid");
+ if (GET_AUX_VALUE(dc, DC_AUX_LOC) == 0)
+ dc_error (dc->handle, "Location is zero.");
+ if (dc->loc_exact >= 3)
+ dc_error (dc->handle, "Location exactness is incorrectly specified: %d",
+ dc->loc_exact);
+ if (dc->psr_ind >= 2)
+ dc_error (dc->handle,
+ "PSR indirection flag is incorrectly specified: %d",
+ dc->psr_ind);
+ for (i = 0; i < 32; i++)
+ if (PSR_STATE(dc, i) == DC_RESERVED)
+ dc_error (dc->handle, "State for PSR bit %d is incorrect", i);
+}
+
+
+
+tdesc_elem_t * dc_tdesc_lookup (loc, tt, tt_size, map_info_in_ptr)
+ dc_word_t loc;
+ tdesc_table_t tt;
+ int tt_size;
+ dc_map_info_in_t *map_info_in_ptr;
+ /* Return address of tdesc_elem_t for given location, or NULL if
+ there is no tdesc chunk for the location.
+ */
+{
+ int l = 0;
+ int h = tt_size;
+ int m;
+
+ if (tt_size == 0) {
+ map_info_in_ptr->flags = 0;
+ return (tdesc_elem_t *)NULL;
+ }
+ for (;;) {
+ m = (l + h) / 2;
+ if (m == l) break;
+ if (loc >= tt[m].start_address)
+ l = m;
+ else
+ h = m;
+ }
+ if (loc >= tt[m].end_address) {
+ map_info_in_ptr->preceding_tdesc_end = tt[m].end_address;
+ if (m+1 < tt_size) {
+ map_info_in_ptr->following_tdesc_start = tt[m+1].start_address;
+ map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END |
+ DC_MII_FOLLOWING_TDESC_START;
+ } else {
+ map_info_in_ptr->flags = DC_MII_PRECEDING_TDESC_END;
+ }
+ return (tdesc_elem_t *)NULL;
+ } else if (loc < tt[m].start_address) {
+ map_info_in_ptr->following_tdesc_start = tt[m].start_address;
+ map_info_in_ptr->flags = DC_MII_FOLLOWING_TDESC_START;
+ return (tdesc_elem_t *)NULL;
+ } else {
+ return (&tt[m]);
+ }
+}
+
+
+
+dc_dcontext_t dc_make_dcontext (handle,
+ reg_info, reg_flags,
+ aux_info, aux_flags, loc_exact,
+ psr_info, psr_ind, psr_flags)
+ dc_handle_t handle;
+ dc_word_t reg_info[DC_NUM_REG];
+ dc_word_t reg_flags[2];
+ dc_word_t aux_info[DC_NUM_AUX];
+ dc_word_t aux_flags[2];
+ dc_exactness_t loc_exact;
+ dc_word_t psr_info;
+ dc_boolean_t psr_ind;
+ dc_word_t psr_flags[2];
+{
+ dc_dcontext_t dc = (dc_dcontext_t) dc_malloc (handle, sizeof(dcontext_info_t));
+ int i;
+ dc_map_info_in_t map_info_in;
+
+ /* Fill in supplied content. */
+ dc->handle = ((dc_handle_t)handle);
+ for (i = 0; i < DC_NUM_REG; i++) dc->reg_info[i] = reg_info[i];
+ for (i = 0; i < 2; i++) dc->reg_flags[i] = reg_flags[i];
+ for (i = 0; i < DC_NUM_AUX; i++) dc->aux_info[i] = aux_info[i];
+ for (i = 0; i < 2; i++) dc->aux_flags[i] = aux_flags[i];
+ dc->loc_exact = loc_exact;
+ dc->psr_info = psr_info;
+ dc->psr_ind = psr_ind;
+ for (i = 0; i < 2; i++) dc->psr_flags[i] = psr_flags[i];
+
+ dc_check_dcontext(dc);
+
+ /* Find tdesc information for the text chunk. */
+ {
+/***************************************************************/
+/* BUG 8/16/89 Found by hls. Not zeroing EV bits of location. */
+/* SHOULD USE dc_location()! */
+/* dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC); */
+/***************************************************************/
+ dc_word_t loc = GET_AUX_VALUE(dc, DC_AUX_LOC) & ~3;
+ tdesc_elem_t *tep =
+ dc_tdesc_lookup(loc, ((dc_handle_t)handle)->tdesc_table,
+ ((dc_handle_t)handle)->tdesc_table_size,&map_info_in);
+ if (tep) {
+ dc->code_reading = 0;
+ dc->info_ptr.tdesc_elem_ptr = tep;
+ } else {
+ dc->code_reading = 1;
+ if (!dc->handle->map_fcn) {
+ dc_error (dc->handle, "No tdesc information for %#.8X and no map function supplied.",loc);
+ }
+/****************************************************************/
+/* BUG 9/18/89 Found by hls. Not using dc_malloc() */
+/* dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)malloc(sizeof(dc_cr_data_t )); */
+/****************************************************************/
+ dc->info_ptr.cr_data_ptr= (dc_cr_data_t *)dc_calloc(dc->handle,1,sizeof(dc_cr_data_t ));
+ dc_read_code(loc,dc,map_info_in,dc->info_ptr.cr_data_ptr);
+ }
+ }
+
+ return (dc_dcontext_t) dc;
+}
+
+
+
+void dc_free_dcontext (dcontext)
+ dc_dcontext_t dcontext;
+{
+/****************************************************************/
+/* BUG 9/19/89 Found by hls. Freeing non-pointer value. */
+/* free((char *)dcontext->code_reading); */
+/****************************************************************/
+ if (dcontext->code_reading)
+ free((char *)dcontext->info_ptr.cr_data_ptr);
+ free((char *)dcontext);
+}
+
+
+
+dc_register_state_t dc_location_state (dcontext)
+ dc_dcontext_t dcontext;
+{
+ return AUX_STATE(((dc_dcontext_t)dcontext), DC_AUX_LOC);
+}
+
+
+dc_exactness_t dc_location_exactness (dcontext)
+ dc_dcontext_t dcontext;
+{
+ return ((dc_dcontext_t)dcontext)->loc_exact;
+}
+
+
+dc_word_t dc_location (dcontext)
+ dc_dcontext_t dcontext;
+ /* Return high 30 bits only. */
+{
+ /* Don't need: CHECK_AUX_READ (((dc_dcontext_t)dcontext), DC_AUX_LOC); */
+ return GET_AUX_VALUE (((dc_dcontext_t)dcontext), DC_AUX_LOC) & ~3;
+}
+
+
+dc_boolean_t dc_location_in_text_chunk( dcontext, value )
+ dc_dcontext_t dcontext;
+ dc_word_t value;
+{
+ /* Check that new location is still within same text chunk. */
+ tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+/********************************************************************/
+/* Bug in predicate -- LS adjusted according to OCS documentation.. */
+/* if ((value < tep->start_address) || (value >= tep->end_address))*/
+/********************************************************************/
+ if ((value >= tep->start_address) && (value < tep->end_address))
+ return DC_TRUE;
+ else
+ return DC_FALSE;
+
+}
+
+
+void dc_set_location (dcontext, value)
+ dc_dcontext_t dcontext;
+ dc_word_t value;
+ /* Set high 30 bits only. */
+{
+ if (dc_location_in_text_chunk( dcontext, value ) != DC_TRUE)
+ dc_warn (((dc_dcontext_t)dcontext)->handle,
+ "New location is not in same text chunk.");
+
+ CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), DC_AUX_LOC);
+ dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+ ((dc_dcontext_t)dcontext)->aux_info[DC_AUX_LOC], ~3, value);
+}
+
+
+
+dc_register_state_t dc_general_register_state (dcontext, reg)
+ dc_dcontext_t dcontext;
+ int reg;
+{
+ CHECK_REG (((dc_dcontext_t)dcontext), reg);
+ return REG_STATE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+dc_word_t dc_general_register (dcontext, reg)
+ dc_dcontext_t dcontext;
+ int reg;
+{
+ CHECK_REG (((dc_dcontext_t)dcontext), reg);
+ CHECK_REG_READ (((dc_dcontext_t)dcontext), reg);
+ return GET_REG_VALUE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+void dc_set_general_register (dcontext, reg, value)
+ dc_dcontext_t dcontext;
+ int reg;
+ dc_word_t value;
+{
+ CHECK_REG (((dc_dcontext_t)dcontext), reg);
+ CHECK_REG_WRITE (((dc_dcontext_t)dcontext), reg);
+ SET_REG_VALUE (((dc_dcontext_t)dcontext), reg, value);
+}
+
+
+
+dc_register_state_t dc_auxiliary_register_state (dcontext, reg)
+ dc_dcontext_t dcontext;
+ int reg;
+{
+ CHECK_AUX (((dc_dcontext_t)dcontext), reg);
+ return AUX_STATE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+dc_word_t dc_auxiliary_register (dcontext, reg)
+ dc_dcontext_t dcontext;
+ int reg;
+{
+ CHECK_AUX (((dc_dcontext_t)dcontext), reg);
+ CHECK_AUX_READ (((dc_dcontext_t)dcontext), reg);
+ return GET_AUX_VALUE(((dc_dcontext_t)dcontext), reg);
+}
+
+
+void dc_set_auxiliary_register (dcontext, reg, value)
+ dc_dcontext_t dcontext;
+ int reg;
+ dc_word_t value;
+{
+ CHECK_AUX (((dc_dcontext_t)dcontext), reg);
+ CHECK_AUX_WRITE (((dc_dcontext_t)dcontext), reg);
+ SET_AUX_VALUE (((dc_dcontext_t)dcontext), reg, value);
+}
+
+
+
+dc_register_state_t dc_psr_register_bit_state (dcontext, bit)
+ dc_dcontext_t dcontext;
+ int bit;
+{
+ CHECK_BIT (((dc_dcontext_t)dcontext), bit);
+ return PSR_STATE(((dc_dcontext_t)dcontext), bit);
+}
+
+
+dc_word_t dc_psr_register (dcontext)
+ dc_dcontext_t dcontext;
+{
+ if (((dc_dcontext_t)dcontext)->psr_ind) {
+ return dc_read_word(((dc_dcontext_t)dcontext)->handle,
+ ((dc_dcontext_t)dcontext)->psr_info);
+ } else {
+ return ((dc_dcontext_t)dcontext)->psr_info;
+ }
+}
+
+
+void dc_set_psr_register (dcontext, mask, value)
+ dc_dcontext_t dcontext;
+ dc_word_t mask;
+ dc_word_t value;
+ /* Set bits of PSR corresponding to 1 bits in mask. */
+{
+ if (((dc_dcontext_t)dcontext)->psr_ind) {
+ if (((((dc_dcontext_t)dcontext)->psr_flags[0] & mask) != mask) ||
+ ((((dc_dcontext_t)dcontext)->psr_flags[1] & mask) != 0))
+ dc_error (((dc_dcontext_t)dcontext)->handle,
+ "Some PSR bits specified are not writable.");
+ dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+ ((dc_dcontext_t)dcontext)->psr_info, mask, value);
+ } else {
+ dc_error (((dc_dcontext_t)dcontext)->handle, "PSR is not writable.");
+ }
+}
+
+
+
+dc_word_t dc_frame_address (dcontext)
+ dc_dcontext_t dcontext;
+{
+ if (!dcontext->code_reading) {
+ tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+ return dc_general_register(dcontext,
+ tep->info.frame_address_register) + tep->info.frame_address_offset;
+ } else {
+ if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].reg == DC_REG_SP) {
+ return (dc_general_register(dcontext,DC_REG_FP)
+ - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_FP].off);
+ }
+ if (dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].reg == DC_REG_SP) {
+ return (dc_general_register(dcontext,DC_REG_SP)
+ - dcontext->info_ptr.cr_data_ptr->reg_val[DC_REG_SP].off);
+ }
+ dc_error (((dc_dcontext_t)dcontext)->handle, "Cannot locate frame pointer.");
+ }
+}
+
+
+
+dc_kind_t dc_context_kind (dcontext)
+ dc_dcontext_t dcontext;
+{
+ return DC_CALL_KIND;
+}
+
+
+
+
+/* operations valid for call contexts only */
+
+
+dc_register_state_t dc_return_address_state (dcontext)
+ dc_dcontext_t dcontext;
+{
+ tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+ int reg;
+
+ if (!dcontext->code_reading) {
+ if (tep->info.return_address_info_discriminant) {
+ return DC_WRITABLE;
+ } else {
+ return REG_STATE(((dc_dcontext_t)dcontext), tep->info.return_address_info);
+ }
+ } else {
+ reg= DC_REG_RA;
+ if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
+ if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
+ return DC_WRITABLE;
+ } else {
+ reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
+ }
+ }
+ return REG_STATE(((dc_dcontext_t)dcontext),reg);
+
+
+ }
+}
+
+
+dc_exactness_t dc_return_address_exactness (dcontext)
+ dc_dcontext_t dcontext;
+{
+ return DC_MAYBE;
+}
+
+
+dc_word_t dc_return_address (dcontext)
+ dc_dcontext_t dcontext;
+ /* Return high 30 bits only. */
+{
+ tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+ dc_word_t rai = tep->info.return_address_info;
+ dc_word_t val;
+ int reg;
+
+ if (!dcontext->code_reading) {
+ if (tep->info.return_address_info_discriminant) {
+ val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
+ dc_frame_address(dcontext) + rai);
+ } else {
+ val = dc_general_register (dcontext, rai);
+ }
+ } else {
+ reg=DC_REG_RA;
+ if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,reg)) {
+ if (bit_test(dcontext->info_ptr.cr_data_ptr->how,reg)) {
+ val = dc_read_word (((dc_dcontext_t)dcontext)->handle,
+ dc_frame_address(dcontext) +
+ (dcontext->info_ptr.cr_data_ptr->where[reg]));
+ } else {
+ reg= dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA];
+ val = dc_general_register (dcontext, reg);
+ }
+ } else {
+ val = dc_general_register (dcontext, reg);
+ }
+ }
+ return val & ~3;
+}
+
+
+void dc_set_return_address (dcontext, value)
+ dc_dcontext_t dcontext;
+ dc_word_t value;
+ /* Set high 30 bits only. */
+{
+ if (!dcontext->code_reading) {
+ tdesc_elem_t *tep = ((dc_dcontext_t)dcontext)->info_ptr.tdesc_elem_ptr;
+ dc_word_t rai = tep->info.return_address_info;
+
+ if (tep->info.return_address_info_discriminant) {
+ dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+ dc_frame_address(dcontext) + rai, ~3, value);
+ } else {
+ dc_set_general_register (dcontext, rai,
+ (value & ~3) | (dc_general_register(dcontext, rai) & 3));
+ }
+ } else {
+ if (bit_test(dcontext->info_ptr.cr_data_ptr->saved,DC_REG_RA)) {
+ if (bit_test(dcontext->info_ptr.cr_data_ptr->how,DC_REG_RA)) {
+ dc_write_masked_word (((dc_dcontext_t)dcontext)->handle,
+ dc_frame_address(dcontext)
+ + dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA], ~3, value);
+ } else {
+ dc_set_general_register( dcontext,
+ dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
+ }
+ } else {
+ dc_set_general_register( dcontext,
+ dcontext->info_ptr.cr_data_ptr->where[DC_REG_RA]);
+ }
+ }
+}
+
+
+
+/* operations valid for save contexts only */
+
+/* (none) */
+
+
+
+/* operations valid for exception contexts only */
+
+
+void dc_get_exception_info (dcontext, handler, datum)
+ dc_dcontext_t dcontext;
+ dc_word_t *handler;
+ dc_word_t *datum;
+{
+ dc_error (((dc_dcontext_t)dcontext)->handle,
+ "dc_get_exception_info is not yet implemented.");
+}
+
+
+
+/* operations valid for protection contexts only */
+
+
+void dc_get_protection_info (dcontext, handler, datum)
+ dc_dcontext_t dcontext;
+ dc_word_t *handler;
+ dc_word_t *datum;
+{
+ dc_error (((dc_dcontext_t)dcontext)->handle,
+ "dc_get_protection_info is not yet implemented.");
+}
+
+
+
+/* operations valid for special contexts only */
+
+
+void dc_get_special_info (dcontext, kind, datum)
+ dc_dcontext_t dcontext;
+ dc_word_t *kind;
+ dc_word_t *datum;
+{
+ dc_error (((dc_dcontext_t)dcontext)->handle,
+ "dc_get_special_info is not yet implemented.");
+}
+
+
+
+/* operations valid for all contexts (again) */
+
+
+dc_dcontext_t dc_previous_dcontext (dcontext)
+ dc_dcontext_t dcontext;
+ /* Return NULL if there is no previous context. */
+{
+ dc_dcontext_t old = (dc_dcontext_t) dcontext;
+ dcontext_info_t new; /* to serve as temporary storage only */
+ tdesc_elem_t *tep;
+ dc_cr_data_t *cdp;
+ dc_word_t cfa;
+ int rsm;
+ dc_word_t offset;
+ dc_word_t rai;
+ int r;
+
+ if (dc_return_address_state((dc_dcontext_t)old) == DC_INVALID)
+ dc_error (old->handle, "Return address is invalid.");
+
+ if (dc_return_address((dc_dcontext_t)old) == 0)
+ return (dc_dcontext_t)NULL; /* end of the chain */
+
+ /* Copy over old contents. */
+ new = *old;
+
+ cfa = dc_frame_address(old);
+ /* Restore stack pointer. */
+ new.reg_info[DC_REG_SP] = cfa;
+ SET_READABLE (new.reg_flags, DC_REG_SP);
+
+ /* Invalidate temporary registers. */
+ for (r = 1; r <= 13; r++) SET_INVALID (new.reg_flags, r);
+
+ if (!old->code_reading) {
+ tep = old->info_ptr.tdesc_elem_ptr;
+ /* Restore preserved registers. */
+ rsm = tep->info.register_save_mask;
+ offset = cfa + tep->info.register_save_offset;
+ for (r = 14; r <= 30; r++) {
+ if (bit_test(rsm, 30-r)) {
+ new.reg_info[r] = offset;
+ SET_WRITABLE (new.reg_flags, r);
+ offset += sizeof(dc_word_t);
+ }
+ }
+
+ /* Set location from old return address. */
+ rai = tep->info.return_address_info;
+ if (tep->info.return_address_info_discriminant) {
+ new.aux_info[DC_AUX_LOC] = cfa + rai;
+ SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
+ } else {
+ new.aux_info[DC_AUX_LOC] = old->reg_info[rai];
+ ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC, old->reg_flags, rai);
+ }
+ } else {
+ cdp = old->info_ptr.cr_data_ptr;
+
+ /* Restore preserved registers. */
+ for (r = 14; r <= 30; r++) {
+ if (bit_test(cdp->saved,r)) {
+ if (bit_test(cdp->how,r)){ /* saved in the frame */
+ new.reg_info[r] = cfa+cdp->where[r];
+ SET_WRITABLE (new.reg_flags, r);
+ } else { /* saved in the in a register */
+ new.reg_info[r] = dc_general_register(old,cdp->where[r]);
+ ASSIGN_RSTATE (new.aux_flags, r, old->reg_flags, cdp->where[r]);
+ }
+ } /* not saved, therefore, already valid , no else*/
+ }
+
+ /* Set location from old return address. */
+ if (bit_test(cdp->saved,DC_REG_RA)) {
+ if (bit_test(cdp->how,DC_REG_RA)){ /* saved in the frame */
+ new.aux_info[DC_AUX_LOC] =
+ new.reg_info[DC_REG_RA] = cfa+cdp->where[DC_REG_RA];
+ SET_WRITABLE (new.reg_flags, DC_REG_RA);
+ SET_WRITABLE (new.aux_flags, DC_AUX_LOC);
+ } else { /* saved in the in a register */
+ new.reg_info[DC_REG_RA] =
+ new.aux_info[DC_AUX_LOC] =
+ dc_general_register(old,cdp->where[DC_REG_RA]);
+ ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC,
+ old->reg_flags, cdp->where[DC_REG_RA]);
+ }
+ } else { /* not saved, therefore, already valid , set DC_AUX_LOC only*/
+ new.aux_info[DC_AUX_LOC] =
+ dc_general_register(old,DC_REG_RA);
+ ASSIGN_RSTATE (new.aux_flags, DC_AUX_LOC,
+ old->reg_flags, DC_REG_RA);
+ }
+ }
+
+ /* Invalidate instruction pointers. */
+ SET_INVALID (new.aux_flags, DC_AUX_SXIP);
+ SET_INVALID (new.aux_flags, DC_AUX_SNIP);
+ SET_INVALID (new.aux_flags, DC_AUX_SFIP);
+
+ /* No change to FCR registers. */
+
+ /* No change to PSR register. */
+
+ return dc_make_dcontext ((dc_handle_t)new.handle,
+ new.reg_info, new.reg_flags,
+ new.aux_info, new.aux_flags, new.loc_exact,
+ new.psr_info, new.psr_ind, new.psr_flags);
+}
+
+
+
+/* extensions for nonlocal goto */
+
+#if 0
+
+typedef
+ struct label {
+ ???
+ } label_t;
+
+
+label_t dc_make_label (dcontext, location)
+ dc_dcontext_t dcontext;
+ dc_word_t location;
+{
+}
+
+#endif
+
+/* procedure for reading code */
+
+dc_read_code(loc,dc,map_info_in,cdp)
+dc_word_t loc;
+dc_dcontext_t dc;
+dc_cr_data_t *cdp;
+dc_map_info_in_t map_info_in;
+{
+dc_map_info_out_t map_info_out;
+dc_word_t pc;
+dc_boolean_t found_branch=DC_FALSE;
+dc_word_t instr;
+
+ (*dc->handle->map_fcn)(dc->handle->map_env,loc,map_info_in,&map_info_out);
+ if (map_info_out.flags & DC_MIO_ENTRY_POINT
+ && (!(map_info_in.flags & DC_MII_PRECEDING_TDESC_END)
+ || map_info_out.entry_point >= map_info_in.preceding_tdesc_end
+ || map_info_out.flags & DC_MIO_LITERAL_ENTRY_POINT)) {
+ dc_init_cr_data(cdp,(tdesc_elem_t *)NULL);
+ pc= map_info_out.entry_point;
+ } else if (map_info_in.flags & DC_MII_PRECEDING_TDESC_END) {
+ /**/
+ /* tdesc_lookup gets the tep for the preceeding tdesc information
+ /* so we call it with one less than the preceding tdesc end since
+ /* tdesc information is exclusive of the ending address
+ /**/
+ dc_init_cr_data(cdp,
+ dc_tdesc_lookup(map_info_in.preceding_tdesc_end-1,
+ ((dc_handle_t)dc->handle)->tdesc_table,
+ ((dc_handle_t)dc->handle)->tdesc_table_size,
+ &map_info_in));
+ pc= map_info_in.preceding_tdesc_end;
+ } else {
+ dc_error (dc->handle, "Insufficient information for code reading.");
+ }
+ for (;;pc+=4) {
+ if (pc==loc) {
+ return (DC_TRUE);
+ }
+ instr= dc_read_word(dc->handle,pc);
+ found_branch= dc_decode_finds_branch(dc,instr);
+ if ((map_info_out.flags & DC_MIO_PROLOGUE_END)
+ && (pc==map_info_out.prologue_end)) {
+ break;
+ }
+ if (found_branch) {
+ if (DC_MIO_IMPLICIT_PROLOGUE_END & map_info_out.flags) {
+ break;
+ } else {
+ dc_error (dc->handle, "Found branch before end of prologue.");
+ }
+ }
+ }
+ if (!(map_info_out.flags & DC_MIO_LITERAL_EPILOGUE_START)
+ && (map_info_out.epilogue_start >= loc
+ || !(map_info_out.flags & DC_MIO_EPILOGUE_START))) {
+ return (DC_TRUE);
+ }
+ dc_correct_cr_data(cdp,dc->handle);
+ for (pc=map_info_out.epilogue_start;pc<loc;pc+=4) {
+ instr= dc_read_word(dc->handle,pc);
+ if (dc_decode_finds_branch(dc,instr)) {
+ return (DC_FALSE);
+ }
+ }
+ return (DC_TRUE);
+
+}
+
+
+
+dc_init_cr_data(cdp,tep)
+dc_cr_data_t *cdp;
+tdesc_elem_t *tep;
+{
+int reg;
+dc_word_t rai;
+dc_word_t raid;
+dc_word_t rsm;
+dc_word_t frpos;
+
+ if (tep){
+
+ /* Start off with all registers undefined and none saved. */
+ for (reg = 0; reg < DC_NUM_REG; reg++) {
+ cdp->reg_val[reg].reg = DC_UNDEF;
+ }
+ cdp->saved = 0;
+
+ /* Overwrite with what tdesc element says. */
+
+ cdp->reg_val[tep->info.frame_address_register].reg = DC_REG_SP;
+ cdp->reg_val[tep->info.frame_address_register].off =
+ - tep->info.frame_address_offset;
+
+ rai = tep->info.return_address_info;
+ raid = tep->info.return_address_info_discriminant;
+ if (raid || rai != DC_REG_RA) {
+ bit_set(cdp->saved,DC_REG_RA);
+ bit_assign(cdp->how,DC_REG_RA,raid);
+ cdp->where[DC_REG_RA] = rai;
+ }
+
+ rsm = tep->info.register_save_mask;
+ frpos = tep->info.register_save_offset;
+ for (reg = 14; reg <= 30; reg++) {
+ if (bit_test(rsm, 30-reg)) {
+ bit_set(cdp->saved,reg);
+ bit_set(cdp->how,reg);
+ cdp->where[reg] = frpos;
+ frpos += sizeof(dc_word_t);
+ } else {
+ cdp->reg_val[reg].reg = reg;
+ cdp->reg_val[reg].off = 0;
+ }
+ }
+
+ cdp->reg_val[0].reg = 0; /* guarantee what hardware does */
+ cdp->reg_val[0].off = 0;
+
+ } else {
+ /* Each register has its own initial value. */
+ for (reg = 0; reg < DC_NUM_REG; reg++) {
+ cdp->reg_val[reg].reg = reg;
+ cdp->reg_val[reg].off = 0;
+ }
+ /* No register is yet saved. */
+ cdp->saved = 0;
+ cdp->how = 0;
+ }
+}
+void dc_correct_cr_data(cdp,handle)
+dc_cr_data_t *cdp;
+dc_handle_t handle;
+{
+long sr,r;
+dc_word_t save_regs = 0; /* registers used to save others */
+ for (r = 1; r < DC_REG_SP; r++) {
+ if (bit_test(cdp->saved,r) && !bit_test(cdp->how,r)) {
+ sr = cdp->where[r];
+ if (bit_test(save_regs,sr)) {
+ dc_error(handle, "Same register used to save two others.");
+ }
+ bit_set(save_regs,sr);
+ }
+ }
+ for (r = 1; r < DC_REG_FP; r++) {
+ if ((r < 14 || bit_test(cdp->saved,r)) && !bit_test(save_regs,r)) {
+ cdp->reg_val[r].reg = DC_UNDEF;
+ }
+ }
+ if (bit_test(cdp->saved,DC_REG_FP) &&
+ cdp->reg_val[DC_REG_FP].reg == DC_REG_SP) { /* is r30 the far? */
+ cdp->reg_val[DC_REG_SP].reg = DC_UNDEF; /* trash sp */
+ } else if (cdp->reg_val[DC_REG_SP].reg == DC_REG_SP) { /* is r31 the far? */
+ if (bit_test(cdp->saved,DC_REG_FP) && !bit_test(save_regs,DC_REG_FP)) {
+ cdp->reg_val[DC_REG_FP].reg = DC_UNDEF; /* trash r30 */
+ }
+ }
+}
--- /dev/null
+/* This file has been modified by Data General Corporation, November 1989. */
+
+#ifndef _tdesc_h
+#define _tdesc_h
+#ifdef __STDC__
+#define _ARGS(x) x
+#else
+#define _ARGS(x) ()
+#endif
+
+/*
+ This file provides an abstract interface to "tdesc" information.
+ It is designed to be used in a uniform manner by several kinds
+ of debuggers:
+ (1) code in live debugged process (e.g., a traceback routine)
+ (2) a separate-process debugger debugging a live process
+ (3) a separate-process debugger debugging a memory dump
+
+ Dcontext model notes
+ * captures machine context
+ * partial: excludes memory
+ * frames
+ * kinds
+ * make one for starters, chain in reverse order to previous ones
+ * representation: pointer to opaque
+ * alloc/free protocol
+
+ Overall model
+ * access functions
+ * handle
+ * error handling
+*/
+
+
+
+typedef int dc_boolean_t; /* range 0 .. 1 */
+#define DC_FALSE 0
+#define DC_TRUE 1
+
+
+typedef int dc_tristate_t; /* range 0 .. 2 */
+#define DC_NO 0
+#define DC_YES 1
+#define DC_MAYBE 2
+
+
+#define DC_MII_PRECEDING_TDESC_END (1<<0)
+#define DC_MII_FOLLOWING_TDESC_START (1<<1)
+
+#define DC_MIO_ENTRY_POINT (1<< 0)
+#define DC_MIO_PROLOGUE_END (1<< 1)
+#define DC_MIO_EPILOGUE_START (1<< 2)
+#define DC_MIO_IMPLICIT_PROLOGUE_END (1<<16)
+#define DC_MIO_LITERAL_ENTRY_POINT (1<<17)
+#define DC_MIO_LITERAL_EPILOGUE_START (1<<18)
+
+
+/*
+ A word is 32 bits of information. In memory, a word is word-aligned.
+
+ A common and important use of word_t is to represent values in the
+ target process, including (byte) addresses in the target process.
+ In this case, C arithmetic can be used to simulate machine address
+ arithmetic on the target. (Unsigned arithmetic is actually modulus
+ arithmetic.)
+*/
+typedef unsigned int dc_word_t;
+
+
+/*----------------*/
+
+
+/* The exactness of locations may not be certainly known. */
+typedef dc_tristate_t dc_exactness_t;
+
+
+/*
+ The model includes five kinds of contexts. Because each context
+ has an associated region and frame, these describe region kinds
+ and frame kinds as well.
+ [more description needed]
+ Currently, only call contexts exist.
+*/
+
+typedef int dc_kind_t; /* range 0 .. 4 */
+#define DC_CALL_KIND 0
+#define DC_SAVE_KIND 1
+#define DC_EXCEPTION_KIND 2
+#define DC_PROTECTION_KIND 3
+#define DC_SPECIAL_KIND 4
+#define DC_NUM_KINDS 5
+
+
+typedef struct dc_debug_info {
+ unsigned int protocol; /* 1 for this structure */
+ dc_word_t tdesc_ptr;
+ unsigned int text_words_count;
+ dc_word_t text_words_ptr;
+ unsigned int data_words_count;
+ dc_word_t data_words_ptr;
+} dc_debug_info_t;
+
+
+typedef struct dc_mstate {
+ dc_word_t reg[32]; /* general registers */
+ dc_word_t xip;
+ dc_word_t nip;
+ dc_word_t fip;
+ dc_word_t fpsr;
+ dc_word_t fpcr;
+ dc_word_t psr;
+} dc_mstate_t;
+
+
+
+#if 0
+
+ void error_fcn (env, continuable, message)
+ dc_word_t env; /* environment (arbitrary datum) */
+ boolean_t continuable; /* whether error function may return */
+ char *message; /* string (no trailing newline) */
+
+ /* In the future, we probably want the error_fcn to be: */
+ void error_fcn (env, continuable, code, ...)
+ dc_word_t env; /* environment (arbitrary datum) */
+ boolean_t continuable; /* whether error function may return */
+ int code; /* error code */
+ ... /* parameters to message associated
+ with the code */
+
+ void read_fcn (env, memory, length, buffer)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_word_t memory; /* start address in image */
+ int length; /* in bytes */
+ char *buffer; /* start address of buffer */
+ /* There are no alignment assumptions for the read function. */
+
+ void write_fcn (env, memory, length, buffer)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_word_t memory; /* start address in image */
+ int length; /* in bytes */
+ char *buffer; /* start address of buffer */
+ /* There are no alignment assumptions for the write function. */
+ /* The write function is optional. It must be provided if changes
+ to writable registers are to be made. */
+
+ void exec_fcn (env, mstate)
+ dc_word_t env; /* environment (arbitrary datum) */
+ dc_mstate_t *mstate; /* machine state (read-write) */
+ /* The execute function is optional. It would be used (in the future)
+ by the implementation of a procedurally specified tdesc mechanism. */
+
+#endif
+
+/*----------------*/
+
+
+typedef struct dc_map_info_in {
+ dc_word_t flags;
+ dc_word_t preceding_tdesc_end;
+ dc_word_t following_tdesc_start;
+} dc_map_info_in_t;
+
+
+typedef struct dc_map_info_out {
+ dc_word_t flags;
+ dc_word_t entry_point;
+ dc_word_t prologue_end;
+ dc_word_t epilogue_start;
+} dc_map_info_out_t;
+
+
+typedef void *dc_handle_t;
+
+typedef void (*tdesc_error_fcn_type) _ARGS((
+ dc_word_t env, /* environment (arbitrary datum) */
+ dc_boolean_t continuable, /* whether error function may return */
+ const char *message /* string (no trailing newline) */
+));
+typedef void (*tdesc_io_fcn_type) _ARGS((
+ dc_word_t env, /* environment (arbitrary datum) */
+ dc_word_t memory, /* start address in image */
+ int length, /* in bytes */
+ void *buffer /* start address of buffer */
+));
+typedef void (*tdesc_exec_fcn_type) _ARGS((
+ dc_word_t env, /* environment (arbitrary datum) */
+ dc_mstate_t *mstate /* machine state (read-write) */
+));
+typedef void (*tdesc_map_fcn_type) _ARGS((
+ dc_word_t map_env,
+ dc_word_t loc,
+ dc_map_info_in_t map_info_in,
+ dc_map_info_out_t *map_info_out
+));
+
+
+extern dc_handle_t dc_initiate _ARGS((
+ dc_word_t debug_info_ptr,
+ tdesc_error_fcn_type error_fcn,
+ dc_word_t error_env,
+ tdesc_io_fcn_type read_fcn,
+ dc_word_t read_env,
+ tdesc_io_fcn_type write_fcn, /* NULL => absent */
+ dc_word_t write_env,
+ tdesc_exec_fcn_type exec_fcn, /* NULL => absent */
+ dc_word_t exec_env,
+ tdesc_map_fcn_type map_fcn, /* NULL => absent */
+ dc_word_t map_env
+));
+extern void dc_terminate _ARGS((
+ dc_handle_t handle
+));
+
+typedef int dc_register_state_t; /* range 0 to 2 */
+
+#define DC_INVALID 0
+#define DC_READABLE 1
+#define DC_WRITABLE 2
+
+#define DC_NUM_REG 32
+
+#define DC_AUX_LOC 0
+#define DC_AUX_SXIP 1
+#define DC_AUX_SNIP 2
+#define DC_AUX_SFIP 3
+#define DC_AUX_FPSR 4
+#define DC_AUX_FPCR 5
+#define DC_NUM_AUX 6
+
+
+typedef void *dc_dcontext_t;
+
+extern dc_dcontext_t dc_make_dcontext _ARGS((
+ dc_handle_t handle,
+ dc_word_t reg_info[DC_NUM_REG],
+ dc_word_t reg_flags[2],
+ dc_word_t aux_info[DC_NUM_AUX],
+ dc_word_t aux_flags[2],
+ dc_exactness_t loc_exact,
+ dc_word_t psr_info,
+ dc_boolean_t psr_ind,
+ dc_word_t psr_flags[2]
+));
+extern void dc_free_dcontext _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_register_state_t dc_location_state _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_exactness_t dc_location_exactness _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_word_t dc_location _ARGS((
+ dc_dcontext_t dcontext
+));
+extern void dc_set_location _ARGS((
+ dc_dcontext_t dcontext,
+ dc_word_t value
+));
+extern dc_register_state_t dc_general_register_state _ARGS((
+ dc_dcontext_t dcontext,
+ int reg
+));
+extern dc_word_t dc_general_register _ARGS((
+ dc_dcontext_t dcontext,
+ int reg
+));
+extern void dc_set_general_register _ARGS((
+ dc_dcontext_t dcontext,
+ int reg,
+ dc_word_t value
+));
+extern dc_register_state_t dc_auxiliary_register_state _ARGS((
+ dc_dcontext_t dcontext,
+ int reg
+));
+extern dc_word_t dc_auxiliary_register _ARGS((
+ dc_dcontext_t dcontext,
+ int reg
+));
+extern void dc_set_auxiliary_register _ARGS((
+ dc_dcontext_t dcontext,
+ int reg,
+ dc_word_t value
+));
+extern dc_register_state_t dc_psr_register_bit_state _ARGS((
+ dc_dcontext_t dcontext,
+ int bit
+));
+extern dc_word_t dc_psr_register _ARGS((
+ dc_dcontext_t dcontext
+));
+extern void dc_set_psr_register _ARGS((
+ dc_dcontext_t dcontext,
+ dc_word_t mask,
+ dc_word_t value
+));
+extern dc_word_t dc_frame_address _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_kind_t dc_context_kind _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_register_state_t dc_return_address_state _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_exactness_t dc_return_address_exactness _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_word_t dc_return_address _ARGS((
+ dc_dcontext_t dcontext
+));
+extern void dc_set_return_address _ARGS((
+ dc_dcontext_t dcontext,
+ dc_word_t value
+));
+extern void dc_get_exception_info();
+extern void dc_get_protection_info();
+extern void dc_get_special_info();
+extern dc_dcontext_t dc_previous_dcontext _ARGS((
+ dc_dcontext_t dcontext
+));
+extern dc_boolean_t dc_location_in_text_chunk _ARGS((
+ dc_dcontext_t dcontext,
+ dc_word_t value
+));
+
+#endif
--- /dev/null
+/* Parameters for target machine of AMD 29000, for GDB, the GNU debugger.
+ Copyright 1990, 1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Parameters for an EB29K (a board which plugs into a PC and is
+ accessed through EBMON software running on the PC, which we
+ use as we'd use a remote stub (see remote-eb.c).
+
+ If gdb is ported to other 29k machines/systems, the
+ machine/system-specific parts should be removed from this file (a
+ la tm-68k.h). */
+
+/* Byte order is configurable, but this machine runs big-endian. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Floating point uses IEEE representations. */
+#define IEEE_FLOAT
+
+/* We can either use a.out, encapsulated, or can use COFF */
+#ifndef COFF_ENCAPSULATE
+#define COFF_FORMAT
+/* This just has to do with what coff header files are in use. */
+#define COFF_CHECK_X_ZEROES
+#endif
+
+/* Recognize our magic number. */
+#define BADMAG(x) ((x)->f_magic != 0572)
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+ { pc = skip_prologue (pc); }
+CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_register (LR0_REGNUM))
+
+/* I'm not sure about the exact value of this, but based on looking
+ at the stack pointer when we get to main this seems to be right.
+
+ This is the register stack; We call it "CONTROL" in GDB for consistency
+ with Pyramid. */
+#define CONTROL_END_ADDR 0x80200000
+
+/* Memory stack. This is for the default register stack size, which is
+ only 0x800 bytes. Perhaps we should let the user specify stack sizes
+ (and tell EBMON with the "ZS" command). */
+#define STACK_END_ADDR 0x801ff800
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Stack must be aligned on 32-bit word boundaries. */
+#define STACK_ALIGN(ADDR) (((ADDR) + 3) & ~3)
+
+/* Sequence of bytes for breakpoint instruction. */
+/* ASNEQ 0x50, gr1, gr1
+ The trap number 0x50 is chosen arbitrarily. */
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BREAKPOINT {0x72, 0x50, 0x01, 0x01}
+#else /* Target is little-endian. */
+#define BREAKPOINT {0x01, 0x01, 0x50, 0x72}
+#endif /* Target is little-endian. */
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 4
+
+/* Nonzero if instruction at PC is a return instruction.
+ On the 29k, this is a "jmpi l0" instruction. */
+
+#define ABOUT_TO_RETURN(pc) \
+ ((read_memory_integer (pc, 4) & 0xff0000ff) == 0xc0000080)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 205
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer.
+
+ FIXME, add floating point registers and support here.
+
+ Also note that this list does not attempt to deal with kernel
+ debugging (in which the first 32 registers are gr64-gr95). */
+
+#define REGISTER_NAMES \
+{"gr96", "gr97", "gr98", "gr99", "gr100", "gr101", "gr102", "gr103", "gr104", \
+ "gr105", "gr106", "gr107", "gr108", "gr109", "gr110", "gr111", "gr112", \
+ "gr113", "gr114", "gr115", "gr116", "gr117", "gr118", "gr119", "gr120", \
+ "gr121", "gr122", "gr123", "gr124", "gr125", "gr126", "gr127", \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9", \
+ "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", "lr16", "lr17", "lr18", \
+ "lr19", "lr20", "lr21", "lr22", "lr23", "lr24", "lr25", "lr26", "lr27", \
+ "lr28", "lr29", "lr30", "lr31", "lr32", "lr33", "lr34", "lr35", "lr36", \
+ "lr37", "lr38", "lr39", "lr40", "lr41", "lr42", "lr43", "lr44", "lr45", \
+ "lr46", "lr47", "lr48", "lr49", "lr50", "lr51", "lr52", "lr53", "lr54", \
+ "lr55", "lr56", "lr57", "lr58", "lr59", "lr60", "lr61", "lr62", "lr63", \
+ "lr64", "lr65", "lr66", "lr67", "lr68", "lr69", "lr70", "lr71", "lr72", \
+ "lr73", "lr74", "lr75", "lr76", "lr77", "lr78", "lr79", "lr80", "lr81", \
+ "lr82", "lr83", "lr84", "lr85", "lr86", "lr87", "lr88", "lr89", "lr90", \
+ "lr91", "lr92", "lr93", "lr94", "lr95", "lr96", "lr97", "lr98", "lr99", \
+ "lr100", "lr101", "lr102", "lr103", "lr104", "lr105", "lr106", "lr107", \
+ "lr108", "lr109", "lr110", "lr111", "lr112", "lr113", "lr114", "lr115", \
+ "lr116", "lr117", "lr118", "lr119", "lr120", "lr121", "lr122", "lr123", \
+ "lr124", "lr125", "lr126", "lr127", \
+ "AI0", "AI1", "AI2", "AI3", "AI4", "AI5", "AI6", "AI7", "AI8", "AI9", \
+ "AI10", "AI11", "AI12", "AI13", "AI14", "AI15", "FP", \
+ "bp", "fc", "cr", "q", \
+ "vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", \
+ "pc0", "pc1", "pc2", "mmu", "lru", "fpe", "int", "fps", "exo", "gr1", \
+ "alu", "ipc", "ipa", "ipb" }
+
+/* Special register #x. */
+#define SR_REGNUM(x) \
+ ((x) < 15 ? VAB_REGNUM + (x) \
+ : (x) >= 128 && (x) < 131 ? IPC_REGNUM + (x) \
+ : (x) == 131 ? Q_REGNUM \
+ : (x) == 132 ? ALU_REGNUM \
+ : (x) >= 133 && (x) < 136 ? BP_REGNUM + (x) \
+ : (x) >= 160 && (x) < 163 ? FPE_REGNUM + (x) \
+ : (x) == 164 ? EXO_REGNUM \
+ : (error ("Internal error in SR_REGNUM"), 0))
+#define GR96_REGNUM 0
+#define GR1_REGNUM 200
+/* This needs to be the memory stack pointer, not the register stack pointer,
+ to make call_function work right. */
+#define SP_REGNUM MSP_REGNUM
+#define FP_REGNUM 33 /* lr1 */
+/* Large Return Pointer (gr123). */
+#define LRP_REGNUM (123 - 96 + GR96_REGNUM)
+/* Static link pointer (gr124). */
+#define SLP_REGNUM (124 - 96 + GR96_REGNUM)
+/* Memory Stack Pointer (gr125). */
+#define MSP_REGNUM (125 - 96 + GR96_REGNUM)
+/* Register allocate bound (gr126). */
+#define RAB_REGNUM (126 - 96 + GR96_REGNUM)
+/* Register Free Bound (gr127). */
+#define RFB_REGNUM (127 - 96 + GR96_REGNUM)
+/* Register Stack Pointer. */
+#define RSP_REGNUM GR1_REGNUM
+#define LR0_REGNUM 32
+#define PC_REGNUM 192 /* pc1 */
+#define NPC_REGNUM 191 /* pc0 */
+#define PC2_REGNUM 193
+#define BP_REGNUM 177
+#define FC_REGNUM 178
+#define CR_REGNUM 179
+#define Q_REGNUM 180
+#define VAB_REGNUM 181
+#define LRU_REGNUM 195
+#define FPE_REGNUM 196
+#define INT_REGNUM 197
+#define FPS_REGNUM 198
+#define EXO_REGNUM 199
+#define PS_REGNUM 201
+#define ALU_REGNUM 201
+#define IPC_REGNUM 202
+#define IPB_REGNUM 204
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+/* All regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+/* All regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE (4)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE (4)
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) == PC_REGNUM || (N) == LRP_REGNUM || (N) == SLP_REGNUM \
+ || (N) == MSP_REGNUM || (N) == RAB_REGNUM || (N) == RFB_REGNUM \
+ || (N) == GR1_REGNUM || (N) == FP_REGNUM || (N) == LR0_REGNUM \
+ || (N) == NPC_REGNUM || (N) == PC2_REGNUM) \
+ ? lookup_pointer_type (builtin_type_void) : builtin_type_int)
+\f
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+/* On the 29k the LRP points to the part of the structure beyond the first
+ 16 words. */
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ write_register (LRP_REGNUM, (ADDR) + 16 * 4);
+
+/* Should call_function allocate stack space for a struct return? */
+/* On the 29k objects over 16 words require the caller to allocate space. */
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 16 * 4)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ { \
+ int reg_length = TYPE_LENGTH (TYPE); \
+ if (reg_length > 16 * 4) \
+ { \
+ reg_length = 16 * 4; \
+ read_memory (*((int *)(REGBUF) + LRP_REGNUM), (VALBUF) + 16 * 4, \
+ TYPE_LENGTH (TYPE) - 16 * 4); \
+ } \
+ bcopy (((int *)(REGBUF))+GR96_REGNUM, (VALBUF), reg_length); \
+ }
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { \
+ int reg_length = TYPE_LENGTH (TYPE); \
+ if (reg_length > 16 * 4) \
+ { \
+ reg_length = 16 * 4; \
+ write_memory (read_register (LRP_REGNUM), \
+ (char *)(VALBUF) + 16 * 4, \
+ TYPE_LENGTH (TYPE) - 16 * 4); \
+ } \
+ write_register_bytes (REGISTER_BYTE (GR96_REGNUM), (char *)(VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ }
+\f
+/* The am29k user's guide documents well what the stacks look like.
+ But what isn't so clear there is how this interracts with the
+ symbols, or with GDB.
+ In the following saved_msp, saved memory stack pointer (which functions
+ as a memory frame pointer), means either
+ a register containing the memory frame pointer or, in the case of
+ functions with fixed size memory frames (i.e. those who don't use
+ alloca()), the result of the calculation msp + msize.
+
+ LOC_ARG, LOC_LOCAL - For GCC, these are relative to saved_msp.
+ For high C, these are relative to msp (making alloca impossible).
+ LOC_REGISTER, LOC_REGPARM - The register number is the number at the
+ time the function is running (after the prologue), or in the case
+ of LOC_REGPARM, may be a register number in the range 160-175.
+
+ The compilers do things like store an argument into memory, and then put out
+ a LOC_ARG for it, or put it into global registers and put out a
+ LOC_REGPARM. Thus is it important to execute the first line of
+ code (i.e. the line of the open brace, i.e. the prologue) of a function
+ before trying to print arguments or anything.
+
+ The following diagram attempts to depict what is going on in memory
+ (see also the _am29k user's guide_) and also how that interacts with
+ GDB frames. We arbitrarily pick fci->frame to point the same place
+ as the register stack pointer; since we set it ourself in
+ INIT_EXTRA_FRAME_INFO, and access it only through the FRAME_*
+ macros, it doesn't really matter exactly how we
+ do it. However, note that FRAME_FP is used in two ways in GDB:
+ (1) as a "magic cookie" which uniquely identifies frames (even over
+ calls to the inferior), (2) (in PC_IN_CALL_DUMMY [!CANNOT_EXECUTE_STACK])
+ as the value of SP_REGNUM before the dummy frame was pushed. These
+ two meanings would be incompatible for the 29k if we didn't define
+ CANNOT_EXECUTE_STACK (but we do, so don't worry about it).
+ Also note that "lr1" below, while called a frame pointer
+ in the user's guide, has only one function: To determine whether
+ registers need to be filled in the function epilogue.
+
+ Consider the code:
+ < call bar>
+ loc1: . . .
+ bar: sub gr1,gr1,rsize_b
+ . . .
+ add mfp,msp,0
+ sub msp,msp,msize_b
+ . . .
+ < call foo >
+ loc2: . . .
+ foo: sub gr1,gr1,rsize_f
+ . . .
+ add mfp,msp,0
+ sub msp,msp,msize_f
+ . . .
+ loc3: < suppose the inferior stops here >
+
+ memory stack register stack
+ | | |____________|
+ | | |____loc1____|
+ +------->|___________| | | ^
+ | | ^ | | locals_b | |
+ | | | | |____________| |
+ | | | | | | | rsize_b
+ | | | msize_b | | args_to_f | |
+ | | | | |____________| |
+ | | | | |____lr1_____| V
+ | | V | |____loc2____|<----------------+
+ | +--->|___________|<---------mfp | ^ |
+ | | | ^ | | locals_f | | |
+ | | | | msize_f | |____________| | |
+ | | | | | | | | rsize_f |
+ | | | V | | args | | |
+ | | |___________|<msp |____________| | |
+ | | |_____lr1____| V |
+ | | |___garbage__| <- gr1 <----+ |
+ | | | |
+ | | | |
+ | | pc=loc3 | |
+ | | | |
+ | | | |
+ | | frame cache | |
+ | | |_________________| | |
+ | | |rsize=rsize_b | | |
+ | | |msize=msize_b | | |
+ +---|--------saved_msp | | |
+ | |frame------------------------------------|---+
+ | |pc=loc2 | |
+ | |_________________| |
+ | |rsize=rsize_f | |
+ | |msize=msize_f | |
+ +--------saved_msp | |
+ |frame------------------------------------+
+ |pc=loc3 |
+ |_________________|
+
+ So, is that sufficiently confusing? Welcome to the 29000.
+ Notes:
+ * The frame for foo uses a memory frame pointer but the frame for
+ bar does not. In the latter case the saved_msp is
+ computed by adding msize to the saved_msp of the
+ next frame.
+ * msize is in the frame cache only for high C's sake. */
+
+void read_register_stack ();
+long read_register_stack_integer ();
+\f
+#define EXTRA_FRAME_INFO \
+ CORE_ADDR saved_msp; \
+ unsigned int rsize; \
+ unsigned int msize;
+
+/* Because INIT_FRAME_PC gets passed fromleaf, that's where we init
+ not only ->pc and ->frame, but all the extra stuff, when called from
+ get_prev_frame_info, that is. */
+#define INIT_EXTRA_FRAME_INFO(fci) \
+ init_extra_frame_info(fci);
+void init_extra_frame_info ();
+#define INIT_FRAME_PC(fromleaf, fci) \
+ init_frame_pc(fromleaf, fci);
+void init_frame_pc ();
+\f
+/* FRAME_CHAIN takes a FRAME
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* On the 29k, the nominal address of a frame is the address on the
+ register stack of the return address (the one next to the incoming
+ arguments, not down at the bottom so nominal address == stack pointer).
+
+ GDB expects "nominal address" to equal contents of FP_REGNUM,
+ at least when it comes time to create the innermost frame.
+ However, that doesn't work for us, so when creating the innermost
+ frame we set ->frame ourselves in INIT_EXTRA_FRAME_INFO. */
+
+/* These are mostly dummies for the 29k because INIT_FRAME_PC
+ sets prev->frame instead. */
+#define FRAME_CHAIN(thisframe) (0)
+
+/* Not sure how to figure out where the bottom frame is. There is
+ no frame for start. In my tests so far the
+ pc has been outside the text segment, though, so check for that.
+ However, allow a pc in a call dummy. */
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (outside_startup_file (FRAME_SAVED_PC (thisframe)) \
+ && FRAME_SAVED_PC (thisframe) >= text_start \
+ && FRAME_SAVED_PC (thisframe) < text_end + CALL_DUMMY_LENGTH)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (0)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* Saved pc (i.e. return address). */
+#define FRAME_SAVED_PC(fraim) \
+ (read_register_stack_integer ((fraim)->frame + (fraim)->rsize, 4))
+
+/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
+ offsets being relative to the memory stack pointer (high C) or
+ saved_msp (gcc). */
+
+#define FRAME_LOCALS_ADDRESS(fi) frame_locals_address (fi)
+extern CORE_ADDR frame_locals_address ();
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+/* While we could go the effort of finding the tags word and getting
+ the argcount field from it,
+ (1) It only counts arguments in registers, i.e. the first 16 words
+ of arguments
+ (2) It gives the number of arguments the function was declared with
+ not how many it was called with (or some variation, like all 16
+ words for varadic functions). This makes argcount pretty much
+ redundant with -g info, even for varadic functions.
+ So don't bother. */
+#define FRAME_NUM_ARGS(numargs, fi) ((numargs) = -1)
+
+#define FRAME_ARGS_ADDRESS(fi) FRAME_LOCALS_ADDRESS (fi)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Provide our own get_saved_register. HAVE_REGISTER_WINDOWS is insufficient
+ because registers get renumbered on the 29k without getting saved. */
+
+#define GET_SAVED_REGISTER
+\f
+/* Call function stuff. */
+
+/* The dummy frame looks like this (see also the general frame picture
+ above):
+
+ register stack
+
+ | | frame for function
+ | locals_sproc | executing at time
+ |________________| of call_function.
+ | | We must not disturb
+ | args_out_sproc | it.
+ memory stack |________________|
+ |____lr1_sproc___|
+ | | |__retaddr_sproc_| <- gr1 (at start)
+ |____________|<-msp 0 <-----------mfp_dummy_____|
+ | | (at start) | |
+ | arg_slop | | saved regs |
+ | (16 words) | | gr96-gr124 |
+ |____________|<-msp 1--after | sr128-sr135 |
+ | | PUSH_DUMMY_FRAME| |
+ | struct ret | |________________|
+ | 17+ | | |
+ |____________|<- lrp | args_out_dummy |
+ | struct ret | | (16 words) |
+ | 16 | |________________|
+ | (16 words) | |____lr1_dummy___|
+ |____________|<- msp 2--after |_retaddr_dummy__|<- gr1 after
+ | | struct ret | | PUSH_DUMMY_FRAME
+ | margs17+ | area allocated | locals_inf |
+ | | |________________| called
+ |____________|<- msp 4--when | | function's
+ | | inf called | args_out_inf | frame (set up
+ | margs16 | |________________| by called
+ | (16 words) | |_____lr1_inf____| function).
+ |____________|<- msp 3--after | . |
+ | | args pushed | . |
+ | | | . |
+ | |
+
+ arg_slop: This area is so that when the call dummy adds 16 words to
+ the msp, it won't end up larger than mfp_dummy (it is needed in the
+ case where margs and struct_ret do not add up to at least 16 words).
+ struct ret: This area is allocated by GDB if the return value is more
+ than 16 words. struct ret_16 is not used on the 29k.
+ margs: Pushed by GDB. The call dummy copies the first 16 words to
+ args_out_dummy.
+ retaddr_sproc: Contains the PC at the time we call the function.
+ set by PUSH_DUMMY_FRAME and read by POP_FRAME.
+ retaddr_dummy: This points to a breakpoint instruction in the dummy. */
+\f
+/* Rsize for dummy frame, in bytes. */
+
+/* Bytes for outgoing args, lr1, and retaddr. */
+#define DUMMY_ARG (2 * 4 + 16 * 4)
+
+/* Number of special registers (sr128-) to save. */
+#define DUMMY_SAVE_SR128 8
+/* Number of general (gr96-) registers to save. */
+#define DUMMY_SAVE_GR96 29
+
+#define DUMMY_FRAME_RSIZE \
+(4 /* mfp_dummy */ \
+ + DUMMY_SAVE_GR96 * 4 \
+ + DUMMY_SAVE_SR128 * 4 \
+ + DUMMY_ARG \
+ )
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME push_dummy_frame();
+extern void push_dummy_frame ();
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME pop_frame ();
+extern void pop_frame ();
+
+/* This sequence of words is the instructions
+ mtsrim cr, 15
+ loadm 0, 0, lr2, msp ; load first 16 words of arguments into registers
+ add msp, msp, 16 * 4 ; point to the remaining arguments
+ CONST_INSN:
+ const gr96,inf
+ consth gr96,inf
+ calli lr0, gr96
+ aseq 0x40,gr1,gr1 ; nop
+ asneq 0x50,gr1,gr1 ; breakpoint
+ */
+
+/* Position of the "const" instruction within CALL_DUMMY in bytes. */
+#define CONST_INSN (3 * 4)
+#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
+#define CALL_DUMMY {0x0400870f, 0x3600827d, 0x157d7d40, 0x03ff60ff, \
+ 0x02ff60ff, 0xc8008060, 0x70400101, 0x72500101}
+#else /* Byte order differs. */
+ you lose
+#endif /* Byte order differs. */
+#define CALL_DUMMY_LENGTH (8 * 4)
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Helper macro for FIX_CALL_DUMMY. WORDP is a long * which points to a
+ word in target byte order; bits 0-7 and 16-23 of *WORDP are replaced with
+ bits 0-7 and 8-15 of DATA (which is in host byte order). */
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define STUFF_I16(WORDP, DATA) \
+ { \
+ *((char *)(WORDP) + 3) = ((DATA) & 0xff);\
+ *((char *)(WORDP) + 1) = (((DATA) >> 8) & 0xff);\
+ }
+#else /* Target is little endian. */
+#define STUFF_I16(WORDP, DATA) \
+ {
+ *(char *)(WORDP) = ((DATA) & 0xff);
+ *((char *)(WORDP) + 2) = (((DATA) >> 8) & 0xff);
+ }
+#endif /* Target is little endian. */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+/* Currently this stuffs in the address of the function that we are calling.
+ If different 29k systems use different breakpoint instructions, it
+ could also stuff BREAKPOINT in the right place (to avoid having to
+ duplicate CALL_DUMMY in each tm-*.h file). */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+ {\
+ STUFF_I16((char *)dummyname + CONST_INSN, fun);\
+ STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16);\
+ }
+
+/* At least our 29k board has separate data & instruction memories and can't
+ execute the data memory. Also, there should be space after text_end;
+ we won't get a SIGSEGV or scribble on data space. */
+
+#define CALL_DUMMY_LOCATION AFTER_TEXT_END
+
+/* How to translate register numbers in the .stab's into gdb's internal register
+ numbers. We don't translate them, but we warn if an invalid register
+ number is seen. Note that FIXME, we use the value "sym" as an implicit
+ argument in printing the error message. It happens to be available where
+ this macro is used. (This macro definition appeared in a late revision
+ of gdb-3.91.6 and is not well tested. Also, it should be a "complaint".) */
+
+#define STAB_REG_TO_REGNUM(num) \
+ (((num) > LR0_REGNUM + 127) \
+ ? fprintf(stderr, \
+ "Invalid register number %d in symbol table entry for %s\n", \
+ (num), SYMBOL_NAME (sym)), (num) \
+ : (num))
--- /dev/null
+/* Parameters for targeting to a 3b1.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define BREAKPOINT { 0x4e, 0x41 }
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in COFF format. */
+
+#define COFF_FORMAT
+#define COFF_NO_LONG_FILE_NAMES
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0x300000
+
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ moveml 0xfffc,-(sp)
+ clrw -(sp)
+ movew ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jsr @#32323232
+ addl #69696969,sp
+ bpt
+ nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 24
+
+#define CALL_DUMMY_START_OFFSET 8
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \
+{ *(int *)((char *) dummyname + 16) = nargs * 4; \
+ *(int *)((char *) dummyname + 10) = fun; }
+\f
+#include "tm-68k.h"
--- /dev/null
+/* Parameters for execution on a 68000 series machine.
+ Copyright (C) 1986, 1987, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Generic 68000 stuff, to be included by other m-*.h files.
+ Define HAVE_68881 if that is the case. */
+
+#if defined (HAVE_68881)
+#define IEEE_FLOAT 1
+#endif
+
+/* Define the bit, byte, and word ordering of the machine. */
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = read_memory_integer (pc, 2); \
+ if (op == 0047126) \
+ pc += 4; /* Skip link #word */ \
+ else if (op == 0044016) \
+ pc += 6; /* Skip link #long */ \
+ /* Not sure why branches are here. */ \
+ /* From m-isi.h, m-altos.h */ \
+ else if (op == 0060000) \
+ pc += 4; /* Skip bra #word */ \
+ else if (op == 00600377) \
+ pc += 6; /* skip bra #long */ \
+ else if ((op & 0177400) == 0060000) \
+ pc += 2; /* skip bra #char */ \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.
+ This is a TRAP instruction. The last 4 bits (0xf below) is the
+ vector. Systems which don't use 0xf should define BREAKPOINT
+ themselves before including this file. */
+
+#if !defined (BREAKPOINT)
+#define BREAKPOINT {0x4e, 0x4f}
+#endif
+
+/* If your kernel resets the pc after the trap happens you may need to
+ define this in m-68k.h. */
+
+#if !defined (DECR_PC_AFTER_BREAK)
+#define DECR_PC_AFTER_BREAK 2
+#endif
+
+/* Nonzero if instruction at PC is a return instruction. */
+/* Allow any of the return instructions, including a trapv and a return
+ from interupt. */
+
+#define ABOUT_TO_RETURN(pc) ((read_memory_integer (pc, 2) & ~0x3) == 0x4e74)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
+
+/* Say how long registers are. */
+
+#define REGISTER_TYPE long
+
+#if defined (HAVE_68881)
+# if defined (sun)
+ /* Sun3 status includes fpflags, which shows whether the FPU has been used
+ by the process, and whether the FPU was done with an instruction or
+ was interrupted in the middle of a long instruction. See
+ <machine/reg.h>. */
+ /* a&d, pc,sr, fp, fpstat, fpflags */
+# define NUM_REGS 31
+# define REGISTER_BYTES (16*4 + 8 + 8*12 + 3*4 + 4)
+# else /* Not sun3. */
+# define NUM_REGS 29
+# define REGISTER_BYTES (16*4 + 8 + 8*12 + 3*4)
+# endif /* Not sun3. */
+#else /* No 68881. */
+# define NUM_REGS 18
+# define REGISTER_BYTES (16*4 + 8)
+#endif /* No 68881. */
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#if defined (HAVE_68881)
+#define REGISTER_BYTE(N) \
+ ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \
+ : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \
+ : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the 68000, all regs are 4 bytes
+ except the floating point regs which are 12 bytes. */
+/* Note that the unsigned cast here forces the result of the
+ subtraction to very high positive values if N < FP0_REGNUM */
+
+#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the 68000, all regs are 4 bytes
+ except the floating point regs which are 8-byte doubles. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 12
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ \
+ extern struct ext_format ext_format_68881 []; \
+ \
+ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+ ieee_extended_to_double (ext_format_68881, (FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4); \
+}
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+{ \
+ extern struct ext_format ext_format_68881 []; \
+ \
+ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+ double_to_ieee_extended (ext_format_68881, (FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+/* Note, for registers which contain addresses return
+ pointer to void, not pointer to char, because we don't
+ want to attempt to print the string after printing the address. */
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)(N) - FP0_REGNUM) < 8 ? builtin_type_double : \
+ (N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM ? \
+ lookup_pointer_type (builtin_type_void) : builtin_type_int)
+
+#else /* no 68881. */
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the 68000, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the 68000, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+#endif /* No 68881. */
+
+/* Initializer for an array of names of registers.
+ Entries beyond the first NUM_REGS are ignored. */
+
+#define REGISTER_NAMES \
+ {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
+ "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", \
+ "ps", "pc", \
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", \
+ "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define A1_REGNUM 9
+#define FP_REGNUM 14 /* Contains address of executing stack frame */
+#define SP_REGNUM 15 /* Contains address of top of stack */
+#define PS_REGNUM 16 /* Contains processor status */
+#define PC_REGNUM 17 /* Contains program counter */
+#if defined (HAVE_68881)
+#define FP0_REGNUM 18 /* Floating point register 0 */
+#define FPC_REGNUM 26 /* 68881 control register */
+#define FPS_REGNUM 27 /* 68881 status register */
+#endif /* 68881. */
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (A1_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. This is assuming that floating point values are returned
+ as doubles in d0/d1. */
+
+#if !defined (EXTRACT_RETURN_VALUE)
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+#endif
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. Assumes floats are passed
+ in d0/d1. */
+
+#if !defined (STORE_RETURN_VALUE)
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+#endif
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the 68000, the frame's nominal address
+ is the address of a 4-byte word containing the calling frame's address. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && outside_startup_file (FRAME_SAVED_PC (thisframe)))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+#if !defined (FRAME_NUM_ARGS)
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+#endif
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#if !defined (FRAME_FIND_SAVED_REGS)
+#if defined (HAVE_68881)
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int regmask; \
+ register CORE_ADDR next_addr; \
+ register CORE_ADDR pc; \
+ int nextinsn; \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
+ && (frame_info)->pc <= (frame_info)->frame) \
+ { next_addr = (frame_info)->frame; \
+ pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
+ else \
+ { pc = get_pc_function_start ((frame_info)->pc); \
+ /* Verify we have a link a6 instruction next; \
+ if not we lose. If we win, find the address above the saved \
+ regs using the amount of storage from the link instruction. */\
+ if (044016 == read_memory_integer (pc, 2)) \
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \
+ else if (047126 == read_memory_integer (pc, 2)) \
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \
+ else goto lose; \
+ /* If have an addal #-n, sp next, adjust next_addr. */ \
+ if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
+ next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
+ } \
+ /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
+ regmask = read_memory_integer (pc + 2, 2); \
+ /* But before that can come an fmovem. Check for it. */ \
+ nextinsn = 0xffff & read_memory_integer (pc, 2); \
+ if (0xf227 == nextinsn \
+ && (regmask & 0xff00) == 0xe000) \
+ { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */ \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr -= 12); \
+ regmask = read_memory_integer (pc + 2, 2); } \
+ if (0044327 == read_memory_integer (pc, 2)) \
+ { pc += 4; /* Regmask's low bit is for register 0, the first written */ \
+ for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
+ else if (0044347 == read_memory_integer (pc, 2)) \
+ { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
+ for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
+ else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2))) \
+ { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
+ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
+ /* fmovemx to index of sp may follow. */ \
+ regmask = read_memory_integer (pc + 2, 2); \
+ nextinsn = 0xffff & read_memory_integer (pc, 2); \
+ if (0xf236 == nextinsn \
+ && (regmask & 0xff00) == 0xf000) \
+ { pc += 10; /* Regmask's low bit is for register fp0, the first written */ \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 12) - 12; \
+ regmask = read_memory_integer (pc + 2, 2); } \
+ /* clrw -(sp); movw ccr,-(sp) may follow. */ \
+ if (0x426742e7 == read_memory_integer (pc, 4)) \
+ (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
+ lose: ; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
+}
+#else /* no 68881. */
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int regmask; \
+ register CORE_ADDR next_addr; \
+ register CORE_ADDR pc; \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 \
+ && (frame_info)->pc <= (frame_info)->frame) \
+ { next_addr = (frame_info)->frame; \
+ pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4; }\
+ else \
+ { pc = get_pc_function_start ((frame_info)->pc); \
+ /* Verify we have a link a6 instruction next; \
+ if not we lose. If we win, find the address above the saved \
+ regs using the amount of storage from the link instruction. */\
+ if (044016 == read_memory_integer (pc, 2)) \
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4; \
+ else if (047126 == read_memory_integer (pc, 2)) \
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2; \
+ else goto lose; \
+ /* If have an addal #-n, sp next, adjust next_addr. */ \
+ if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
+ next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
+ } \
+ /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
+ regmask = read_memory_integer (pc + 2, 2); \
+ if (0044327 == read_memory_integer (pc, 2)) \
+ { pc += 4; /* Regmask's low bit is for register 0, the first written */ \
+ for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 4) - 4; } \
+ else if (0044347 == read_memory_integer (pc, 2)) \
+ { pc += 4; /* Regmask's low bit is for register 15, the first pushed */ \
+ for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
+ else if (0x2f00 == 0xfff0 & read_memory_integer (pc, 2)) \
+ { regnum = 0xf & read_memory_integer (pc, 2); pc += 2; \
+ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
+ /* clrw -(sp); movw ccr,-(sp) may follow. */ \
+ if (0x426742e7 == read_memory_integer (pc, 4)) \
+ (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
+ lose: ; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
+}
+#endif /* no 68881. */
+#endif /* no FIND_FRAME_SAVED_REGS. */
+
+/* Note that stuff for calling inferior functions is not in this file
+ because the call dummy is different for different breakpoint
+ instructions, which are different on different systems. Perhaps
+ they could be merged, but I haven't bothered. */
--- /dev/null
+/* Definitions to make GDB run on an Altos 3068 (m68k running SVR2)
+ Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x4e, 0x4e}
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#undef NAMES_HAVE_UNDERSCORE
+
+/* Exec files and symbol tables are in COFF format */
+
+#define COFF_FORMAT
+#define COFF_NO_LONG_FILE_NAMES
+
+/* Address of end of stack space. */
+
+/*#define STACK_END_ADDR (0xffffff)*/
+#define STACK_END_ADDR (0x1000000)
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always.
+ On the Altos, the kernel resets the pc to the trap instr */
+
+#define DECR_PC_AFTER_BREAK 0
+
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char raw_buffer[12]; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
+ sp = push_bytes (sp, raw_buffer, 12); } \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ char raw_buffer[12]; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ if (fsr.regs[regnum]) \
+ { read_memory (fsr.regs[regnum], raw_buffer, 12); \
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM), \
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ fmovem 0xff,-(sp)
+ moveml 0xfffc,-(sp)
+ clrw -(sp)
+ movew ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jsr @#32323232
+ addl #69696969,sp
+ bpt
+ nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4e4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 20) = nargs * 4; \
+ *(int *)((char *) dummyname + 14) = fun; }
+\f
+#include "tm-68k.h"
--- /dev/null
+/* Definitions to make GDB run on an Altos 3068 using COFF encapsulation.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define COFF_ENCAPSULATE
+
+#include "m-altos.h"
+
+#undef COFF_FORMAT
+#undef COFF_NO_LONG_FILE_NAMES
+#define NAMES_HAVE_UNDERSCORE
+
+#define READ_DBX_FORMAT
--- /dev/null
+/* Definitions to make GDB target for an ARM under RISCiX (4.3bsd).
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* IEEE format floating point */
+
+#define IEEE_FLOAT
+
+/* I provide my own xfer_core_file to cope with shared libraries */
+
+#define XFER_CORE_FILE
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) pc = skip_prologue(pc)
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_register (LR_REGNUM) & 0x03fffffc)
+
+/* I don't know the real values for these. */
+#define TARGET_UPAGES UPAGES
+#define TARGET_NBPG NBPG
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0x01000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x00,0x00,0x18,0xef} /* BKPT_SWI from <sys/ptrace.h> */
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) \
+ ((read_memory_integer(pc, 4) & 0x0fffffff == 0x01b0f00e) || \
+ (read_memory_integer(pc, 4) & 0x0ffff800 == 0x09eba800))
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes. */
+
+#define INVALID_FLOAT(p, len) 0
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { arm_float_info (); }
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+/* Note: I make a fake copy of the pc in register 25 (calling it ps) so
+ that I can clear the status bits from pc (register 15) */
+
+#define NUM_REGS 26
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+ { "a1", "a2", "a3", "a4", \
+ "v1", "v2", "v3", "v4", "v5", "v6", \
+ "sl", "fp", "ip", "sp", "lr", "pc", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "fps", "ps" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define AP_REGNUM 11
+#define FP_REGNUM 11 /* Contains address of executing stack frame */
+#define SP_REGNUM 13 /* Contains address of top of stack */
+#define LR_REGNUM 14 /* address to return to from a function call */
+#define PC_REGNUM 15 /* Contains program counter */
+#define F0_REGNUM 16 /* first floating point register */
+#define FPS_REGNUM 24 /* floating point status register */
+#define PS_REGNUM 25 /* Contains processor status */
+
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (16*4 + 12*8 + 4 + 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) (((N) < F0_REGNUM) ? (N)*4 : \
+ (((N) < PS_REGNUM) ? 16*4 + ((N) - 16)*12 : \
+ 16*4 + 8*12 + ((N) - FPS_REGNUM) * 4))
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 12)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < F0_REGNUM || (N) >= FPS_REGNUM) ? 4 : 8)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 12
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) ((unsigned)(N) - F0_REGNUM < 8)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ if (REGISTER_CONVERTIBLE(REGNUM)) \
+ convert_from_extended((FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ if (REGISTER_CONVERTIBLE(REGNUM)) \
+ convert_to_extended((FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)(N) - F0_REGNUM) < 8 ? builtin_type_double : builtin_type_int)
+\f
+/* The system C compiler uses a similar structure return convention to gcc */
+
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 4)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (0, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ convert_from_extended(REGBUF + REGISTER_BYTE (F0_REGNUM), VALBUF); \
+ else \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) { \
+ char _buf[MAX_REGISTER_RAW_SIZE]; \
+ convert_to_extended(VALBUF, _buf); \
+ write_register_bytes (REGISTER_BYTE (F0_REGNUM), _buf, MAX_REGISTER_RAW_SIZE); \
+ } else \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* Specify that for the native compiler variables for a particular
+ lexical context are listed after the beginning LBRAC instead of
+ before in the executables list of symbols. */
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (!(gcc_p))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the ARM, the frame's nominal address is the FP value,
+ and 12 bytes before comes the saved previous FP value as a 4-byte word. */
+
+#define FRAME_CHAIN(thisframe) \
+ ((thisframe)->pc >= first_object_file_end ? \
+ read_memory_integer ((thisframe)->frame - 12, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ \
+ CORE_ADDR func_start, after_prologue; \
+ func_start = (get_pc_function_start ((FI)->pc) + \
+ FUNCTION_START_OFFSET); \
+ after_prologue = func_start; \
+ SKIP_PROLOGUE (after_prologue); \
+ (FRAMELESS) = (after_prologue == func_start); \
+}
+
+/* Saved Pc. */
+
+#define FRAME_SAVED_PC(FRAME) \
+ (read_memory_integer ((FRAME)->frame - 4, 4) & 0x03fffffc)
+
+#define FRAME_ARGS_ADDRESS(fi) (fi->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ \
+ register int regnum; \
+ register int frame; \
+ register int next_addr; \
+ register int return_data_save; \
+ register int saved_register_mask; \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ frame = (frame_info)->frame; \
+ return_data_save = read_memory_integer(frame, 4) & 0x03fffffc - 12; \
+ saved_register_mask = \
+ read_memory_integer(return_data_save, 4); \
+ next_addr = frame - 12; \
+ for (regnum = 4; regnum < 10; regnum++) \
+ if (saved_register_mask & (1<<regnum)) { \
+ next_addr -= 4; \
+ (frame_saved_regs).regs[regnum] = next_addr; \
+ } \
+ if (read_memory_integer(return_data_save + 4, 4) == 0xed6d7103) { \
+ next_addr -= 12; \
+ (frame_saved_regs).regs[F0_REGNUM + 7] = next_addr; \
+ } \
+ if (read_memory_integer(return_data_save + 8, 4) == 0xed6d6103) { \
+ next_addr -= 12; \
+ (frame_saved_regs).regs[F0_REGNUM + 6] = next_addr; \
+ } \
+ if (read_memory_integer(return_data_save + 12, 4) == 0xed6d5103) { \
+ next_addr -= 12; \
+ (frame_saved_regs).regs[F0_REGNUM + 5] = next_addr; \
+ } \
+ if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103) { \
+ next_addr -= 12; \
+ (frame_saved_regs).regs[F0_REGNUM + 4] = next_addr; \
+ } \
+ (frame_saved_regs).regs[SP_REGNUM] = next_addr; \
+ (frame_saved_regs).regs[PC_REGNUM] = frame - 4; \
+ (frame_saved_regs).regs[PS_REGNUM] = frame - 4; \
+ (frame_saved_regs).regs[FP_REGNUM] = frame - 12; \
+}
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ \
+ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ /* opcode for ldmdb fp,{v1-v6,fp,ip,lr,pc}^ */ \
+ sp = push_word(sp, 0xe92dbf0); /* dummy return_data_save ins */ \
+ /* push a pointer to the dummy instruction minus 12 */ \
+ sp = push_word(sp, read_register (SP_REGNUM) - 16); \
+ sp = push_word(sp, read_register (PS_REGNUM)); \
+ sp = push_word(sp, read_register (SP_REGNUM)); \
+ sp = push_word(sp, read_register (FP_REGNUM)); \
+ for (regnum = 9; regnum >= 4; regnum --) \
+ sp = push_word(sp, read_register (regnum)); \
+ write_register (FP_REGNUM, read_register (SP_REGNUM) - 8); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ \
+ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register unsigned long return_data_save = \
+ read_memory_integer ( (read_memory_integer (fp, 4) & \
+ 0x03fffffc) - 12, 4); \
+ register int regnum; \
+ write_register (PS_REGNUM, read_memory_integer (fp - 4, 4)); \
+ write_register (PC_REGNUM, read_register (PS_REGNUM) & 0x03fffffc); \
+ write_register (SP_REGNUM, read_memory_integer (fp - 8, 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp - 12, 4)); \
+ fp -= 12; \
+ for (regnum = 9; regnum >= 4; regnum--) \
+ if (return_data_save & (1<<regnum)) { \
+ fp -= 4; \
+ write_register (regnum, read_memory_integer(fp, 4)); \
+ } \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM), \
+ read_pc ())); \
+}
+
+/* This sequence of words is the instructions
+
+ ldmia sp!,{a1-a4}
+ mov lk,pc
+ bl *+8
+ swi bkpt_swi
+
+ Note this is 16 bytes. */
+
+#define CALL_DUMMY {0xe8bd000f, 0xe1a0e00f, 0xeb000000, 0xef180000}
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ register enum type_code code = TYPE_CODE (type); \
+ register nargs_in_registers, struct_return = 0; \
+ /* fix the load-arguments mask to move the first 4 or less arguments \
+ into a1-a4 but make sure the structure return address in a1 is \
+ not disturbed if the function is returning a structure */ \
+ if ((code == TYPE_CODE_STRUCT || \
+ code == TYPE_CODE_UNION || \
+ code == TYPE_CODE_ARRAY) && \
+ TYPE_LENGTH (type) > 4) { \
+ nargs_in_registers = min(nargs + 1, 4); \
+ struct_return = 1; \
+ } else \
+ nargs_in_registers = min(nargs, 4); \
+ *(char *) dummyname = (1 << nargs_in_registers) - 1 - struct_return; \
+ *(int *)((char *) dummyname + 8) = \
+ (((fun - (pc + 16)) / 4) & 0x00ffffff) | 0xeb000000; }
--- /dev/null
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+#include "tm-mips.h"
--- /dev/null
+/* Definitions to make GDB run on Convex Unix (4bsd)
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* I don't know if this will work for cross-debugging, even if you do get
+ the right files. */
+/* Include certain files for dbxread.c */
+#include <convex/filehdr.h>
+#include <convex/opthdr.h>
+#include <convex/scnhdr.h>
+#include <nlist.h>
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* There is come problem with the debugging symbols generated by the
+ compiler such that the debugging symbol for the first line of a
+ function overlap with the function prologue. */
+#define PROLOGUE_FIRSTLINE_OVERLAP
+
+/* When convex pcc says CHAR or SHORT, it provides the correct address. */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Symbol types to ignore. */
+/* 0xc4 is N_MONPT. Use the numeric value for the benefit of people
+ with (rather) old OS's. */
+#define IGNORE_SYMBOL(TYPE) \
+ (((TYPE) & ~N_EXT) == N_TBSS \
+ || ((TYPE) & ~N_EXT) == N_TDATA \
+ || ((TYPE) & ~N_EXT) == 0xc4)
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code.
+ Convex prolog is:
+ [sub.w #-,sp] in one of 3 possible sizes
+ [mov psw,- fc/vc main program prolog
+ and #-,- (skip it because the "mov psw" saves the
+ mov -,psw] T bit, so continue gets a surprise trap)
+ [and #-,sp] fc/vc O2 main program prolog
+ [ld.- -(ap),-] pcc/gcc register arg loads
+*/
+
+#define SKIP_PROLOGUE(pc) \
+{ int op, ix; \
+ op = read_memory_integer (pc, 2); \
+ if ((op & 0xffc7) == 0x5ac0) pc += 2; \
+ else if (op == 0x1580) pc += 4; \
+ else if (op == 0x15c0) pc += 6; \
+ if ((read_memory_integer (pc, 2) & 0xfff8) == 0x7c40 \
+ && (read_memory_integer (pc + 2, 2) & 0xfff8) == 0x1240 \
+ && (read_memory_integer (pc + 8, 2) & 0xfff8) == 0x7c48) \
+ pc += 10; \
+ if (read_memory_integer (pc, 2) == 0x1240) pc += 6; \
+ for (;;) { \
+ op = read_memory_integer (pc, 2); \
+ ix = (op >> 3) & 7; \
+ if (ix != 6) break; \
+ if ((op & 0xfcc0) == 0x3000) pc += 4; \
+ else if ((op & 0xfcc0) == 0x3040) pc += 6; \
+ else if ((op & 0xfcc0) == 0x2800) pc += 4; \
+ else if ((op & 0xfcc0) == 0x2840) pc += 6; \
+ else break;}}
+
+/* Immediately after a function call, return the saved pc.
+ (ignore frame and return *$sp so we can handle both calls and callq) */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space.
+ This is ((USRSTACK + 0xfff) & -0x1000)) from <convex/vmparam.h> but
+ that expression depends on the kernel version; instead, fetch a
+ page-zero pointer and get it from that. This will be invalid if
+ they ever change the way bkpt signals are delivered. */
+
+#define STACK_END_ADDR (0xfffff000 & *(unsigned *) 0x80000050)
+
+/* User-mode traps push an extended rtn block,
+ then fault with one of the following PCs */
+
+#define is_trace_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000040)) <= 4)
+#define is_arith_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000044)) <= 4)
+#define is_break_pc(pc) ((unsigned) ((pc) - (*(int *) 0x80000050)) <= 4)
+
+/* We need to manipulate trap bits in the psw */
+
+#define PSW_TRAP_FLAGS 0x69670000
+#define PSW_T_BIT 0x08000000
+#define PSW_S_BIT 0x01000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. (bkpt) */
+
+#define BREAKPOINT {0x7d,0x50}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT but not always.
+ (The break PC needs to be decremented by 2, but we do it when the
+ break frame is recognized and popped. That way gdb can tell breaks
+ from trace traps with certainty.) */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. (rtn or rtnq) */
+
+#define ABOUT_TO_RETURN(pc) \
+ ((read_memory_integer (pc, 2) & 0xffe0) == 0x7c80)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p,len) 0
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long long
+
+/* Number of machine registers */
+
+#define NUM_REGS 26
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"pc","psw","fp","ap","a5","a4","a3","a2","a1","sp",\
+ "s7","s6","s5","s4","s3","s2","s1","s0",\
+ "S7","S6","S5","S4","S3","S2","S1","S0"}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define S0_REGNUM 25 /* the real S regs */
+#define S7_REGNUM 18
+#define s0_REGNUM 17 /* low-order halves of S regs */
+#define s7_REGNUM 10
+#define SP_REGNUM 9 /* A regs */
+#define A1_REGNUM 8
+#define A5_REGNUM 4
+#define AP_REGNUM 3
+#define FP_REGNUM 2 /* Contains address of executing stack frame */
+#define PS_REGNUM 1 /* Contains processor status */
+#define PC_REGNUM 0 /* Contains program counter */
+
+/* convert dbx stab register number (from `r' declaration) to a gdb REGNUM */
+
+#define STAB_REG_TO_REGNUM(value) \
+ ((value) < 8 ? S0_REGNUM - (value) : SP_REGNUM - ((value) - 8))
+
+/* Vector register numbers, not handled as ordinary regs.
+ They are treated as convenience variables whose values are read
+ from the inferior when needed. */
+
+#define V0_REGNUM 0
+#define V7_REGNUM 7
+#define VM_REGNUM 8
+#define VS_REGNUM 9
+#define VL_REGNUM 10
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (4*10 + 8*8)
+
+/* Index within `registers' of the first byte of the space for
+ register N.
+ NB: must match structure of struct syscall_context for correct operation */
+
+#define REGISTER_BYTE(N) ((N) < s7_REGNUM ? 4*(N) : \
+ (N) < S7_REGNUM ? 44 + 8 * ((N)-s7_REGNUM) : \
+ 40 + 8 * ((N)-S7_REGNUM))
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) ((N) < S7_REGNUM ? 4 : 8)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_RAW_SIZE (REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_RAW_SIZE (REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < S7_REGNUM ? builtin_type_int : builtin_type_long_long)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (A1_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (&((char *) REGBUF) [REGISTER_BYTE (S0_REGNUM) + \
+ 8 - TYPE_LENGTH (TYPE)],\
+ VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (S0_REGNUM), VALBUF, 8)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (*(int *) & ((char *) REGBUF) [REGISTER_BYTE (s0_REGNUM)])
+
+/* Define trapped internal variable hooks to read and write
+ vector and communication registers. */
+
+#define IS_TRAPPED_INTERNALVAR is_trapped_internalvar
+#define VALUE_OF_TRAPPED_INTERNALVAR value_of_trapped_internalvar
+#define SET_TRAPPED_INTERNALVAR set_trapped_internalvar
+
+extern struct value *value_of_trapped_internalvar ();
+
+/* Hooks to read data from soff exec and core files,
+ and to describe the files. */
+
+#define XFER_CORE_FILE
+#define FILES_INFO_HOOK print_maps
+
+/* Hook to call to print a typeless integer value, normally printed in decimal.
+ For convex, use hex instead if the number looks like an address. */
+
+#define PRINT_TYPELESS_INTEGER decout
+
+/* For the native compiler, variables for a particular lexical context
+ are listed after the beginning LBRAC instead of before in the
+ executables list of symbols. Using "gcc_compiled." to distinguish
+ between GCC and native compiler doesn't work on Convex because the
+ linker sorts the symbols to put "gcc_compiled." in the wrong place.
+ desc is nonzero for native, zero for gcc. */
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) (desc != 0)
+
+/* Pcc occaisionally puts an SO where there should be an SOL. */
+#define PCC_SOL_BROKEN
+
+/* Cannot execute with pc on the stack. */
+#define CANNOT_EXECUTE_STACK
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame_info with a frame's nominal address in fi->frame,
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* (caller fp is saved at 8(fp)) */
+
+#define FRAME_CHAIN(fi) (read_memory_integer ((fi)->frame + 8, 4))
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0.
+ On convex, check at the return address for `callq' -- if so, frameless,
+ otherwise, not. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ \
+ extern CORE_ADDR text_start, text_end; \
+ CORE_ADDR call_addr = SAVED_PC_AFTER_CALL (FI); \
+ (FRAMELESS) = (call_addr >= text_start && call_addr < text_end \
+ && read_memory_integer (call_addr - 6, 1) == 0x22); \
+}
+
+#define FRAME_SAVED_PC(fi) (read_memory_integer ((fi)->frame, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) (read_memory_integer ((fi)->frame + 12, 4))
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ numargs = read_memory_integer (FRAME_ARGS_ADDRESS (fi) - 4, 4); \
+ if (numargs < 0 || numargs >= 256) numargs = -1;}
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+/* Normal (short) frames save only PC, FP, (callee's) AP. To reasonably
+ handle gcc and pcc register variables, scan the code following the
+ call for the instructions the compiler inserts to reload register
+ variables from stack slots and record the stack slots as the saved
+ locations of those registers. This will occasionally identify some
+ random load as a saved register; this is harmless. vc does not
+ declare its register allocation actions in the stabs. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */\
+ (read_memory_integer ((frame_info)->frame + 4, 4) >> 25) & 3; \
+ register CORE_ADDR frame_fp = \
+ read_memory_integer ((frame_info)->frame + 8, 4); \
+ register CORE_ADDR next_addr; \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 0; \
+ (frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[AP_REGNUM] = frame_fp + 12; \
+ next_addr = (frame_info)->frame + 12; \
+ if (frame_length < 3) \
+ for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 4); \
+ if (frame_length < 2) \
+ (frame_saved_regs).regs[SP_REGNUM] = (next_addr += 4); \
+ next_addr -= 4; \
+ if (frame_length < 3) \
+ for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 8); \
+ if (frame_length < 2) \
+ (frame_saved_regs).regs[S0_REGNUM] = (next_addr += 8); \
+ else \
+ (frame_saved_regs).regs[SP_REGNUM] = next_addr + 8; \
+ if (frame_length == 3) { \
+ CORE_ADDR pc = read_memory_integer ((frame_info)->frame, 4); \
+ int op, ix, disp; \
+ op = read_memory_integer (pc, 2); \
+ if ((op & 0xffc7) == 0x1480) pc += 4; /* add.w #-,sp */ \
+ else if ((op & 0xffc7) == 0x58c0) pc += 2; /* add.w #-,sp */ \
+ op = read_memory_integer (pc, 2); \
+ if ((op & 0xffc7) == 0x2a06) pc += 4; /* ld.w -,ap */ \
+ for (;;) { \
+ op = read_memory_integer (pc, 2); \
+ ix = (op >> 3) & 7; \
+ if ((op & 0xfcc0) == 0x2800) { /* ld.- -,ak */ \
+ regnum = SP_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 2); \
+ pc += 4;} \
+ else if ((op & 0xfcc0) == 0x2840) { /* ld.- -,ak */ \
+ regnum = SP_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 4); \
+ pc += 6;} \
+ if ((op & 0xfcc0) == 0x3000) { /* ld.- -,sk */ \
+ regnum = S0_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 2); \
+ pc += 4;} \
+ else if ((op & 0xfcc0) == 0x3040) { /* ld.- -,sk */ \
+ regnum = S0_REGNUM - (op & 7); \
+ disp = read_memory_integer (pc + 2, 4); \
+ pc += 6;} \
+ else if ((op & 0xff00) == 0x7100) { /* br crossjump */ \
+ pc += 2 * (char) op; \
+ continue;} \
+ else if (op == 0x0140) { /* jmp crossjump */ \
+ pc = read_memory_integer (pc + 2, 4); \
+ continue;} \
+ else break; \
+ if ((frame_saved_regs).regs[regnum]) \
+ break; \
+ if (ix == 7) disp += frame_fp; \
+ else if (ix == 6) disp += read_memory_integer (frame_fp + 12, 4); \
+ else if (ix != 0) break; \
+ (frame_saved_regs).regs[regnum] = \
+ disp - 8 + (1 << ((op >> 8) & 3)); \
+ if (regnum >= S7_REGNUM) \
+ (frame_saved_regs).regs[regnum - S0_REGNUM + s0_REGNUM] = \
+ disp - 4 + (1 << ((op >> 8) & 3)); \
+ } \
+ } \
+}
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char buf[8]; \
+ long word; \
+ for (regnum = S0_REGNUM; regnum >= S7_REGNUM; --regnum) { \
+ read_register_bytes (REGISTER_BYTE (regnum), buf, 8); \
+ sp = push_bytes (sp, buf, 8);} \
+ for (regnum = SP_REGNUM; regnum >= FP_REGNUM; --regnum) { \
+ word = read_register (regnum); \
+ sp = push_bytes (sp, &word, 4);} \
+ word = (read_register (PS_REGNUM) &~ (3<<25)) | (1<<25); \
+ sp = push_bytes (sp, &word, 4); \
+ word = read_register (PC_REGNUM); \
+ sp = push_bytes (sp, &word, 4); \
+ write_register (SP_REGNUM, sp); \
+ write_register (FP_REGNUM, sp); \
+ write_register (AP_REGNUM, sp);}
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME do {\
+ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register int regnum; \
+ register int frame_length = /* 3 short, 2 long, 1 extended, 0 context */ \
+ (read_memory_integer (fp + 4, 4) >> 25) & 3; \
+ char buf[8]; \
+ write_register (PC_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PS_REGNUM, read_memory_integer (fp += 4, 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp += 4, 4)); \
+ write_register (AP_REGNUM, read_memory_integer (fp += 4, 4)); \
+ if (frame_length < 3) \
+ for (regnum = A5_REGNUM; regnum < SP_REGNUM; ++regnum) \
+ write_register (regnum, read_memory_integer (fp += 4, 4)); \
+ if (frame_length < 2) \
+ write_register (SP_REGNUM, read_memory_integer (fp += 4, 4)); \
+ fp -= 4; \
+ if (frame_length < 3) \
+ for (regnum = S7_REGNUM; regnum < S0_REGNUM; ++regnum) { \
+ read_memory (fp += 8, buf, 8); \
+ write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \
+ if (frame_length < 2) { \
+ read_memory (fp += 8, buf, 8); \
+ write_register_bytes (REGISTER_BYTE (regnum), buf, 8);} \
+ else write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM), \
+ read_pc ())); \
+} while (0)
+
+/* This sequence of words is the instructions
+ mov sp,ap
+ pshea 69696969
+ calls 32323232
+ bkpt
+ Note this is 16 bytes. */
+
+#define CALL_DUMMY {0x50860d4069696969LL,0x2140323232327d50LL}
+
+#define CALL_DUMMY_LENGTH 16
+
+#define CALL_DUMMY_START_OFFSET 0
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 4) = nargs; \
+ *(int *)((char *) dummyname + 10) = fun; }
+\f
+/* Defs to read soff symbol tables, see dbxread.c */
+
+#define NUMBER_OF_SYMBOLS ((long) opthdr.o_nsyms)
+#define STRING_TABLE_OFFSET ((long) filehdr.h_strptr)
+#define SYMBOL_TABLE_OFFSET ((long) opthdr.o_symptr)
+#define STRING_TABLE_SIZE ((long) filehdr.h_strsiz)
+#define SIZE_OF_TEXT_SEGMENT ((long) txthdr.s_size)
+#define ENTRY_POINT ((long) opthdr.o_entry)
+
+#define READ_STRING_TABLE_SIZE(BUFFER) \
+ (BUFFER = STRING_TABLE_SIZE)
+
+#define DECLARE_FILE_HEADERS \
+ FILEHDR filehdr; \
+ OPTHDR opthdr; \
+ SCNHDR txthdr
+
+#define READ_FILE_HEADERS(DESC,NAME) \
+{ \
+ int n; \
+ val = myread (DESC, &filehdr, sizeof filehdr); \
+ if (val < 0) \
+ perror_with_name (NAME); \
+ if (! IS_SOFF_MAGIC (filehdr.h_magic)) \
+ error ("%s: not an executable file.", NAME); \
+ lseek (DESC, 0L, 0); \
+ if (myread (DESC, &filehdr, sizeof filehdr) < 0) \
+ perror_with_name (NAME); \
+ if (myread (DESC, &opthdr, filehdr.h_opthdr) <= 0) \
+ perror_with_name (NAME); \
+ for (n = 0; n < filehdr.h_nscns; n++) \
+ { \
+ if (myread (DESC, &txthdr, sizeof txthdr) < 0) \
+ perror_with_name (NAME); \
+ if ((txthdr.s_flags & S_TYPMASK) == S_TEXT) \
+ break; \
+ } \
+}
--- /dev/null
+/* Parameters for execution on a Hewlett-Packard 9000/300, running bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Configuration file for HP9000/300 series machine running
+ * University of Utah's 4.3bsd port. This is NOT for HP-UX.
+ * Problems to hpbsd-bugs@cs.utah.edu
+ */
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+#define TARGET_NBPG 4096
+#define TARGET_UPAGES 3
+
+/* On the HP300, sigtramp is in the u area. Gak! User struct is not
+ mapped to the same virtual address in user/kernel address space
+ (hence STACK_END_ADDR as opposed to KERNEL_U_ADDR). This tests
+ for the whole u area, since we don't necessarily have hp300bsd
+ include files around. */
+#define IN_SIGTRAMP(pc, name) \
+ ((pc) >= STACK_END_ADDR \
+ && (pc) < STACK_END_ADDR + TARGET_UPAGES * TARGET_NBPG \
+ )
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xfff00000
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x4e, 0x42}
+
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char raw_buffer[12]; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ { read_register_gen (regnum, raw_buffer); \
+ sp = push_bytes (sp, raw_buffer, 12); } \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ char raw_buffer[12]; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ if (fsr.regs[regnum]) \
+ { read_memory (fsr.regs[regnum], raw_buffer, 12); \
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ fmovem 0xff,-(sp)
+ moveml 0xfffc,-(sp)
+ clrw -(sp)
+ movew ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jsr @#32323232
+ addl #69696969,sp
+ trap #2
+ nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e424e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 20) = nargs * 4; \
+ *(int *)((char *) dummyname + 14) = fun; }
+\f
+#define HAVE_68881
+
+#include "tm-68k.h"
--- /dev/null
+/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x4e, 0x41}
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xFFF00000
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char raw_buffer[12]; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
+ sp = push_bytes (sp, raw_buffer, 12); } \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ char raw_buffer[12]; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ if (fsr.regs[regnum]) \
+ { read_memory (fsr.regs[regnum], raw_buffer, 12); \
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+ read_pc ()));}
+
+/* This sequence of words is the instructions
+ fmovem 0xff,-(sp)
+ moveml 0xfffc,-(sp)
+ clrw -(sp)
+ movew ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jsr @#32323232
+ addl #69696969,sp
+ bpt
+ nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e414e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 20) = nargs * 4; \
+ *(int *)((char *) dummyname + 14) = fun; }
+\f
+#include HAVE_68881
+
+#include "tm-68k.h"
--- /dev/null
+/* Macro definitions for i386 using the GNU object file format.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ *
+ * i386gnu: COFF_ENCAPSULATE
+ */
+
+
+#define COFF_ENCAPSULATE
+
+#include "tm-i386v.h"
+
+/* The version in m-i386.h is for COFF. */
+#undef N_SET_MAGIC
+
+#define NAMES_HAVE_UNDERSCORE
+
+#undef COFF_FORMAT
+#define READ_DBX_FORMAT
--- /dev/null
+/* Macro defintions for i386.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* define this if you don't have the extension to coff that allows
+ * file names to appear in the string table
+ * (aux.x_file.x_foff)
+ */
+#define COFF_NO_LONG_FILE_NAMES
+
+/* turn this on when rest of gdb is ready */
+/* #define IEEE_FLOAT */
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+/* #define NAMES_HAVE_UNDERSCORE */
+
+/* Specify debugger information format. */
+
+/* #define READ_DBX_FORMAT */
+#define COFF_FORMAT
+
+/* number of traps that happen between exec'ing the shell
+ * to run an inferior, and when we finally get to
+ * the inferior code. This is 2 on most implementations.
+ */
+#define START_INFERIOR_TRAPS_EXPECTED 4
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* This is only supposed to work in execcore.c, where x == 0 and
+ this is called before any other fields are filled in. */
+#define N_SET_MAGIC(aouthdr, x) \
+ bzero ((char *) &aouthdr, sizeof aouthdr)
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0x80000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 1
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the 386. */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 16
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* the order of the first 8 registers must match the compiler's
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "ps", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP_REGNUM 5 /* Contains address of executing stack frame */
+#define SP_REGNUM 4 /* Contains address of top of stack */
+
+#define PC_REGNUM 8
+#define PS_REGNUM 9
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), 4);}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { (SP) -= sizeof (ADDR); \
+ write_memory ((SP), &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { i386_pop_frame (); }
+
+/* this is
+ * call 11223344 (32 bit relative)
+ * int3
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ int from, to, delta, loc; \
+ loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+ from = loc + 5; \
+ to = (int)(fun); \
+ delta = to - from; \
+ *(int *)((char *)(dummyname) + 1) = delta; \
+}
--- /dev/null
+/* Parameters for target machine Intel 960, for GDB, the GNU debugger.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Definitions to target GDB to any i960. */
+
+#ifndef I80960
+#define I80960
+#endif
+
+/* Hook for the SYMBOL_CLASS of a parameter when decoding DBX symbol
+ information. In the i960, parameters can be stored as locals or as
+ args, depending on the type of the debug record.
+
+ From empirical observation, gcc960 uses N_LSYM to indicate
+ arguments passed in registers and then copied immediately
+ to the frame, and N_PSYM to indicate arguments passed in a
+ g14-relative argument block. */
+
+#define DBX_PARM_SYMBOL_CLASS(type) ((type == N_LSYM)? LOC_LOCAL_ARG: LOC_ARG)
+
+/* Byte order is configurable, but this machine runs little-endian. */
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* We have IEEE floating point, if we have any float at all. */
+
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance ip across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(ip) { ip = skip_prologue (ip); }
+extern CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved ip.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function
+ executes some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) (saved_pc_after_call (frame))
+extern CORE_ADDR saved_pc_after_call ();
+
+/* Stack grows upward */
+
+#define INNER_THAN >
+
+/* Nonzero if instruction at ip is a return instruction. */
+
+#define ABOUT_TO_RETURN(ip) (read_memory_integer(ip,4) == 0x0a000000)
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes. */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* How long (ordinary) registers are */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+#define NUM_REGS 40
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES { \
+ /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", \
+ /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",\
+ /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", \
+ /* 32 */ "pc", "ac", "ip", "tc", "fp0", "fp1", "fp2", "fp3", \
+}
+
+/* Register numbers of various important registers (used to index
+ into arrays of register names and register values). */
+
+#define R0_REGNUM 0 /* First local register */
+#define SP_REGNUM 1 /* Contains address of top of stack */
+#define RIP_REGNUM 2 /* Return instruction pointer (local r2) */
+#define R15_REGNUM 15 /* Last local register */
+#define G0_REGNUM 16 /* First global register */
+#define G13_REGNUM 29 /* g13 - holds struct return address */
+#define G14_REGNUM 30 /* g14 - ptr to arg block / leafproc return address */
+#define FP_REGNUM 31 /* Contains address of executing stack frame */
+#define PCW_REGNUM 32 /* process control word */
+#define ACW_REGNUM 33 /* arithmetic control word */
+#define IP_REGNUM 34 /* instruction pointer */
+#define TCW_REGNUM 35 /* trace control word */
+#define FP0_REGNUM 36 /* First floating point register */
+
+/* Some registers have more than one name */
+
+#define PC_REGNUM IP_REGNUM /* GDB refers to ip as the Program Counter */
+#define PFP_REGNUM R0_REGNUM /* Previous frame pointer */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES ((36*4) + (4*10))
+
+/* Index within `registers' of the first byte of the space for register N. */
+
+#define REGISTER_BYTE(N) ( (N) < FP0_REGNUM ? \
+ (4*(N)) : ((10*(N)) - (6*FP0_REGNUM)) )
+
+/* The i960 has register windows, sort of. */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system? A yes answer
+ implies that 1) The name of this register will not be the same in
+ other frames, and 2) This register is automatically "saved" upon
+ subroutine calls and thus there is no need to search more than one
+ stack frame for it.
+
+ On the i960, in fact, the name of this register in another frame is
+ "mud" -- there is no overlap between the windows. Each window is
+ simply saved into the stack (true for our purposes, after having been
+ flushed; normally they reside on-chip and are restored from on-chip
+ without ever going to memory). */
+
+#define REGISTER_IN_WINDOW_P(regnum) ((regnum) <= R15_REGNUM)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the i960, all regs are 4 bytes except for floating
+ point, which are 10. NINDY only sends us 8 byte values for these,
+ which is a pain, but VxWorks handles this correctly, so we must. */
+
+#define REGISTER_RAW_SIZE(N) ( (N) < FP0_REGNUM ? 4 : 10 )
+
+/* Number of bytes of storage in the program's representation for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ( (N) < FP0_REGNUM ? 4 : 8 )
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion from raw format to virtual
+ format. */
+
+#define REGISTER_CONVERTIBLE(N) ((N) >= FP0_REGNUM)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ \
+ extern struct ext_format ext_format_i960[]; \
+ \
+ if ((REGNUM) >= FP0_REGNUM) \
+ ieee_extended_to_double (ext_format_i960, (FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4); \
+}
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+{ \
+ extern struct ext_format ext_format_i960[]; \
+ \
+ if ((REGNUM) >= FP0_REGNUM) \
+ double_to_ieee_extended (ext_format_i960, (FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4); \
+}
+
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) ((N) < FP0_REGNUM ? \
+ builtin_type_int : builtin_type_double)
+\f
+/* Macros for understanding function return values... */
+
+/* Does the specified function use the "struct returning" convention
+ or the "value returning" convention? The "value returning" convention
+ almost invariably returns the entire value in registers. The
+ "struct returning" convention often returns the entire value in
+ memory, and passes a pointer (out of or into the function) saying
+ where the value (is or should go).
+
+ Since this sometimes depends on whether it was compiled with GCC,
+ this is also an argument. This is used in call_function to build a
+ stack, and in value_being_returned to print return values.
+
+ On i960, a structure is returned in registers g0-g3, if it will fit.
+ If it's more than 16 bytes long, g13 pointed to it on entry. */
+
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 16)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. This is only called if USE_STRUCT_CONVENTION for this
+ type is 0.
+
+ On the i960 we just take as many bytes as we need from G0 through G3. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy(REGBUF+REGISTER_BYTE(G0_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
+
+/* If USE_STRUCT_CONVENTION produces a 1,
+ extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one).
+
+ Address of where to put structure was passed in in global
+ register g13 on entry. God knows what's in g13 now. The
+ (..., 0) below is to make it appear to return a value, though
+ actually all it does is call error(). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (error("Don't know where large structure is returned on i960"), 0)
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format, for "value returning" functions.
+
+ For 'return' command: not (yet) implemented for i960. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ error ("Returning values from functions is not implemented in i960 gdb")
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ error ("Returning values from functions is not implemented in i960 gdb")
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* We cache information about saved registers in the frame structure,
+ to save us from having to re-scan function prologues every time
+ a register in a non-current frame is accessed. */
+
+#define EXTRA_FRAME_INFO \
+ struct frame_saved_regs *fsr; \
+ CORE_ADDR arg_pointer;
+
+/* Zero the frame_saved_regs pointer when the frame is initialized,
+ so that FRAME_FIND_SAVED_REGS () will know to allocate and
+ initialize a frame_saved_regs struct the first time it is called.
+ Set the arg_pointer to -1, which is not valid; 0 and other values
+ indicate real, cached values. */
+
+#define INIT_EXTRA_FRAME_INFO(fi) ((fi)->fsr = 0, (fi)->arg_pointer = -1)
+
+/* On the i960, we get the chain pointer by reading the PFP saved
+ on the stack and clearing the status bits. */
+
+#define FRAME_CHAIN(thisframe) \
+ (read_memory_integer (FRAME_FP(thisframe), 4) & ~0xf)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+ and has no caller. In that case, FRAME_CHAIN_COMBINE is not used.
+
+ On the i960, each various target system type must define FRAME_CHAIN_VALID,
+ since it differs between NINDY and VxWorks, the two currently supported
+ targets types. We leave it undefined here. */
+
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ { (FRAMELESS) = (leafproc_return ((FI)->pc) != 0); }
+
+/* Note that in the i960 architecture the return pointer is saved in the
+ *caller's* stack frame.
+
+ Make sure to zero low-order bits because of bug in 960CA A-step part
+ (instruction addresses should always be word-aligned anyway). */
+
+#define FRAME_SAVED_PC(frame) \
+ ((read_memory_integer(FRAME_CHAIN(frame)+8,4)) & ~3)
+
+/* On the i960, FRAME_ARGS_ADDRESS should return the value of
+ g14 as passed into the frame, if known. We need a function for this.
+ We cache this value in the frame info if we've already looked it up. */
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ (((fi)->arg_pointer != -1)? (fi)->arg_pointer: frame_args_address (fi, 0))
+extern CORE_ADDR frame_args_address (); /* i960-tdep.c */
+
+/* This is the same except it should return 0 when
+ it does not really know where the args are, rather than guessing.
+ This value is not cached since it is only used infrequently. */
+
+#define FRAME_ARGS_ADDRESS_CORRECT(fi) (frame_args_address (fi, 1))
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Set NUMARGS to the number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Produce the positions of the saved registers in a stack frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info_addr, sr) \
+ frame_find_saved_regs (frame_info_addr, &sr)
+extern void frame_find_saved_regs(); /* See i960-tdep.c */
+
+
+/* Print status when we get a random unexpected signal. We have more
+ kinds of signals than Unix does... */
+
+#define PRINT_RANDOM_SIGNAL(stop_signal) print_fault (stop_signal)
+\f
+/* Things needed for making calls to functions in the inferior process */
+
+/* Push an empty stack frame, to record the current ip, etc.
+
+ Not (yet?) implemented for i960. */
+
+#define PUSH_DUMMY_FRAME \
+error("Function calls into the inferior process are not supported on the i960")
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+ pop_frame ()
+
+
+/* This sequence of words is the instructions
+
+ callx 0x00000000
+ fmark
+ */
+
+/* #define CALL_DUMMY { 0x86003000, 0x00000000, 0x66003e00 } */
+
+/* #define CALL_DUMMY_START_OFFSET 0 *//* Start execution at beginning of dummy */
+
+/* Indicate that we don't support calling inferior child functions. */
+
+#undef CALL_DUMMY
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at 'dummyname'.
+
+ Ignore arg count on i960. */
+
+/* #define FIX_CALL_DUMMY(dummyname, fun, nargs) *(((int *)dummyname)+1) = fun */
+
+#undef FIX_CALL_DUMMY
+
+
+/* Interface definitions for kernel debugger KDB */
+/* (Not relevant to i960.) */
--- /dev/null
+/* Definitions to target GDB on an ISI Optimum V (3.05) under 4.3bsd.
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This has not been tested on ISI's running BSD 4.2, but it will probably
+ work. */
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/*#define STACK_END_ADDR 0x10000000*/
+#define STACK_END_ADDR 0xfffe000
+
+/* Data segment starts at etext rounded up to DATAROUND in {N,Z}MAGIC files */
+
+#define DATAROUND 0x20000
+#define N_DATADDR(hdr) (hdr.a_magic != OMAGIC ? \
+ (hdr.a_text + DATAROUND) & ~(DATAROUND-1) : hdr.a_text)
+
+/* Text segment starts at sizeof (struct exec) in {N,Z}MAGIC files */
+
+#define N_TXTADDR(hdr) (hdr.a_magic != OMAGIC ? sizeof (struct exec) : 0)
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always.
+ On the ISI, the kernel resets the pc to the trap instr */
+
+#define DECR_PC_AFTER_BREAK 0
+
+\f
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(val, fi) \
+{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
+ register int insn = 0177777 & read_memory_integer (pc, 2); \
+ val = 0; \
+ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
+ val = read_memory_integer (pc + 2, 2); \
+ else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
+ || (insn & 0170777) == 0050117) /* addqw */ \
+ { val = (insn >> 9) & 7; if (val == 0) val = 8; } \
+ else if (insn == 0157774) /* addal #WW, sp */ \
+ val = read_memory_integer (pc + 2, 4); \
+ val >>= 2; }
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int regmask; \
+ register CORE_ADDR next_addr; \
+ register CORE_ADDR pc; \
+ register int insn; \
+ register int offset; \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ if ((frame_info)->pc >= (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 8*12 - 4 \
+ && (frame_info)->pc <= (frame_info)->frame) \
+ { next_addr = (frame_info)->frame; \
+ pc = (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 8*12 - 4; }\
+ else \
+ { pc = get_pc_function_start ((frame_info)->pc); \
+ /* Verify we have a link a6 instruction next, \
+ or a branch followed by a link a6 instruction; \
+ if not we lose. If we win, find the address above the saved \
+ regs using the amount of storage from the link instruction. */\
+retry: \
+ insn = read_memory_integer (pc, 2); \
+ if (insn == 044016) \
+ next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 4), pc+=4; \
+ else if (insn == 047126) \
+ next_addr = (frame_info)->frame - read_memory_integer (pc += 2, 2), pc+=2; \
+ else if ((insn & 0177400) == 060000) /* bra insn */ \
+ { offset = insn & 0377; \
+ pc += 2; /* advance past bra */ \
+ if (offset == 0) /* bra #word */ \
+ offset = read_memory_integer (pc, 2), pc += 2; \
+ else if (offset == 0377) /* bra #long */ \
+ offset = read_memory_integer (pc, 4), pc += 4; \
+ pc += offset; \
+ goto retry; \
+ } else goto lose; \
+ /* If have an addal #-n, sp next, adjust next_addr. */ \
+ if ((0177777 & read_memory_integer (pc, 2)) == 0157774) \
+ next_addr += read_memory_integer (pc += 2, 4), pc += 4; \
+ } \
+ /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */ \
+ insn = read_memory_integer (pc, 2), pc += 2; \
+ regmask = read_memory_integer (pc, 2); \
+ if ((insn & 0177760) == 022700) /* movl rn, (sp) */ \
+ (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr; \
+ else if ((insn & 0177760) == 024700) /* movl rn, -(sp) */ \
+ (frame_saved_regs).regs[(insn&7) + ((insn&010)?8:0)] = next_addr-=4; \
+ else if (insn == 0044327) /* moveml mask, (sp) */ \
+ { pc += 2; \
+ /* Regmask's low bit is for register 0, the first written */ \
+ next_addr -= 4; \
+ for (regnum = 0; regnum < 16; regnum++, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr += 4); \
+ } else if (insn == 0044347) /* moveml mask, -(sp) */ \
+ { pc += 2; \
+ /* Regmask's low bit is for register 15, the first pushed */ \
+ for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1) \
+ if (regmask & 1) \
+ (frame_saved_regs).regs[regnum] = (next_addr -= 4); } \
+ /* clrw -(sp); movw ccr,-(sp) may follow. */ \
+ if (read_memory_integer (pc, 2) == 041147 \
+ && read_memory_integer (pc+2, 2) == 042347) \
+ (frame_saved_regs).regs[PS_REGNUM] = (next_addr -= 4); \
+ lose: ; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame; \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
+}
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char raw_buffer[12]; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
+ sp = push_bytes (sp, raw_buffer, 12); } \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ char raw_buffer[12]; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ if (fsr.regs[regnum]) \
+ { read_memory (fsr.regs[regnum], raw_buffer, 12); \
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM), \
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ fmovem #<f0-f7>,-(sp)
+ moveml 0xfffc,-(sp)
+ clrw -(sp)
+ movew ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jsr @#32323232
+ addl #69696969,sp
+ bpt
+ nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 20) = nargs * 4; \
+ *(int *)((char *) dummyname + 14) = fun; }
+\f
+#define HAVE_68881 1
+
+#include "tm-68k.h"
--- /dev/null
+/* Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is currently for a 88000 running DGUX. If other 88k ports are
+ done, OS-specific stuff should be moved (see tm-68k.h, for example). */
+/* g++ support is not yet included. */
+
+#include "tdesc.h"
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* This is not a CREATE_INFERIOR_HOOK because it also applies to
+ remote debugging. */
+#define START_INFERIOR_HOOK () \
+ { \
+ extern int safe_to_init_tdesc_context; \
+ extern int tdesc_handle; \
+ \
+ safe_to_init_tdesc_context = 0; \
+ if (tdesc_handle) \
+ { \
+ dc_terminate (tdesc_handle); \
+ tdesc_handle = 0; \
+ } \
+ }
+
+#define EXTRA_FRAME_INFO dc_dcontext_t frame_context;
+#define INIT_EXTRA_FRAME_INFO(fci) \
+ { \
+ if (fci->next_frame != NULL) \
+ { \
+ /* The call to get_prev_context */ \
+ /* will update current_context for us. */ \
+ int stack_error = 1; \
+ jmp_buf stack_jmp; \
+ if (!setjmp (stack_jmp)) \
+ { \
+ prev->frame_context \
+ = get_prev_context (next_frame->frame_context); \
+ stack_error = 0; \
+ } \
+ else \
+ { \
+ stack_error = 0; \
+ next_frame->prev = 0; \
+ return 0; \
+ } \
+ if (!prev->frame_context) \
+ { \
+ next_frame->prev = 0; \
+ return 0; \
+ } \
+ } \
+ else \
+ { \
+ /* We are creating an arbitrary frame */ \
+ /* (i.e. we are in create_new_frame). */ \
+ extern dc_dcontext_t current_context; \
+ \
+ fci->frame_context = current_context; \
+ } \
+ }
+
+#define INIT_FRAME_PC(fromleaf, prev) \
+ { \
+ prev->pc = dc_location (prev->frame_context); \
+ prev->frame = get_frame_base (prev->pc); \
+ }
+
+#define IEEE_FLOAT
+
+/* Text Description (TDESC) is used by m88k to maintain stack & reg info */
+
+#define TDESC
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Hook for read_relative_register_raw_bytes */
+
+#define READ_RELATIVE_REGISTER_RAW_BYTES
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(frompc) 0
+
+/* The m88k kernel aligns all instructions on 4-byte boundaries. The
+ kernel also uses the least significant two bits for its own hocus
+ pocus. When gdb receives an address from the kernel, it needs to
+ preserve those right-most two bits, but gdb also needs to be careful
+ to realize that those two bits are not really a part of the address
+ of an instruction. Shrug. */
+
+#define ADDR_BITS_REMOVE(addr) ((addr) & ~3)
+#define ADDR_BITS_SET(addr) (((addr) | 0x00000002) - 4)
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_register (SRP_REGNUM) & (~3))
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xF0000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+/* instruction 0xF000D1FF is 'tb0 0,r0,511'
+ If Bit bit 0 of r0 is clear (always true),
+ initiate exception processing (trap).
+ */
+#define BREAKPOINT {0xF0, 0x00, 0xD1, 0xFF}
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xF0000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+/* instruction 0xF000D1FF is 'tb0 0,r0,511'
+ If Bit bit 0 of r0 is clear (always true),
+ initiate exception processing (trap).
+ */
+#define BREAKPOINT {0xF0, 0x00, 0xD1, 0xFF}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. */
+/* 'jmp r1' or 'jmp.n r1' is used to return from a subroutine. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0xF800)
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the 386. */
+
+#define INVALID_FLOAT(p, len) IEEE_isNAN(p,len)
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 38
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {\
+ "r0",\
+ "r1",\
+ "r2",\
+ "r3",\
+ "r4",\
+ "r5",\
+ "r6",\
+ "r7",\
+ "r8",\
+ "r9",\
+ "r10",\
+ "r11",\
+ "r12",\
+ "r13",\
+ "r14",\
+ "r15",\
+ "r16",\
+ "r17",\
+ "r18",\
+ "r19",\
+ "r20",\
+ "r21",\
+ "r22",\
+ "r23",\
+ "r24",\
+ "r25",\
+ "r26",\
+ "r27",\
+ "r28",\
+ "r29",\
+ "r30",\
+ "r31",\
+ "psr",\
+ "fpsr",\
+ "fpcr",\
+ "sxip",\
+ "snip",\
+ "sfip",\
+ "vbr",\
+ "dmt0",\
+ "dmd0",\
+ "dma0",\
+ "dmt1",\
+ "dmd1",\
+ "dma1",\
+ "dmt2",\
+ "dmd2",\
+ "dma2",\
+ "sr0",\
+ "sr1",\
+ "sr2",\
+ "sr3",\
+ "fpecr",\
+ "fphs1",\
+ "fpls1",\
+ "fphs2",\
+ "fpls2",\
+ "fppt",\
+ "fprh",\
+ "fprl",\
+ "fpit",\
+ "fpsr",\
+ "fpcr",\
+ };
+
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define SRP_REGNUM 1 /* Contains subroutine return pointer */
+#define RV_REGNUM 2 /* Contains simple return values */
+#define SRA_REGNUM 12 /* Contains address of struct return values */
+#define FP_REGNUM 30 /* Contains address of executing stack frame */
+#define SP_REGNUM 31 /* Contains address of top of stack */
+#define SXIP_REGNUM 35 /* Contains Shadow Execute Instruction Pointer */
+#define SNIP_REGNUM 36 /* Contains Shadow Next Instruction Pointer */
+#define PC_REGNUM SXIP_REGNUM /* Program Counter */
+#define NPC_REGNUM SNIP_REGNUM /* Next Program Counter */
+#define PSR_REGNUM 32 /* Processor Status Register */
+#define FPSR_REGNUM 33 /* Floating Point Status Register */
+#define FPCR_REGNUM 34 /* Floating Point Control Register */
+#define SFIP_REGNUM 37 /* Contains Shadow Fetched Intruction pointer */
+#define NNPC_REGNUM SFIP_REGNUM /* Next Next Program Counter */
+
+/* PSR status bit definitions. */
+
+#define PSR_MODE 0x80000000
+#define PSR_BYTE_ORDER 0x40000000
+#define PSR_SERIAL_MODE 0x20000000
+#define PSR_CARRY 0x10000000
+#define PSR_SFU_DISABLE 0x000003f0
+#define PSR_SFU1_DISABLE 0x00000008
+#define PSR_MXM 0x00000004
+#define PSR_IND 0x00000002
+#define PSR_SFRZ 0x00000001
+
+/* BCS requires that the SXIP_REGNUM (or PC_REGNUM) contain the address
+ of the next instr to be executed when a breakpoint occurs. Because
+ the kernel gets the next instr (SNIP_REGNUM), the instr in SNIP needs
+ to be put back into SFIP, and the instr in SXIP should be shifted
+ to SNIP */
+
+/* Are you sitting down? It turns out that the 88K BCS (binary compatibility
+ standard) folks originally felt that the debugger should be responsible
+ for backing up the IPs, not the kernel (as is usually done). Well, they
+ have reversed their decision, and in future releases our kernel will be
+ handling the backing up of the IPs. So, eventually, we won't need to
+ do the SHIFT_INST_REGS stuff. But, for now, since there are 88K systems out
+ there that do need the debugger to do the IP shifting, and since there
+ will be systems where the kernel does the shifting, the code is a little
+ more complex than perhaps it needs to be (we still go inside SHIFT_INST_REGS,
+ and if the shifting hasn't occurred then gdb goes ahead and shifts). */
+
+#define SHIFT_INST_REGS
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#define REGISTER_BYTES (NUM_REGS * sizeof(REGISTER_TYPE))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N)*sizeof(REGISTER_TYPE))
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) (sizeof(REGISTER_TYPE))
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (sizeof(REGISTER_TYPE))
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE (sizeof(REGISTER_TYPE))
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.
+/* Are FPS1, FPS2, FPR "virtual" regisers? */
+
+#define MAX_REGISTER_VIRTUAL_SIZE (sizeof(REGISTER_TYPE))
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) {bcopy ((FROM), (TO), (sizeof(REGISTER_TYPE)));}
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) {bcopy ((FROM), (TO), (sizeof(REGISTER_TYPE)));}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+/* The 88k call/return conventions call for "small" values to be returned
+ into consecutive registers starting from r2. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (&(((void *)REGBUF)[REGISTER_BYTE(RV_REGNUM)]), (VALBUF), TYPE_LENGTH (TYPE))
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (2*sizeof(void*), (VALBUF), TYPE_LENGTH (TYPE))
+
+/* In COFF, if PCC says a parameter is a short or a char, do not
+ change it to int (it seems the convention is to change it). */
+
+#define BELIEVE_PCC_PROMOTION 1
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* These are just dummies for the 88k because INIT_FRAME_PC sets prev->frame
+ instead. */
+
+#define FRAME_CHAIN(thisframe) (0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (1)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (0)
+
+/* Define other aspects of the stack frame. */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame+4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) ((numargs) = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+/* On the 88k, parameter registers get stored into the so called "homing"
+ area. This *always* happens when you compiled with GCC and use -g.
+ Also, (with GCC and -g) the saving of the parameter register values
+ always happens right within the function prologue code, so these register
+ values can generally be relied upon to be already copied into their
+ respective homing slots by the time you will normally try to look at
+ them (we hope).
+
+ Note that homing area stack slots are always at *positive* offsets from
+ the frame pointer. Thus, the homing area stack slots for the parameter
+ registers (passed values) for a given function are actually part of the
+ frame area of the caller. This is unusual, but it should not present
+ any special problems for GDB.
+
+ Note also that on the 88k, we are only interested in finding the
+ registers that might have been saved in memory. This is a subset of
+ the whole set of registers because the standard calling sequence allows
+ the called routine to clobber many registers.
+
+ We could manage to locate values for all of the so called "preserved"
+ registers (some of which may get saved within any particular frame) but
+ that would require decoding all of the tdesc information. Tht would be
+ nice information for GDB to have, but it is not strictly manditory if we
+ can live without the ability to look at values within (or backup to)
+ previous frames.
+*/
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+ frame_find_saved_regs (frame_info, &frame_saved_regs)
+
+\f
+/* When popping a frame on the 88k (say when doing a return command), the
+ calling function only expects to have the "preserved" registers restored.
+ Thus, those are the only ones that we even try to restore here. */
+
+extern void pop_frame ();
+
+#define POP_FRAME pop_frame ()
+
+/* BCS is a standard for binary compatibility. This machine uses it. */
+#define BCS
--- /dev/null
+/* Definitions to target GDB to a merlin under utek 2.1
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* I don't know if this will work for cross-debugging, even if you do get
+ a copy of the right include file. */
+#include <machine/reg.h>
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = read_memory_integer (pc, 1); \
+ if (op == 0x82) \
+ { op = read_memory_integer (pc+2,1); \
+ if ((op & 0x80) == 0) pc += 3; \
+ else if ((op & 0xc0) == 0x80) pc += 4; \
+ else pc += 6; \
+ }}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0x800000)
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xf2}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p, len) 0
+
+/* Define this to say that the "svc" insn is followed by
+ codes in memory saying which kind of system call it is. */
+
+#define NS32K_SVC_IMMED_OPERANDS
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 25
+
+#define NUM_GENERAL_REGS 8
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "pc", "sp", "fp", "ps", \
+ "fsr", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "l0", "l1", "l2", "l3", "l4", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define AP_REGNUM FP_REGNUM
+#define FP_REGNUM 10 /* Contains address of executing stack frame */
+#define SP_REGNUM 9 /* Contains address of top of stack */
+#define PC_REGNUM 8 /* Contains program counter */
+#define PS_REGNUM 11 /* Contains processor status */
+#define FPS_REGNUM 12 /* Floating point status register */
+#define FP0_REGNUM 13 /* Floating point register 0 */
+#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+ LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) >= FP0_REGNUM ? \
+ ((N) >= LP0_REGNUM ? \
+ builtin_type_double \
+ : builtin_type_float) \
+ : builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ On this machine this is a no-op, as gcc doesn't run on it yet.
+ This calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the Merlin, the frame's nominal address is the FP value,
+ and at that address is saved previous FP value as a 4-byte word. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* compute base of arguments */
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ CORE_ADDR pc; \
+ int insn; \
+ int addr_mode; \
+ int width; \
+ \
+ pc = FRAME_SAVED_PC (fi); \
+ insn = read_memory_integer (pc,2); \
+ addr_mode = (insn >> 11) & 0x1f; \
+ insn = insn & 0x7ff; \
+ if ((insn & 0x7fc) == 0x57c \
+ && addr_mode == 0x14) /* immediate */ \
+ { if (insn == 0x57c) /* adjspb */ \
+ width = 1; \
+ else if (insn == 0x57d) /* adjspw */ \
+ width = 2; \
+ else if (insn == 0x57f) /* adjspd */ \
+ width = 4; \
+ numargs = read_memory_integer (pc+2,width); \
+ if (width > 1) \
+ flip_bytes (&numargs, width); \
+ numargs = - sign_extend (numargs, width*8) / 4; } \
+ else numargs = -1; \
+}
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ int regmask,regnum; \
+ int localcount; \
+ CORE_ADDR enter_addr; \
+ CORE_ADDR next_addr; \
+ \
+ enter_addr = get_pc_function_start ((frame_info)->pc); \
+ regmask = read_memory_integer (enter_addr+1, 1); \
+ localcount = ns32k_localcount (enter_addr); \
+ next_addr = (frame_info)->frame + localcount; \
+ for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
+ (frame_saved_regs).regs[regnum] \
+ = (regmask & 1) ? (next_addr -= 4) : 0; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4; \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4; \
+ (frame_saved_regs).regs[FP_REGNUM] \
+ = read_memory_integer ((frame_info)->frame, 4); }
+
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ sp = push_word (sp, read_register (regnum)); \
+ write_register (SP_REGNUM, sp); \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+ read_pc ())); \
+}
+
+/* This sequence of words is the instructions
+ enter 0xff,0 82 ff 00
+ jsr @0x00010203 7f ae c0 01 02 03
+ adjspd 0x69696969 7f a5 01 02 03 04
+ bpt f2
+ Note this is 16 bytes. */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET 3
+#define CALL_DUMMY_LENGTH 16
+#define CALL_DUMMY_ADDR 5
+#define CALL_DUMMY_NARGS 11
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ int flipped = fun | 0xc0000000; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
+ flipped = - nargs * 4; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
+}
--- /dev/null
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (TARGET_BYTE_ORDER)
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* Floating point is IEEE compliant */
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+/*#define NAMES_HAVE_UNDERSCORE*/
+
+/* Debugger information will be in mips' format */
+
+#define READ_MIPS_FORMAT
+
+/* File format is coff, but with additions */
+
+#define COFF_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) pc = mips_skip_prologue(pc)
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) read_register(RA_REGNUM)
+
+/* Are we currently handling a signal */
+
+#define IN_SIGTRAMP(pc, name) in_sigtramp(pc, name)
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0x7ffff000)
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+#define BIG_ENDIAN 4321
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BREAKPOINT {0, 0x5, 0, 0xd}
+#else
+#define BREAKPOINT {0xd, 0, 0x5, 0}
+#endif
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. "j ra" on mips. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0x3e00008)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p,l) isa_NAN(p,l)
+
+/* Say how long (all) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 73
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+ { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
+ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
+ "sr", "lo", "hi", "bad", "cause","pc", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
+ "fsr", "fir", "fp" \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define SP_REGNUM 29 /* Contains address of top of stack */
+#define PC_REGNUM 37 /* Contains program counter */
+#define RA_REGNUM 31 /* Contains return address value */
+#define PS_REGNUM 32 /* Contains processor status */
+#define HI_REGNUM 34 /* Multiple/divide temp */
+#define LO_REGNUM 33 /* ... */
+#define FP0_REGNUM 38 /* Floating point register 0 (single float) */
+#define FCRCS_REGNUM 70 /* FP control/status */
+#define FCRIR_REGNUM 71 /* FP implementation/revision */
+#define FP_REGNUM 72 /* Pseudo register that contains true address of executing stack frame */
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+ of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum) mips_do_registers_info(_regnum)
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ if (blockend == 0) { \
+ if (regno < 38) addr = (NBPG*UPAGES) + (regno - 38)*sizeof(int);\
+ else addr = 0; /* ..somewhere in the pcb */ \
+ } else if (regno < 32) addr = regno; \
+ else if (regno == PC_REGNUM) addr = 96; \
+ else if (regno == 36) addr = 97; \
+ else if (regno == HI_REGNUM) addr = 98; \
+ else if (regno == LO_REGNUM) addr = 99; \
+ else if (regno == FCRCS_REGNUM) addr = 100; \
+ else if (regno == FCRIR_REGNUM) addr = 101; \
+ else if (regno >= FP0_REGNUM) addr = regno - (FP0_REGNUM-32);\
+ else addr = 0;
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On mips, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+ for register N. On mips, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(addr, sp) \
+ { sp = push_word(sp, addr);}
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. XXX floats */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 2), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF+16))
+
+/* Structures are returned by ref in extra arg0 */
+#define USE_STRUCT_CONVENTION(gcc_p, type) 1
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+#define FRAME_CHAIN(thisframe) (FRAME_ADDR)mips_frame_chain(thisframe)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+/* We handle this differently for mips, and maybe we should not */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) = 0;}
+
+/* Saved Pc. */
+
+#define FRAME_SAVED_PC(FRAME) (mips_frame_saved_pc(FRAME))
+
+#define FRAME_ARGS_ADDRESS(fi) (fi)->frame
+
+#define FRAME_LOCALS_ADDRESS(fi) (fi)->frame
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(num, fi) (num = mips_frame_num_args(fi))
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) ( \
+ (frame_saved_regs) = *(frame_info)->saved_regs, \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame)
+
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Stack has strict alignment. However, use PUSH_ARGUMENTS
+ to take care of it. */
+/*#define STACK_ALIGN(addr) (((addr)+3)&~3)*/
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME mips_push_dummy_frame()
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME mips_pop_frame()
+
+#define MK_OP(op,rs,rt,offset) (((op)<<26)|((rs)<<21)|((rt)<<16)|(offset))
+#define CALL_DUMMY_SIZE (16*4)
+#define Dest_Reg 2
+#define CALL_DUMMY {\
+ MK_OP(0,RA_REGNUM,0,8), /* jr $ra # Fake ABOUT_TO_RETURN ...*/\
+ 0, /* nop # ... to stop raw backtrace*/\
+ 0x27bd0000, /* addu sp,?0 # Pseudo prologue */\
+/* Start here: */\
+ MK_OP(061,SP_REGNUM,12,0), /* lwc1 $f12,0(sp) # Reload first 4 args*/\
+ MK_OP(061,SP_REGNUM,13,4), /* lwc1 $f13,4(sp) */\
+ MK_OP(061,SP_REGNUM,14,8), /* lwc1 $f14,8(sp) */\
+ MK_OP(061,SP_REGNUM,15,12), /* lwc1 $f15,12(sp) */\
+ MK_OP(043,SP_REGNUM,4,0), /* lw $r4,0(sp) # Re-load FP regs*/\
+ MK_OP(043,SP_REGNUM,5,4), /* lw $r5,4(sp) */\
+ MK_OP(043,SP_REGNUM,6,8), /* lw $r6,8(sp) */\
+ MK_OP(043,SP_REGNUM,7,12), /* lw $r7,12(sp) */\
+ (017<<26)| (Dest_Reg << 16), /* lui $r31,<target upper 16 bits>*/\
+ MK_OP(13,Dest_Reg,Dest_Reg,0), /* ori $r31,$r31,<lower 16 bits>*/ \
+ (Dest_Reg<<21) | (31<<11) | 9, /* jalr $r31 */\
+ MK_OP(043,SP_REGNUM,7,12), /* lw $r7,12(sp) */\
+ 0x5000d, /* bpt */\
+}
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, start_sp, fun, nargs, args, rettype, gcc_p)\
+ (((int*)dummyname)[11] |= (((unsigned long)(fun)) >> 16), \
+ ((int*)dummyname)[12] |= (unsigned short)(fun))
+
+/* Specific information about a procedure.
+ This overlays the MIPS's PDR records,
+ mipsread.c (ab)uses this to save memory */
+
+typedef struct mips_extra_func_info {
+ unsigned long adr; /* memory address of start of procedure */
+ long isym; /* pointer to procedure symbol */
+ long pad2; /* iline: start of line number entries*/
+ long regmask; /* save register mask */
+ long regoffset; /* save register offset */
+ long numargs; /* number of args to procedure (was iopt) */
+ long fregmask; /* save floating point register mask */
+ long fregoffset; /* save floating point register offset */
+ long framesize; /* frameoffset: frame size */
+ short framereg; /* frame pointer register */
+ short pcreg; /* offset or reg of return pc */
+ long lnLow; /* lowest line in the procedure */
+ long lnHigh; /* highest line in the procedure */
+ long pad3; /* cbLineOffset: byte offset for this procedure from the fd base */
+} *mips_extra_func_info_t;
+
+#define EXTRA_FRAME_INFO \
+ char *proc_desc; /* actually, a mips_extra_func_info_t */\
+ int num_args;\
+ struct frame_saved_regs *saved_regs;
+
+#define INIT_EXTRA_FRAME_INFO(fci) init_extra_frame_info(fci)
--- /dev/null
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* See following cpu type determination macro to get the machine type.
+
+Here is an m-news.h file for gdb. It supports the 68881 registers.
+ by hikichi@srava.sra.junet
+
+* Support Sun assembly format instead of Motorola one.
+* Ptrace for handling floating register has a bug(before NEWS OS version 2.2),
+* After NEWS OS version 3.2, some of ptrace's bug is fixed.
+ But we cannot change the floating register(see adb(1) in OS 3.2) yet. */
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Symbols on this machine are in DBX format. */
+#define READ_DBX_FORMAT
+
+/* Use to compute STACK_END_ADDR. */
+#define TARGET_UPAGES 2
+#define TARGET_NBPG 4096
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0x80000000 - TARGET_UPAGES * TARGET_NBPG)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+/* when it return the floating value, use the FP0 in NEWS. */
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM, \
+ ®BUF[REGISTER_BYTE (FP0_REGNUM)], VALBUF); \
+ } \
+ else \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE)); }
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+/* when it return the floating value, use the FP0 in NEWS. */
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ char raw_buf[REGISTER_RAW_SIZE (FP0_REGNUM)]; \
+ REGISTER_CONVERT_TO_RAW (FP0_REGNUM, VALBUF, raw_buf); \
+ write_register_bytes (FP0_REGNUM, \
+ raw_buf, REGISTER_RAW_SIZE (FP0_REGNUM)); \
+ } \
+ else \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)); }
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(val, fi) \
+{ register CORE_ADDR pc = FRAME_SAVED_PC (fi); \
+ register int insn = 0177777 & read_memory_integer (pc, 2); \
+ val = 0; \
+ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \
+ val = read_memory_integer (pc + 2, 2); \
+ else if ((insn & 0170777) == 0050217 /* addql #N, sp */ \
+ || (insn & 0170777) == 0050117) /* addqw */ \
+ { val = (insn >> 9) & 7; if (val == 0) val = 8; } \
+ else if (insn == 0157774) /* addal #WW, sp */ \
+ val = read_memory_integer (pc + 2, 4); \
+ val >>= 2; }
+
+/* Things needed for making the inferior call functions. */
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char raw_buffer[12]; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
+ sp = push_bytes (sp, raw_buffer, 12); } \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ char raw_buffer[12]; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ if (fsr.regs[regnum]) \
+ { read_memory (fsr.regs[regnum], raw_buffer, 12); \
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM), \
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ fmove.m #<f0-f7>,-(sp)
+ movem.l 0xfffc,-(sp) ;; no save a6(fp) and a7(sp)
+ clr.w -(sp)
+ move.w ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jbsr (#32323232)
+ add.l #69696969,sp
+ bpt
+ nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 20) = nargs * 4; \
+ *(int *)((char *) dummyname + 14) = fun; }
+\f
+#define HAVE_68881
+
+#include "tm-68k.h"
--- /dev/null
+/* Parameters for Intel 960 running NINDY monitor, for GDB, the GNU debugger.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation and Cygnus Support.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*****************************************************************************
+ * Definitions to target GDB to an i960 debugged over a serial line.
+ ******************************************************************************/
+
+#include "tm-i960.h"
+
+/* Override the standard gdb prompt when compiled for this target. */
+
+#define DEFAULT_PROMPT "(gdb960) "
+
+/* Additional command line options accepted by nindy gdb's, for handling
+ the remote-nindy.c interface. These should really be target-specific
+ rather than architecture-specific. */
+
+extern int nindy_old_protocol; /* nonzero if old NINDY serial protocol */
+extern int nindy_initial_brk; /* Send a BREAK to reset board first */
+extern char *nindy_ttyname; /* Name of serial port to talk to nindy */
+
+#define ADDITIONAL_OPTIONS \
+ {"O", 0, &nindy_old_protocol, 1}, \
+ {"brk", 0, &nindy_initial_brk, 1}, \
+ {"r", 1, 0, 1004}, /* 1004 is magic cookie for ADDL_CASES */
+
+#define ADDITIONAL_OPTION_CASES \
+ case 1004: /* -r option: remote nindy auto-start */ \
+ nindy_ttyname = optarg; \
+ break;
+
+#define ADDITIONAL_OPTION_HELP \
+ "\
+ -O Use old protocol to talk to a Nindy target\n\
+ -brk Send a break to a Nindy target to reset it.\n\
+ -r SERIAL Open remote Nindy session to SERIAL port.\n\
+"
+
+/* If specified on the command line, open tty for talking to nindy,
+ and download the executable file if one was specified. */
+
+#define ADDITIONAL_OPTION_HANDLER \
+ if (!setjmp (to_top_level) && nindy_ttyname) { \
+ nindy_open (nindy_ttyname, !batch); \
+ if ( !setjmp(to_top_level) && execarg ) { \
+ target_load (execarg, !batch); \
+ } \
+ }
+
+/* If configured for i960 target, we take control before main loop
+ and demand that we configure for a nindy target. */
+
+#define BEFORE_MAIN_LOOP_HOOK \
+ nindy_before_main_loop();
+
+/* Address of end of stack space.
+ * This probably doesn't matter for nindy, because it's only used
+ * in manipulation of core files, which we don't support.
+ */
+
+#define STACK_END_ADDR (0xfe000000)
+
+/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
+ and has no caller. In that case, FRAME_CHAIN_COMBINE is not used.
+
+ On the i960, each various target system type defines FRAME_CHAIN_VALID,
+ since it differs between NINDY and VxWorks, the two currently supported
+ targets types. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ nindy_frame_chain_valid (chain, thisframe)
+
+extern int nindy_frame_chain_valid(); /* See nindy-tdep.c */
+
+/* Sequence of bytes for breakpoint instruction */
+
+#define BREAKPOINT {0x00, 0x3e, 0x00, 0x66}
+
+/* Amount ip must be decremented by after a breakpoint.
+ * This is often the number of bytes in BREAKPOINT but not always.
+ */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Not needed, because we don't support core files:
+ * #define KERNEL_U_ADDR
+ * #define REGISTER_U_ADDR(addr, blockend, regno)
+ */
--- /dev/null
+/* Parameters for targeting on a Gould NP1, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define GOULD_NPL
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* N_ENTRY appears in libraries on Gould machines.
+ Don't know what 0xa4 is; it's mentioned in stab.h
+ but only in the sdb symbol list. */
+#define IGNORE_SYMBOL(type) (type == N_ENTRY || type == 0xa4)
+
+/* We don't want the extra gnu symbols on the machine;
+ they will interfere with the shared segment symbols. */
+#define NO_GNU_STABS
+
+/* Macro for text-offset and data info (in NPL a.out format). */
+#define TEXTINFO \
+ text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr); \
+ exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr)\
+ + exec_aouthdr.a_text
+
+/* Macro for number of symbol table entries */
+#define NUMBER_OF_SYMBOLS \
+ (coffhdr.f_nsyms)
+
+/* Macro for file-offset of symbol table (in NPL a.out format). */
+#define SYMBOL_TABLE_OFFSET \
+ N_SYMOFF (coffhdr)
+
+/* Macro for file-offset of string table (in NPL a.out format). */
+#define STRING_TABLE_OFFSET \
+ (N_STROFF (coffhdr))
+
+/* Macro to store the length of the string table data in INTO. */
+#define READ_STRING_TABLE_SIZE(INTO) \
+ { INTO = hdr.a_stsize; }
+
+/* Macro to declare variables to hold the file's header data. */
+#define DECLARE_FILE_HEADERS struct exec hdr; \
+ FILHDR coffhdr
+
+/* Macro to read the header data from descriptor DESC and validate it.
+ NAME is the file name, for error messages. */
+#define READ_FILE_HEADERS(DESC, NAME) \
+{ val = myread (DESC, &coffhdr, sizeof coffhdr); \
+ if (val < 0) \
+ perror_with_name (NAME); \
+ val = myread (DESC, &hdr, sizeof hdr); \
+ if (val < 0) \
+ perror_with_name (NAME); \
+ if (coffhdr.f_magic != GNP1MAGIC) \
+ error ("File \"%s\" not in coff executable format.", NAME); \
+ if (N_BADMAG (hdr)) \
+ error ("File \"%s\" not in executable format.", NAME); }
+
+/* Define COFF and other symbolic names needed on NP1 */
+#define NS32GMAGIC GNP1MAGIC
+#define NS32SMAGIC GPNMAGIC
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+#define READ_DBX_FORMAT
+
+/* Address of blocks in N_LBRAC and N_RBRAC symbols are absolute addresses,
+ not relative to start of source address. */
+#define BLOCK_ADDRESS_ABSOLUTE
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+#define FUNCTION_START_OFFSET 8
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. One NPL we can have one two startup
+ sequences depending on the size of the local stack:
+
+ Either:
+ "suabr b2, #"
+ of
+ "lil r4, #", "suabr b2, #(r4)"
+
+ "lwbr b6, #", "stw r1, 8(b2)"
+ Optional "stwbr b3, c(b2)"
+ Optional "trr r2,r7" (Gould first argument register passing)
+ or
+ Optional "stw r2,8(b3)" (Gould first argument register passing)
+ */
+#define SKIP_PROLOGUE(pc) { \
+ register int op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0xFA0B0000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0x59400000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0x5F000000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xD4820008) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0x5582000C) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } else { \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xd5030008) { \
+ pc += 4; \
+ } \
+ } \
+ } else { \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ } \
+ if ((op & 0xffff0000) == 0x59000000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0x5F000000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xD4820008) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0x5582000C) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } else { \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xd5030008) { \
+ pc += 4; \
+ } \
+ } \
+ } else { \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } \
+ } \
+ } \
+ } \
+ } \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. True on NPL! Return address is in R1.
+ The true return address is REALLY 4 past that location! */
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_register(R1_REGNUM) + 4)
+
+/* Address of end of stack space. */
+#define STACK_END_ADDR 0x7fffc000
+
+/* Stack grows downward. */
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction.
+ This is padded out to the size of a machine word. When it was just
+ {0x28, 0x09} it gave problems if hit breakpoint on returning from a
+ function call. */
+#define BREAKPOINT {0x28, 0x09, 0x0, 0x0}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+#define DECR_PC_AFTER_BREAK 2
+
+/* Nonzero if instruction at PC is a return instruction. "bu 4(r1)" */
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0x40100004)
+
+/* Return 1 if P points to an invalid floating point value. */
+#define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are. */
+#define REGISTER_TYPE long
+
+/* Size of bytes of vector register (NP1 only), 32 elements * sizeof(int) */
+#define VR_SIZE 128
+
+/* Number of machine registers */
+#define NUM_REGS 27
+#define NUM_GEN_REGS 16
+#define NUM_CPU_REGS 4
+#define NUM_VECTOR_REGS 7
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+#define REGISTER_NAMES { \
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \
+ "sp", "ps", "pc", "ve", \
+ "v1", "v2", "v3", "v4", "v5", "v6", "v7", \
+}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+#define R1_REGNUM 1 /* Gr1 => return address of caller */
+#define R2_REGNUM 2 /* Gr2 => return value from function */
+#define R4_REGNUM 4 /* Gr4 => register save area */
+#define R5_REGNUM 5 /* Gr5 => register save area */
+#define R6_REGNUM 6 /* Gr6 => register save area */
+#define R7_REGNUM 7 /* Gr7 => register save area */
+#define B1_REGNUM 9 /* Br1 => start of this code routine */
+#define SP_REGNUM 10 /* Br2 == (sp) */
+#define AP_REGNUM 11 /* Br3 == (ap) */
+#define FP_REGNUM 16 /* A copy of Br2 saved in trap */
+#define PS_REGNUM 17 /* Contains processor status */
+#define PC_REGNUM 18 /* Contains program counter */
+#define VE_REGNUM 19 /* Vector end (user setup) register */
+#define V1_REGNUM 20 /* First vector register */
+#define V7_REGNUM 26 /* First vector register */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES \
+ (NUM_GEN_REGS*4 + NUM_VECTOR_REGS*VR_SIZE + NUM_CPU_REGS*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+#define REGISTER_BYTE(N) \
+ (((N) < V1_REGNUM) ? ((N) * 4) : (((N) - V1_REGNUM) * VR_SIZE) + 80)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the NP1, all normal regs are 4 bytes, but
+ the vector registers are VR_SIZE*4 bytes long. */
+#define REGISTER_RAW_SIZE(N) \
+ (((N) < V1_REGNUM) ? 4 : VR_SIZE)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the NP1, all regs are 4 bytes. */
+#define REGISTER_VIRTUAL_SIZE(N) \
+ (((N) < V1_REGNUM) ? 4 : VR_SIZE)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+#define MAX_REGISTER_RAW_SIZE VR_SIZE
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+#define MAX_REGISTER_VIRTUAL_SIZE VR_SIZE
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) > VE_REGNUM ? builtin_type_np1_vector : builtin_type_int)
+extern struct type *builtin_type_np1_vector;
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ On this machine this is a no-op, because gcc isn't used on it
+ yet. So this calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) push_word(SP + 8, ADDR)
+
+/* Extract from an arrary REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (((int *)(REGBUF)) + 2, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (R2_REGNUM), VALBUF, \
+ TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*((int *)(REGBUF) + 2))
+
+/* Both gcc and cc return small structs in registers (i.e. in GDB
+ terminology, small structs don't use the struct return convention). */
+#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH(type) > 8)
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the NPL, the frame's norminal address is Br2 and the
+ previous routines frame is up the stack X bytes, where X is the
+ value stored in the code function header xA(Br1). */
+#define FRAME_CHAIN(thisframe) (findframe(thisframe))
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && chain != (thisframe)->frame)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) \
+ (chain)
+
+/* Define other aspects of the stack frame on NPL. */
+#define FRAME_SAVED_PC(FRAME) \
+ (read_memory_integer ((FRAME)->frame + 8, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ ((fi)->next_frame ? \
+ read_memory_integer ((fi)->frame + 12, 4) : \
+ read_register (AP_REGNUM))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can check the stab info to see how
+ many arg we have. No info in stack will tell us */
+#define FRAME_NUM_ARGS(val,fi) (val = findarg(fi))
+
+/* Return number of bytes at start of arglist that are not really args. */
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ (frame_saved_regs).regs[SP_REGNUM] = framechain (frame_info); \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30; \
+ (frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34; \
+ (frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38; \
+ (frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C; \
+}
+\f
+/* Things needed for making the inferior call functions. */
+
+#define CANNOT_EXECUTE_STACK
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ for (regnum = 0; regnum < FP_REGNUM; regnum++) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ write_register (SP_REGNUM, sp);}
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME \
+{ CORE_ADDR sp = read_register(SP_REGNUM); \
+ REGISTER_TYPE reg; \
+ int regnum; \
+ for(regnum = 0;regnum < FP_REGNUM;regnum++){ \
+ sp-=sizeof(REGISTER_TYPE); \
+ read_memory(sp,®,sizeof(REGISTER_TYPE)); \
+ write_register(regnum,reg);} \
+ sp-=sizeof(REGISTER_TYPE); \
+ read_memory(sp,®,sizeof(REGISTER_TYPE)); \
+ write_register(PS_REGNUM,reg); \
+ sp-=sizeof(REGISTER_TYPE); \
+ read_memory(sp,®,sizeof(REGISTER_TYPE)); \
+ write_register(PC_REGNUM,reg);}
+
+/* MJD - Size of dummy frame pushed onto stack by PUSH_DUMMY_FRAME */
+
+#define DUMMY_FRAME_SIZE (0x48)
+
+/* MJD - The sequence of words in the instructions is
+ halt
+ halt
+ halt
+ halt
+ subr b2,stack size,0 grab stack space for dummy call
+ labr b3,x0(b2),0 set AP_REGNUM to point at arguments
+ lw r2,x8(b3),0 load r2 with first argument
+ lwbr b1,arguments size(b2),0 load address of function to be called
+ brlnk r1,x8(b1),0 call function
+ halt
+ halt
+ labr b2,stack size(b2),0 give back stack
+ break break
+ */
+
+#define CALL_DUMMY {0x00000000, \
+ 0x00000000, \
+ 0x59000000, \
+ 0x598a0000, \
+ 0xb5030008, \
+ 0x5c820000, \
+ 0x44810008, \
+ 0x00000000, \
+ 0x590a0000, \
+ 0x28090000 }
+
+#define CALL_DUMMY_LENGTH 40
+
+#define CALL_DUMMY_START_OFFSET 8
+
+#define CALL_DUMMY_STACK_ADJUST 8
+
+/* MJD - Fixup CALL_DUMMY for the specific function call.
+ OK heres the problems
+ 1) On a trap there are two copies of the stack pointer, one in SP_REGNUM
+ which is read/write and one in FP_REGNUM which is only read. It seems
+ that when restarting the GOULD NP1 uses FP_REGNUM's value.
+ 2) Loading function address into b1 looks a bit difficult if bigger than
+ 0x0000fffc, infact from what I can tell the compiler sets up table of
+ function address in base3 through which function calls are referenced.
+
+ OK my solutions
+ Calculate the size of the dummy stack frame and do adjustments of
+ SP_REGNUM in the dummy call.
+ Push function address onto the stack and load it in the dummy call
+ */
+
+#define FIX_CALL_DUMMY(dummyname, sp, fun, nargs, args, type, gcc_p) \
+ { int i;\
+ int arg_len = 0, total_len;\
+ old_sp = push_word(old_sp,fun);\
+ for(i = nargs - 1;i >= 0;i--)\
+ arg_len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));\
+ if(struct_return)\
+ arg_len += TYPE_LENGTH(value_type);\
+ total_len = DUMMY_FRAME_SIZE+CALL_DUMMY_STACK_ADJUST+4+arg_len;\
+ dummyname[0] += total_len;\
+ dummyname[2] += total_len;\
+ dummyname[5] += arg_len+CALL_DUMMY_STACK_ADJUST;\
+ dummyname[8] += total_len;}
+
+/* MJD - So the stack should end up looking like this
+
+ | Normal stack frame |
+ | from normal program |
+ | flow |
+ +---------------------+ <- Final sp - 0x08 - argument size
+ | | - 0x4 - dummy_frame_size
+ | Pushed dummy frame |
+ | b0-b7, r0-r7 |
+ | pc and ps |
+ | |
+ +---------------------+
+ | Function address |
+ +---------------------+ <- Final sp - 0x8 - arguments size
+ | |
+ | |
+ | |
+ | Arguments to |
+ | Function |
+ | |
+ | |
+ | |
+ +---------------------+ <- Final sp - 0x8
+ | Dummy_stack_adjust |
+ +---------------------+ <- Final sp
+ | |
+ | where call will |
+ | build frame |
+*/
--- /dev/null
+/* Parameters for targe of a Gould Powernode, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define GOULD_PN
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* This code appears in libraries on Gould machines. Ignore it. */
+#define IGNORE_SYMBOL(type) (type == N_ENTRY)
+
+/* We don't want the extra gnu symbols on the machine;
+ they will interfere with the shared segment symbols. */
+#define NO_GNU_STABS
+
+/* Macro for text-offset and data info (in PN a.out format). */
+#define TEXTINFO \
+ text_offset = N_TXTOFF (exec_coffhdr); \
+ exec_data_offset = N_TXTOFF (exec_coffhdr) \
+ + exec_aouthdr.a_text
+
+/* Macro for number of symbol table entries */
+#define END_OF_TEXT_DEFAULT \
+ (0xffffff)
+
+/* Macro for number of symbol table entries */
+#define NUMBER_OF_SYMBOLS \
+ (coffhdr.f_nsyms)
+
+/* Macro for file-offset of symbol table (in usual a.out format). */
+#define SYMBOL_TABLE_OFFSET \
+ N_SYMOFF (coffhdr)
+
+/* Macro for file-offset of string table (in usual a.out format). */
+#define STRING_TABLE_OFFSET \
+ (N_STROFF (coffhdr) + sizeof(int))
+
+/* Macro to store the length of the string table data in INTO. */
+#define READ_STRING_TABLE_SIZE(INTO) \
+ { INTO = hdr.a_stsize; }
+
+/* Macro to declare variables to hold the file's header data. */
+#define DECLARE_FILE_HEADERS struct old_exec hdr; \
+ FILHDR coffhdr
+
+/* Macro to read the header data from descriptor DESC and validate it.
+ NAME is the file name, for error messages. */
+#define READ_FILE_HEADERS(DESC, NAME) \
+{ val = myread (DESC, &coffhdr, sizeof coffhdr); \
+ if (val < 0) \
+ perror_with_name (NAME); \
+ val = myread (DESC, &hdr, sizeof hdr); \
+ if (val < 0) \
+ perror_with_name (NAME); \
+ if (coffhdr.f_magic != GNP1MAGIC) \
+ error ("File \"%s\" not in coff executable format.", NAME); \
+ if (N_BADMAG (hdr)) \
+ error ("File \"%s\" not in executable format.", NAME); }
+
+/* Define COFF and other symbolic names needed on NP1 */
+#define NS32GMAGIC GDPMAGIC
+#define NS32SMAGIC PN_MAGIC
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+#define FUNCTION_START_OFFSET 4
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. One PN we can have one or two startup
+ sequences depending on the size of the local stack:
+
+ Either:
+ "suabr b2, #"
+ of
+ "lil r4, #", "suabr b2, #(r4)"
+
+ "lwbr b6, #", "stw r1, 8(b2)"
+ Optional "stwbr b3, c(b2)"
+ Optional "trr r2,r7" (Gould first argument register passing)
+ or
+ Optional "stw r2,8(b3)" (Gould first argument register passing)
+ */
+#define SKIP_PROLOGUE(pc) { \
+ register int op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0x580B0000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0x59400000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0x5F000000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xD4820008) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0x5582000C) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } else { \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xd5030008) { \
+ pc += 4; \
+ } \
+ } \
+ } else { \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ } \
+ if ((op & 0xffff0000) == 0x59000000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if ((op & 0xffff0000) == 0x5F000000) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xD4820008) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0x5582000C) { \
+ pc += 4; \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } else { \
+ op = read_memory_integer ((pc), 4); \
+ if (op == 0xd5030008) { \
+ pc += 4; \
+ } \
+ } \
+ } else { \
+ op = read_memory_integer ((pc), 2); \
+ if (op == 0x2fa0) { \
+ pc += 2; \
+ } \
+ } \
+ } \
+ } \
+ } \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. True on PN! Return address is in R1.
+ Note: true return location is 4 bytes past R1! */
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_register(R1_REGNUM) + 4)
+
+/* Address of end of stack space. */
+#define STACK_END_ADDR 0x480000
+
+/* Stack grows downward. */
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+#define BREAKPOINT {0x28, 0x09}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+#define DECR_PC_AFTER_BREAK 2
+
+/* Nonzero if instruction at PC is a return instruction. "bu 4(r1)" */
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0xEC100004)
+
+/* Return 1 if P points to an invalid floating point value. */
+#define INVALID_FLOAT(p, len) ((*(short *)p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are. */
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+#define NUM_REGS 19
+#define NUM_GEN_REGS 16
+#define NUM_CPU_REGS 3
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+#define REGISTER_NAMES { \
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \
+ "sp", "ps", "pc", \
+}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+#define R1_REGNUM 1 /* Gr1 => return address of caller */
+#define R4_REGNUM 4 /* Gr4 => register save area */
+#define R5_REGNUM 5 /* Gr5 => register save area */
+#define R6_REGNUM 6 /* Gr6 => register save area */
+#define R7_REGNUM 7 /* Gr7 => register save area */
+#define B1_REGNUM 9 /* Br1 => start of this code routine */
+#define FP_REGNUM 10 /* Br2 == (sp) */
+#define AP_REGNUM 11 /* Br3 == (ap) */
+#define SP_REGNUM 16 /* A copy of Br2 saved in trap */
+#define PS_REGNUM 17 /* Contains processor status */
+#define PC_REGNUM 18 /* Contains program counter */
+
+/* This is a piece of magic that is given a register number REGNO
+ and as BLOCKEND the address in the system of the end of the user structure
+ and stores in ADDR the address in the kernel or core dump
+ of that register. */
+#define REGISTER_U_ADDR(addr, blockend, regno) { \
+ addr = blockend + regno * 4; \
+ if (regno == PC_REGNUM) addr = blockend - 8 * 4; \
+ if (regno == PS_REGNUM) addr = blockend - 7 * 4; \
+ if (regno == SP_REGNUM) addr = blockend - 6 * 4; \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_GEN_REGS*4 + NUM_CPU_REGS*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the PN, all normal regs are 4 bytes. */
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the PN, all regs are 4 bytes. */
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+#define MAX_REGISTER_RAW_SIZE (4)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+#define MAX_REGISTER_VIRTUAL_SIZE (4)
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_RAW_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ On this machine this is a no-op, because gcc isn't used on it
+ yet. So this calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an arrary REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the NPL, the frame's norminal address is Br2 and the
+ previous routines frame is up the stack X bytes, where X is the
+ value stored in the code function header xA(Br1). */
+#define FRAME_CHAIN(thisframe) (findframe(thisframe))
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && chain != (thisframe)->frame)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) \
+ (chain)
+
+/* Define other aspects of the stack frame on NPL. */
+#define FRAME_SAVED_PC(frame) \
+ (read_memory_integer ((frame)->frame + 8, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ ((fi)->next_frame ? \
+ read_memory_integer ((fi)->frame + 12, 4) : \
+ read_register (AP_REGNUM))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame + 80)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can check the stab info to see how
+ many arg we have. No info in stack will tell us */
+#define FRAME_NUM_ARGS(val,fi) (val = findarg(fi))
+
+/* Return number of bytes at start of arglist that are not really args. */
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[R4_REGNUM] = (frame_info)->frame + 0x30; \
+ (frame_saved_regs).regs[R5_REGNUM] = (frame_info)->frame + 0x34; \
+ (frame_saved_regs).regs[R6_REGNUM] = (frame_info)->frame + 0x38; \
+ (frame_saved_regs).regs[R7_REGNUM] = (frame_info)->frame + 0x3C; \
+}
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
+ read_pc ())); }
+
+/* This sequence of words is the instructions:
+ halt
+ halt
+ halt
+ halt
+ suabr b2, #<stacksize>
+ lwbr b6, #con
+ stw r1, 8(b2) - save caller address, do we care?
+ lw r2, 60(b2) - arg1
+ labr b3, 50(b2)
+ std r4, 30(b2) - save r4-r7
+ std r6, 38(b2)
+ lwbr b1, #<func> - load function call address
+ brlnk r1, 8(b1) - call function
+ halt
+ halt
+ ld r4, 30(b2) - restore r4-r7
+ ld r6, 38(b2)
+
+ Setup our stack frame, load argumemts, call and then restore registers.
+*/
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 20) = nargs * 4; \
+ *(int *)((char *) dummyname + 14) = fun; }
--- /dev/null
+/* Definitions to make GDB run on a Pyramidax under OSx 4.0 (4.2bsd).
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Traditional Unix virtual address spaces have thre regions: text,
+ data and stack. The text, initialised data, and uninitialised data
+ are represented in separate segments of the a.out file.
+ When a process dumps core, the data and stack regions are written
+ to a core file. This gives a debugger enough information to
+ reconstruct (and debug) the virtual address space at the time of
+ the coredump.
+ Pyramids have an distinct fourth region of the virtual address
+ space, in which the contents of the windowed registers are stacked
+ in fixed-size frames. Pyramid refer to this region as the control
+ stack. Each call (or trap) automatically allocates a new register
+ frame; each return deallocates the current frame and restores the
+ windowed registers to their values before the call.
+
+ When dumping core, the control stack is written to a core files as
+ a third segment. The core-handling functions need to know to deal
+ with it. */
+/* Tell core.c there is an extra segment. */
+#define REG_STACK_SEGMENT
+
+/* Floating point is IEEE compatible on most Pyramid hardware
+ (Older processors do not have IEEE NaNs). */
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+/* FIXME -- do we want to skip insns to allocate the local frame?
+ If so, what do they look like?
+ This is becoming harder, since tege@sics.SE wants to change
+ gcc to not output a prologue when no frame is needed. */
+#define SKIP_PROLOGUE(pc) do {} while (0)
+
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
+
+/* Address of end of stack space. */
+/* This seems to be right for the 90x comp.vuw.ac.nz.
+ The correct value at any site may be a function of the configured
+ maximum control stack depth. If so, I don't know where the
+ control-stack depth is configured, so I can't #include it here. */
+#define STACK_END_ADDR (0xc00cc000)
+
+/* Register window stack (Control stack) stack definitions
+ - Address of beginning of control stack.
+ - size of control stack frame
+ (Note that since crts0 is usually the first function called,
+ main()'s control stack is one frame (0x80 bytes) beyond this value. */
+
+#define CONTROL_STACK_ADDR (0xc00cd000)
+
+/* Bytes in a register window -- 16 parameter regs, 16 local regs
+ for each call, is 32 regs * 4 bytes */
+
+#define CONTROL_STACK_FRAME_SIZE (32*4)
+
+/* FIXME. On a pyr, Data Stack grows downward; control stack goes upwards.
+ Which direction should we use for INNER_THAN, PC_INNER_THAN ?? */
+
+#define INNER_THAN <
+#define PC_INNER_THAN >
+
+/* Stack has strict alignment. */
+
+#define STACK_ALIGN(ADDR) (((ADDR)+3)&-4)
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xf0, 00, 00, 00}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction.
+ On a pyr, this is either "ret" or "retd".
+ It would be friendly to check that any "retd" always had an
+ argument of 0, since anything else is invalid. */
+
+#define ABOUT_TO_RETURN(pc) \
+(((read_memory_integer (pc, 2) & 0x3ff0) == 0x3090) || \
+ ((read_memory_integer (pc, 2) & 0x0ff0) == 0x00a0))
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the Vax. */
+/* FIXME -- this is ok for a vax, bad for big-endian ieee format.
+ I would use the definition for a Sun; but it is no better! */
+
+#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+/* pyramids have 64, plus one for the PSW; plus perhaps one more for the
+ kernel stack pointer (ksp) and control-stack pointer (CSP) */
+
+#define NUM_REGS 67
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+{"gr0", "gr1", "gr2", "gr3", "gr4", "gr5", "gr6", "gr7", \
+ "gr8", "gr9", "gr10", "gr11", "logpsw", "cfp", "sp", "pc", \
+ "pr0", "pr1", "pr2", "pr3", "pr4", "pr5", "pr6", "pr7", \
+ "pr8", "pr9", "pr10", "pr11", "pr12", "pr13", "pr14", "pr15", \
+ "lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", \
+ "lr8", "lr9", "lr10", "lr11", "lr12", "lr13", "lr14", "lr15", \
+ "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7", \
+ "tr8", "tr9", "tr10", "tr11", "tr12", "tr13", "tr14", "tr15", \
+ "psw", "ksp", "csp"}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+/* pseudo-registers: */
+#define PS_REGNUM 64 /* Contains processor status */
+#define PSW_REGNUM 64 /* Contains current psw, whatever it is.*/
+#define CSP_REGNUM 65 /* address of this control stack frame*/
+#define KSP_REGNUM 66 /* Contains process's Kernel Stack Pointer */
+
+#define CFP_REGNUM 13 /* Current data-stack frame ptr */
+#define TR0_REGNUM 48 /* After function call, contains
+ function result */
+
+/* Registers interesting to the machine-independent part of gdb*/
+
+#define FP_REGNUM CSP_REGNUM /* Contains address of executing (control)
+ stack frame */
+#define SP_REGNUM 14 /* Contains address of top of stack -??*/
+#define PC_REGNUM 15 /* Contains program counter */
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+ of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum) pyr_do_registers_info(_regnum)
+
+/* need this so we can find the global registers: they never get saved. */
+extern unsigned int global_reg_offset;
+extern unsigned int last_frame_offset;
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (NUM_REGS*4)
+
+/* the Pyramid has register windows. */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system? A yes answer
+ implies that 1) The name of this register will not be the same in
+ other frames, and 2) This register is automatically "saved" (out
+ registers shifting into ins counts) upon subroutine calls and thus
+ there is no need to search more than one stack frame for it. */
+
+#define REGISTER_IN_WINDOW_P(regnum) \
+ ((regnum) >= 16 && (regnum) < 64)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the Pyramid, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the Pyramid, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* FIXME: It seems impossible for both EXTRACT_RETURN_VALUE and
+ STORE_RETURN_VALUE to be correct. */
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+/****FIXME****/
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (TR0_REGNUM, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+/* Note that on a register-windowing machine (eg, Pyr, SPARC), this is
+ where the value is found after the function call -- ie, it should
+ correspond to GNU CC's FUNCTION_VALUE rather than FUNCTION_OUTGOING_VALUE.*/
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (((int *)(REGBUF))+TR0_REGNUM, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+/* on pyrs, values are returned in */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE(TR0_REGNUM), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+/* FIXME */
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ ( ((int *)(REGBUF)) [TR0_REGNUM])
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+#define EXTRA_FRAME_INFO \
+ FRAME_ADDR bottom; \
+ CORE_ADDR frame_cfp; \
+ CORE_ADDR frame_window_addr;
+
+#define INIT_EXTRA_FRAME_INFO(fci) \
+do { \
+ (fci)->frame_window_addr = (fci)->frame; \
+ (fci)->bottom = \
+ ((fci)->next ? \
+ ((fci)->frame == (fci)->next_frame ? \
+ (fci)->next->bottom : (fci)->next->frame) : \
+ read_register (SP_REGNUM)); \
+ (fci)->frame_cfp = \
+ read_register (CFP_REGNUM); \
+ /***fprintf (stderr, \
+ "[[creating new frame for %0x,pc=%0x,csp=%0x]]\n", \
+ (fci)->frame, (fci)->pc,(fci)->frame_cfp);*/ \
+} while (0);
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the pyr, the frame's nominal address is the address
+ of parameter register 0. The previous frame is found 32 words up. */
+
+#define FRAME_CHAIN(thisframe) \
+ ( (thisframe) -> frame - CONTROL_STACK_FRAME_SIZE)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+ /*((thisframe) >= CONTROL_STACK_ADDR))*/
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0.
+
+ I do not understand what this means on a Pyramid, where functions
+ *always* have a control-stack frame, but may or may not have a
+ frame on the data stack. Since GBD uses the value of the
+ control stack pointer as its "address" of a frame, FRAMELESS
+ is always 1, so does not need to be defined. */
+
+
+/* Where is the PC for a specific frame */
+
+#define FRAME_SAVED_PC(fi) \
+ ((CORE_ADDR) (read_memory_integer ( (fi) -> frame + 60, 4)))
+
+/* There may be bugs in FRAME_ARGS_ADDRESS and FRAME_LOCALS_ADDRESS;
+ or there may be bugs in accessing the registers that break
+ their definitions.
+ Having the macros expand into functions makes them easier to debug.
+ When the bug is finally located, the inline macro defintions can
+ be un-#if 0ed, and frame_args_addr and frame_locals_address can
+ be deleted from pyr-dep.c */
+
+/* If the argument is on the stack, it will be here. */
+#define FRAME_ARGS_ADDRESS(fi) \
+ frame_args_addr(fi)
+
+#define FRAME_LOCALS_ADDRESS(fi) \
+ frame_locals_address(fi)
+
+/* The following definitions doesn't seem to work.
+ I don't understand why. */
+#if 0
+#define FRAME_ARGS_ADDRESS(fi) \
+ /*(FRAME_FP(fi) + (13*4))*/ (read_register (CFP_REGNUM))
+
+#define FRAME_LOCALS_ADDRESS(fi) \
+ ((fi)->frame +(16*4))
+
+#endif /* 0 */
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(val, fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ Note that on register window machines, we are currently making the
+ assumption that window registers are being saved somewhere in the
+ frame in which they are being used. If they are stored in an
+ inferior frame, find_saved_register will break.
+
+ On pyrs, frames of window registers are stored contiguously on a
+ separate stack. All window registers are always stored.
+ The pc and psw (gr15 and gr14) are also always saved: the call
+ insn saves them in pr15 and pr14 of the new frame (tr15,tr14 of the
+ old frame).
+ The data-stack frame pointer (CFP) is only saved in functions which
+ allocate a (data)stack frame (with "adsf"). We detect them by
+ looking at the first insn of the procedure.
+
+ Other non-window registers (gr0-gr11) are never saved. Pyramid's C
+ compiler and gcc currently ignore them, so it's not an issue. */
+
+#define FRAME_FIND_SAVED_REGS(fi_p, frame_saved_regs) \
+{ register int regnum; \
+ register CORE_ADDR pc; \
+ register CORE_ADDR fn_start_pc; \
+ register int first_insn; \
+ register CORE_ADDR prev_cf_addr; \
+ register int window_ptr; \
+ FRAME fid = FRAME_INFO_ID (fi_p); \
+ if (!fid) fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); \
+ bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \
+ \
+ window_ptr = prev_cf_addr = FRAME_FP(fi_p); \
+ \
+ for (regnum = 16 ; regnum < 64; regnum++,window_ptr+=4) \
+ { \
+ (frame_saved_regs).regs[regnum] = window_ptr; \
+ } \
+ \
+ /* In each window, psw, and pc are "saved" in tr14,tr15. */ \
+ /*** psw is sometimes saved in gr12 (so sez <sys/pcb.h>) */ \
+ (frame_saved_regs).regs[PS_REGNUM] = FRAME_FP(fi_p) + (14*4); \
+ \
+/*(frame_saved_regs).regs[PC_REGNUM] = (frame_saved_regs).regs[31];*/ \
+ (frame_saved_regs).regs[PC_REGNUM] = FRAME_FP(fi_p) + ((15+32)*4); \
+ \
+ /* Functions that allocate a frame save sp *where*? */ \
+/*first_insn = read_memory_integer (get_pc_function_start ((fi_p)->pc),4); */ \
+ \
+ fn_start_pc = (get_pc_function_start ((fi_p)->pc)); \
+ first_insn = read_memory_integer(fn_start_pc, 4); \
+ \
+ if (0x08 == ((first_insn >> 20) &0x0ff)) { \
+ /* NB: because WINDOW_REGISTER_P(cfp) is false, a saved cfp \
+ in this frame is only visible in this frame's callers. \
+ That means the cfp we mark saved is my caller's cfp, ie pr13. \
+ I don't understand why we don't have to do that for pc, too. */ \
+ \
+ (frame_saved_regs).regs[CFP_REGNUM] = FRAME_FP(fi_p)+(13*4); \
+ \
+ (frame_saved_regs).regs[SP_REGNUM] = \
+ read_memory_integer (FRAME_FP(fi_p)+((13+32)*4),4); \
+ } \
+ \
+/* \
+ *(frame_saved_regs).regs[CFP_REGNUM] = (frame_saved_regs).regs[61]; \
+ * (frame_saved_regs).regs[SP_REGNUM] = \
+ * read_memory_integer (FRAME_FP(fi_p)+((13+32)*4),4); \
+ */ \
+ \
+ (frame_saved_regs).regs[CSP_REGNUM] = prev_cf_addr; \
+}
+\f
+/* Things needed for making the inferior call functions. */
+#if 0
+/* These are all lies. These macro definitions are appropriate for a
+ SPARC. On a pyramid, pushing a dummy frame will
+ surely involve writing the control stack pointer,
+ then saving the pc. This requires a privileged instruction.
+ Maybe one day Pyramid can be persuaded to add a syscall to do this.
+ Until then, we are out of luck. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, 0); /* arglist */ \
+ for (regnum = 11; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+/* sp = push_word (sp, read_register (AP_REGNUM));*/ \
+ sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef) \
+ + 0x2fff0000); \
+ sp = push_word (sp, 0); \
+ write_register (SP_REGNUM, sp); \
+ write_register (FP_REGNUM, sp); \
+/* write_register (AP_REGNUM, sp + 17 * sizeof (int));*/ }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register int regnum; \
+ register int regmask = read_memory_integer (fp + 4, 4); \
+ write_register (PS_REGNUM, \
+ (regmask & 0xffff) \
+ | (read_register (PS_REGNUM) & 0xffff0000)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 16, 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp + 12, 4)); \
+/* write_register (AP_REGNUM, read_memory_integer (fp + 8, 4));*/ \
+ fp += 16; \
+ for (regnum = 0; regnum < 12; regnum++) \
+ if (regmask & (0x10000 << regnum)) \
+ write_register (regnum, read_memory_integer (fp += 4, 4)); \
+ fp = fp + 4 + ((regmask >> 30) & 3); \
+ if (regmask & 0x20000000) \
+ { regnum = read_memory_integer (fp, 4); \
+ fp += (regnum + 1) * 4; } \
+ write_register (SP_REGNUM, fp); \
+ set_current_frame (read_register (FP_REGNUM)); }
+
+/* This sequence of words is the instructions
+ calls #69, @#32323232
+ bpt
+ Note this is 8 bytes. */
+
+#define CALL_DUMMY {0x329f69fb, 0x03323232}
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *((char *) dummyname + 1) = nargs; \
+ *(int *)((char *) dummyname + 3) = fun; }
+#endif /* 0 */
+
+#define POP_FRAME \
+ { error ("The return command is not supported on this machine."); }
--- /dev/null
+/* Parameters for target machine of Sun 4, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com)
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Floating point is IEEE compatible. */
+#define IEEE_FLOAT
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* When passing a structure to a function, Sun cc passes the address
+ in a register, not the structure itself. It (under SunOS4) creates
+ two symbols, so we get a LOC_ARG saying the address is on the stack
+ (a lie, and a serious one since we don't know which register to
+ use), and a LOC_REGISTER saying that the struct is in a register
+ (sort of a lie, but fixable with REG_STRUCT_HAS_ADDR).
+
+ This still doesn't work if the argument is not one passed in a
+ register (i.e. it's the 7th or later argument). */
+#define REG_STRUCT_HAS_ADDR(gcc_p) (!(gcc_p))
+#define STRUCT_ARG_SYM_GARBAGE(gcc_p) (!(gcc_p))
+
+/* If Pcc says that a parameter is a short, it's a short. This is
+ because the parameter does get passed in in a register as an int,
+ but pcc puts it onto the stack frame as a short (not nailing
+ whatever else might be there. I'm not sure that I consider this
+ swift. Sigh.)
+
+ No, don't do this. The problem here is that pcc says that the
+ argument is in the upper half of the word reserved on the stack,
+ but puts it in the lower half. */
+/* #define BELIEVE_PCC_PROMOTION 1 */
+/* OK, I've added code to dbxread.c to deal with this case. */
+#define BELIEVE_PCC_PROMOTION_TYPE
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+ { pc = skip_prologue (pc); }
+extern CORE_ADDR skip_prologue ();
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+/* On the Sun 4 under SunOS, the compile will leave a fake insn which
+ encodes the structure size being returned. If we detect such
+ a fake insn, step past it. */
+
+#define PC_ADJUST(pc) ((read_memory_integer (pc + 8, 4) & 0xfffffe00) == 0 ? \
+ pc+12 : pc+8)
+
+#define SAVED_PC_AFTER_CALL(frame) PC_ADJUST (read_register (RP_REGNUM))
+
+/* Address of the end of stack space. We get this from the system
+ include files. */
+#include <sys/types.h>
+#include <machine/vmparam.h>
+#define STACK_END_ADDR USRSTACK
+
+#define INNER_THAN <
+
+/* Stack has strict alignment. */
+
+#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8)
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0x91, 0xd0, 0x20, 0x01}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. */
+/* For SPARC, this is either a "jmpl %o7+8,%g0" or "jmpl %i7+8,%g0".
+
+ Note: this does not work for functions returning structures under SunOS. */
+#define ABOUT_TO_RETURN(pc) \
+ ((read_memory_integer (pc, 4)|0x00040000) == 0x81c7e008)
+
+/* Return 1 if P points to an invalid floating point value. */
+
+#define INVALID_FLOAT(p, len) 0 /* Just a first guess; not checked */
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 72
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES \
+{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", \
+ "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
+ "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", \
+ \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
+ \
+ "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" };
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define G0_REGNUM 0 /* %g0 */
+#define G1_REGNUM 1 /* %g1 */
+#define O0_REGNUM 8 /* %o0 */
+#define SP_REGNUM 14 /* Contains address of top of stack, \
+ which is also the bottom of the frame. */
+#define RP_REGNUM 15 /* Contains return address value, *before* \
+ any windows get switched. */
+#define O7_REGNUM 15 /* Last local reg not saved on stack frame */
+#define L0_REGNUM 16 /* First local reg that's saved on stack frame
+ rather than in machine registers */
+#define I0_REGNUM 24 /* %i0 */
+#define FP_REGNUM 30 /* Contains address of executing stack frame */
+#define I7_REGNUM 31 /* Last local reg saved on stack frame */
+#define FP0_REGNUM 32 /* Floating point register 0 */
+#define Y_REGNUM 64 /* Temp register for multiplication, etc. */
+#define PS_REGNUM 65 /* Contains processor status */
+#define WIM_REGNUM 66 /* Window Invalid Mask (not really supported) */
+#define TBR_REGNUM 67 /* Trap Base Register (not really supported) */
+#define PC_REGNUM 68 /* Contains program counter */
+#define NPC_REGNUM 69 /* Contains next PC */
+#define FPS_REGNUM 70 /* Floating point status register */
+#define CPS_REGNUM 71 /* Coprocessor status register */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (32*4+32*4+8*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+/* ?? */
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* The SPARC processor has register windows. */
+
+#define HAVE_REGISTER_WINDOWS
+
+/* Is this register part of the register window system? A yes answer
+ implies that 1) The name of this register will not be the same in
+ other frames, and 2) This register is automatically "saved" (out
+ registers shifting into ins counts) upon subroutine calls and thus
+ there is no need to search more than one stack frame for it. */
+
+#define REGISTER_IN_WINDOW_P(regnum) \
+ ((regnum) >= 8 && (regnum) < 32)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+/* On the SPARC, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+/* On the SPARC, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), 4); }
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : \
+ builtin_type_int)
+
+/* Writing to %g0 is a noop (not an error or exception or anything like
+ that, however). */
+
+#define CANNOT_STORE_REGISTER(regno) ((regno) == G0_REGNUM)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { target_write_memory ((SP)+(16*4), (char *)&(ADDR), 4); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ { \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ { \
+ bcopy (((int *)(REGBUF))+FP0_REGNUM, \
+ (VALBUF), TYPE_LENGTH(TYPE)); \
+ } \
+ else \
+ bcopy (((int *)(REGBUF))+8, (VALBUF), TYPE_LENGTH (TYPE)); \
+ }
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+/* On sparc, values are returned in register %o0. */
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ /* Floating-point values are returned in the register pair */ \
+ /* formed by %f0 and %f1 (doubles are, anyway). */ \
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), (VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ else \
+ /* Other values are returned in register %o0. */ \
+ write_register_bytes (REGISTER_BYTE (O0_REGNUM), (VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
+ (read_memory_integer (((int *)(REGBUF))[SP_REGNUM]+(16*4), 4))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* I don't know whether this will work for cross-debugging, even if you
+ do get the right reg.h. */
+#include <machine/reg.h>
+
+#define GET_RWINDOW_REG(FRAME, REG) \
+ (read_memory_integer ((CORE_ADDR)&((struct rwindow *)FRAME)->REG, 4))
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the Sun 4, the frame-chain's nominal address
+ is held in the frame pointer register.
+
+ On the Sun4, the frame (in %fp) is %sp for the previous frame.
+ From the previous frame's %sp, we can find the previous frame's
+ %fp: it is in the save area just above the previous frame's %sp.
+
+ If we are setting up an arbitrary frame, we'll need to know where
+ it ends. Hence the following. This part of the frame cache
+ structure should be checked before it is assumed that this frame's
+ bottom is in the stack pointer.
+
+ If there isn't a frame below this one, the bottom of this frame is
+ in the stack pointer.
+
+ If there is a frame below this one, and the frame pointers are
+ identical, it's a leaf frame and the bottoms are the same also.
+
+ Otherwise the bottom of this frame is the top of the next frame. */
+
+#define EXTRA_FRAME_INFO FRAME_ADDR bottom;
+#define INIT_EXTRA_FRAME_INFO(fci) \
+ (fci)->bottom = \
+ ((fci)->next ? \
+ ((fci)->frame == (fci)->next_frame ? \
+ (fci)->next->bottom : (fci)->next->frame) : \
+ read_register (SP_REGNUM));
+
+#define FRAME_CHAIN(thisframe) \
+ GET_RWINDOW_REG ((thisframe)->frame, rw_in[6])
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+/* Where is the PC for a specific frame */
+
+#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
+CORE_ADDR frame_saved_pc ();
+
+/* If the argument is on the stack, it will be here. */
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_STRUCT_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Set VAL to the number of args passed to frame described by FI.
+ Can set VAL to -1, meaning no way to tell. */
+
+/* We can't tell how many args there are
+ now that the C compiler delays popping them. */
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 68
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ The actual code is in sparc-tdep.c so we can debug it sanely. */
+
+#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs) \
+ sparc_frame_find_saved_regs ((fi), &(frame_saved_regs))
+extern void sparc_frame_find_saved_regs ();
+\f
+/* Things needed for making the inferior call functions. */
+/*
+ * First of all, let me give my opinion of what the DUMMY_FRAME
+ * actually looks like.
+ *
+ * | |
+ * | |
+ * + - - - - - - - - - - - - - - - - +<-- fp (level 0)
+ * | |
+ * | |
+ * | |
+ * | |
+ * | Frame of innermost program |
+ * | function |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * |---------------------------------|<-- sp (level 0), fp (c)
+ * | |
+ * DUMMY | fp0-31 |
+ * | |
+ * | ------ |<-- fp - 0x80
+ * FRAME | g0-7 |<-- fp - 0xa0
+ * | i0-7 |<-- fp - 0xc0
+ * | other |<-- fp - 0xe0
+ * | ? |
+ * | ? |
+ * |---------------------------------|<-- sp' = fp - 0x140
+ * | |
+ * xcution start | |
+ * sp' + 0x94 -->| CALL_DUMMY (x code) |
+ * | |
+ * | |
+ * |---------------------------------|<-- sp'' = fp - 0x200
+ * | align sp to 8 byte boundary |
+ * | ==> args to fn <== |
+ * Room for | |
+ * i & l's + agg | CALL_DUMMY_STACK_ADJUST = 0x0x44|
+ * |---------------------------------|<-- final sp (variable)
+ * | |
+ * | Where function called will |
+ * | build frame. |
+ * | |
+ * | |
+ *
+ * I understand everything in this picture except what the space
+ * between fp - 0xe0 and fp - 0x140 is used for. Oh, and I don't
+ * understand why there's a large chunk of CALL_DUMMY that never gets
+ * executed (its function is superceeded by PUSH_DUMMY_FRAME; they
+ * are designed to do the same thing).
+ *
+ * PUSH_DUMMY_FRAME saves the registers above sp' and pushes the
+ * register file stack down one.
+ *
+ * call_function then writes CALL_DUMMY, pushes the args onto the
+ * stack, and adjusts the stack pointer.
+ *
+ * run_stack_dummy then starts execution (in the middle of
+ * CALL_DUMMY, as directed by call_function).
+ */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME sparc_push_dummy_frame ()
+#define POP_FRAME sparc_pop_frame ()
+
+void sparc_push_dummy_frame (), sparc_pop_frame ();
+/* This sequence of words is the instructions
+
+ save %sp,-0x140,%sp
+ std %f30,[%fp-0x08]
+ std %f28,[%fp-0x10]
+ std %f26,[%fp-0x18]
+ std %f24,[%fp-0x20]
+ std %f22,[%fp-0x28]
+ std %f20,[%fp-0x30]
+ std %f18,[%fp-0x38]
+ std %f16,[%fp-0x40]
+ std %f14,[%fp-0x48]
+ std %f12,[%fp-0x50]
+ std %f10,[%fp-0x58]
+ std %f8,[%fp-0x60]
+ std %f6,[%fp-0x68]
+ std %f4,[%fp-0x70]
+ std %f2,[%fp-0x78]
+ std %f0,[%fp-0x80]
+ std %g6,[%fp-0x88]
+ std %g4,[%fp-0x90]
+ std %g2,[%fp-0x98]
+ std %g0,[%fp-0xa0]
+ std %i6,[%fp-0xa8]
+ std %i4,[%fp-0xb0]
+ std %i2,[%fp-0xb8]
+ std %i0,[%fp-0xc0]
+ nop ! stcsr [%fp-0xc4]
+ nop ! stfsr [%fp-0xc8]
+ nop ! wr %npc,[%fp-0xcc]
+ nop ! wr %pc,[%fp-0xd0]
+ rd %tbr,%o0
+ st %o0,[%fp-0xd4]
+ rd %wim,%o1
+ st %o0,[%fp-0xd8]
+ rd %psr,%o0
+ st %o0,[%fp-0xdc]
+ rd %y,%o0
+ st %o0,[%fp-0xe0]
+
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following ld instruction. *../
+
+ ld [%sp+0x58],%o5
+ ld [%sp+0x54],%o4
+ ld [%sp+0x50],%o3
+ ld [%sp+0x4c],%o2
+ ld [%sp+0x48],%o1
+ call 0x00000000
+ ld [%sp+0x44],%o0
+ nop
+ ta 1
+ nop
+
+ note that this is 192 bytes, which is a multiple of 8 (not only 4) bytes.
+ note that the `call' insn is a relative, not an absolute call.
+ note that the `nop' at the end is needed to keep the trap from
+ clobbering things (if NPC pointed to garbage instead).
+
+We actually start executing at the `sethi', since the pushing of the
+registers (as arguments) is done by PUSH_DUMMY_FRAME. If this were
+real code, the arguments for the function called by the CALL would be
+pushed between the list of ST insns and the CALL, and we could allow
+it to execute through. But the arguments have to be pushed by GDB
+after the PUSH_DUMMY_FRAME is done, and we cannot allow these ST
+insns to be performed again, lest the registers saved be taken for
+arguments. */
+
+#define CALL_DUMMY { 0x9de3bee0, 0xfd3fbff8, 0xf93fbff0, 0xf53fbfe8, \
+ 0xf13fbfe0, 0xed3fbfd8, 0xe93fbfd0, 0xe53fbfc8, \
+ 0xe13fbfc0, 0xdd3fbfb8, 0xd93fbfb0, 0xd53fbfa8, \
+ 0xd13fbfa0, 0xcd3fbf98, 0xc93fbf90, 0xc53fbf88, \
+ 0xc13fbf80, 0xcc3fbf78, 0xc83fbf70, 0xc43fbf68, \
+ 0xc03fbf60, 0xfc3fbf58, 0xf83fbf50, 0xf43fbf48, \
+ 0xf03fbf40, 0x01000000, 0x01000000, 0x01000000, \
+ 0x01000000, 0x91580000, 0xd027bf50, 0x93500000, \
+ 0xd027bf4c, 0x91480000, 0xd027bf48, 0x91400000, \
+ 0xd027bf44, 0xda03a058, 0xd803a054, 0xd603a050, \
+ 0xd403a04c, 0xd203a048, 0x40000000, 0xd003a044, \
+ 0x01000000, 0x91d02001, 0x01000000, 0x01000000}
+
+#define CALL_DUMMY_LENGTH 192
+
+#define CALL_DUMMY_START_OFFSET 148
+
+#define CALL_DUMMY_STACK_ADJUST 68
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME.
+
+ For structs and unions, if the function was compiled with Sun cc,
+ it expects 'unimp' after the call. But gcc doesn't use that
+ (twisted) convention. So leave a nop there for gcc (FIX_CALL_DUMMY
+ can assume it is operating on a pristine CALL_DUMMY, not one that
+ has already been customized for a different function). */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ *(int *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \
+ if (!gcc_p \
+ && (TYPE_CODE (type) == TYPE_CODE_STRUCT \
+ || TYPE_CODE (type) == TYPE_CODE_UNION)) \
+ *(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff); \
+}
+
+\f
+/* Sparc has no reliable single step ptrace call */
+
+#define NO_SINGLE_STEP 1
+extern void single_step ();
+
+/* We need two arguments (in general) to the "info frame" command.
+ Note that the definition of this macro implies that there exists a
+ function "setup_arbitrary_frame" in mach-dep.c */
+
+#define FRAME_SPECIFICATION_DYADIC
+
+/* To print every pair of float registers as a double, we use this hook. */
+
+#define PRINT_REGISTER_HOOK(regno) \
+ if (((regno) >= FP0_REGNUM) \
+ && ((regno) < FP0_REGNUM + 32) \
+ && (0 == (regno & 1))) { \
+ char doublereg[8]; /* two float regs */ \
+ if (!read_relative_register_raw_bytes (i , doublereg ) \
+ && !read_relative_register_raw_bytes (i+1, doublereg+4)) { \
+ printf("\t"); \
+ print_floating (doublereg, builtin_type_double, stdout); \
+ } \
+ }
+
--- /dev/null
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "m-68k.h"
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Address of the end of stack space. We get this from the system
+ include files. */
+#include <sys/types.h>
+#include <machine/vmparam.h>
+#define STACK_END_ADDR USRSTACK
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),\
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ moveml 0xfffc,-(sp)
+ clrw -(sp)
+ movew ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jsr @#32323232
+ addl #69696969,sp
+ bpt
+ nop
+Note this is 24 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 24
+
+#define CALL_DUMMY_START_OFFSET 8
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 16) = nargs * 4; \
+ *(int *)((char *) dummyname + 10) = fun; }
--- /dev/null
+/* Copyright (C) 1990, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-sun2.h"
+#include "tm-sunos.h"
--- /dev/null
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HAVE_68881
+
+#include "tm-68k.h"
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Address of the end of stack space. We get this from the system
+ include files. */
+#include <sys/types.h>
+#include <machine/vmparam.h>
+#define STACK_END_ADDR USRSTACK
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM); \
+ register int regnum; \
+ char raw_buffer[12]; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ { read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); \
+ sp = push_bytes (sp, raw_buffer, 12); } \
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PS_REGNUM)); \
+ write_register (SP_REGNUM, sp); }
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ char raw_buffer[12]; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--) \
+ if (fsr.regs[regnum]) \
+ { read_memory (fsr.regs[regnum], raw_buffer, 12); \
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12); }\
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ if (fsr.regs[PS_REGNUM]) \
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM), \
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ fmovem 0xff,-(sp)
+ moveml 0xfffc,-(sp)
+ clrw -(sp)
+ movew ccr,-(sp)
+ /..* The arguments are pushed at this point by GDB;
+ no code is needed in the dummy for this.
+ The CALL_DUMMY_START_OFFSET gives the position of
+ the following jsr instruction. *../
+ jsr @#32323232
+ addl #69696969,sp
+ trap #15
+ nop
+Note this is 28 bytes.
+We actually start executing at the jsr, since the pushing of the
+registers is done by PUSH_DUMMY_FRAME. If this were real code,
+the arguments for the function called by the jsr would be pushed
+between the moveml and the jsr, and we could allow it to execute through.
+But the arguments have to be pushed by GDB after the PUSH_DUMMY_FRAME is done,
+and we cannot allow the moveml to push the registers again lest they be
+taken for the arguments. */
+
+#define CALL_DUMMY {0xf227e0ff, 0x48e7fffc, 0x426742e7, 0x4eb93232, 0x3232dffc, 0x69696969, 0x4e4f4e71}
+
+#define CALL_DUMMY_LENGTH 28
+
+#define CALL_DUMMY_START_OFFSET 12
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *(int *)((char *) dummyname + 20) = nargs * 4; \
+ *(int *)((char *) dummyname + 14) = fun; }
--- /dev/null
+/* Parameters for execution on a Sun 386i, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+#ifndef sun386
+#define sun386
+#endif
+#define SUNOS4
+#define USE_MACHINE_REG_H
+
+/* Perhaps some day this will work even without the following #define */
+#define COFF_ENCAPSULATE
+
+#ifdef COFF_ENCAPSULATE
+#define NAMES_HAVE_UNDERSCORE
+/* Avoid conflicts between "a.out.gnu.h" and <sys/exec.h> */
+#define _EXEC_
+#endif
+
+#define BROKEN_LARGE_ALLOCA
+
+/* sun386 ptrace seems unable to change the frame pointer */
+#define PTRACE_FP_BUG
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xfc000000
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 1
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc3)
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the 386. */
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* Largest integer type */
+#define LONGEST long
+
+/* Name of the builtin type for the LONGEST type above. */
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 35
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* the order of the first 8 registers must match the compiler's
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+#define REGISTER_NAMES { "gs", "fs", "es", "ds", \
+ "edi", "esi", "ebp", "esp", \
+ "ebx", "edx", "ecx", "eax", \
+ "retaddr", "trapnum", "errcode", "ip", \
+ "cs", "ps", "sp", "ss", \
+ "fst0", "fst1", "fst2", "fst3", \
+ "fst4", "fst5", "fst6", "fst7", \
+ "fctrl", "fstat", "ftag", "fip", \
+ "fcs", "fopoff", "fopsel" \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP_REGNUM 6 /* Contains address of executing stack frame */
+#define SP_REGNUM 18 /* Contains address of top of stack */
+#define PS_REGNUM 17 /* Contains processor status */
+#define PC_REGNUM 15 /* Contains program counter */
+#define FP0_REGNUM 20 /* Floating point register 0 */
+#define FPC_REGNUM 28 /* 80387 control register */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (20*4+8*10+7*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) \
+ ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 160 \
+ : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 10) + 80 \
+ : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 10 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) (((unsigned)((N) - FP0_REGNUM)) < 8)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+ i387_to_double ((FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4); }
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \
+ double_to_i387 ((FROM), (TO)); \
+ else \
+ bcopy ((FROM), (TO), 4); }
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)((N) - FP0_REGNUM)) < 8 ? builtin_type_double : builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { (SP) -= sizeof (ADDR); \
+ write_memory ((SP), &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF + REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ (FRAMELESS) = frameless_look_for_prologue (FI); }
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { i386_pop_frame (); }
+
+/* this is
+ * call 11223344 (32 bit relative)
+ * int3
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ *(int *)((char *)(dummyname) + 1) = (int)(fun) - (pc) - 5; \
+}
--- /dev/null
+/* Copyright (C) 1990, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-sun3.h"
+#include "tm-sunos.h"
--- /dev/null
+/* Macro definitions for GDB for a Sun 4 running sunos 4.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-sparc.h"
+#include "tm-sunos.h"
+
+#undef STACK_END_ADDRESS
+#define STACK_END_ADDRESS 0xf8000000
--- /dev/null
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is for SunOS version 4, not for earlier versions. */
+
+#define CLEAR_SOLIB clear_solib
+
+/* If we can't set a breakpoint, and it's in a shared library, just
+ disable it. */
+#define DISABLE_UNSETTABLE_BREAK(addr) solib_address(addr)
+extern int solib_address (); /* solib.c */
--- /dev/null
+/* Definitions to make GDB run on a Sequent Symmetry under dynix 3.0,
+ with Weitek 1167 and i387 support.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Symmetry version by Jay Vosburgh (uunet!sequent!fubar) */
+
+/* I don't know if this will work for cross-debugging, even if you do get
+ a copy of the right include file. */
+#include <machine/reg.h>
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. From m-i386.h */
+
+#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer(read_register(SP_REGNUM), 4)
+
+/* I don't know the real values for these. */
+#define TARGET_UPAGES UPAGES
+#define TARGET_NBPG NBPG
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0x40000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. */
+/* For Symmetry, this is really the 'leave' instruction, which */
+/* is right before the ret */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0xc9)
+
+/* Return 1 if P points to an invalid floating point value.
+*/
+
+#define INVALID_FLOAT(p, len) (0)
+
+/* code for 80387 fpu. Functions are from i386-dep.c, copied into
+ * symm-dep.c.
+ */
+#define FLOAT_INFO { i386_float_info(); }
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+#define NUM_REGS 49
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* Symmetry registers are in this weird order to match the register
+ numbers in the symbol table entries. If you change the order,
+ things will probably break mysteriously for no apparent reason.
+ Also note that the st(0)...st(7) 387 registers are represented as
+ st0...st7. */
+
+#define REGISTER_NAMES { "eax", "edx", "ecx", "st0", "st1", \
+ "ebx", "esi", "edi", "st2", "st3", \
+ "st4", "st5", "st6", "st7", "esp", \
+ "ebp", "eip", "eflags", "fp1", "fp2", \
+ "fp3", "fp4", "fp5", "fp6", "fp7", \
+ "fp8", "fp9", "fp10", "fp11", "fp12", \
+ "fp13", "fp14", "fp15", "fp16", "fp17", \
+ "fp18", "fp19", "fp20", "fp21", "fp22", \
+ "fp23", "fp24", "fp25", "fp26", "fp27", \
+ "fp28", "fp29", "fp30", "fp31" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP1_REGNUM 18 /* first 1167 register */
+#define SP_REGNUM 14 /* Contains address of top of stack */
+#define FP_REGNUM 15 /* Contains address of executing stack frame */
+#define PC_REGNUM 16 /* Contains program counter */
+#define PS_REGNUM 17 /* Contains processor status */
+
+/* The magic numbers below are offsets into u_ar0 in the user struct.
+ * They live in <machine/reg.h>. Gdb calls this macro with blockend
+ * holding u.u_ar0 - KERNEL_U_ADDR. Only the registers listed are
+ * saved in the u area (along with a few others that aren't useful
+ * here. See <machine/reg.h>).
+ */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ struct user foo; /* needed for finding fpu regs */ \
+switch (regno) { \
+ case 0: \
+ addr = blockend + EAX * sizeof(int); break; \
+ case 1: \
+ addr = blockend + EDX * sizeof(int); break; \
+ case 2: \
+ addr = blockend + ECX * sizeof(int); break; \
+ case 3: /* st(0) */ \
+ addr = blockend - \
+ ((int)&foo.u_fpusave.fpu_stack[0][0] - (int)&foo); \
+ break; \
+ case 4: /* st(1) */ \
+ addr = blockend - \
+ ((int) &foo.u_fpusave.fpu_stack[1][0] - (int)&foo); \
+ break; \
+ case 5: \
+ addr = blockend + EBX * sizeof(int); break; \
+ case 6: \
+ addr = blockend + ESI * sizeof(int); break; \
+ case 7: \
+ addr = blockend + EDI * sizeof(int); break; \
+ case 8: /* st(2) */ \
+ addr = blockend - \
+ ((int) &foo.u_fpusave.fpu_stack[2][0] - (int)&foo); \
+ break; \
+ case 9: /* st(3) */ \
+ addr = blockend - \
+ ((int) &foo.u_fpusave.fpu_stack[3][0] - (int)&foo); \
+ break; \
+ case 10: /* st(4) */ \
+ addr = blockend - \
+ ((int) &foo.u_fpusave.fpu_stack[4][0] - (int)&foo); \
+ break; \
+ case 11: /* st(5) */ \
+ addr = blockend - \
+ ((int) &foo.u_fpusave.fpu_stack[5][0] - (int)&foo); \
+ break; \
+ case 12: /* st(6) */ \
+ addr = blockend - \
+ ((int) &foo.u_fpusave.fpu_stack[6][0] - (int)&foo); \
+ break; \
+ case 13: /* st(7) */ \
+ addr = blockend - \
+ ((int) &foo.u_fpusave.fpu_stack[7][0] - (int)&foo); \
+ break; \
+ case 14: \
+ addr = blockend + ESP * sizeof(int); break; \
+ case 15: \
+ addr = blockend + EBP * sizeof(int); break; \
+ case 16: \
+ addr = blockend + EIP * sizeof(int); break; \
+ case 17: \
+ addr = blockend + FLAGS * sizeof(int); break; \
+ case 18: /* fp1 */ \
+ case 19: /* fp2 */ \
+ case 20: /* fp3 */ \
+ case 21: /* fp4 */ \
+ case 22: /* fp5 */ \
+ case 23: /* fp6 */ \
+ case 24: /* fp7 */ \
+ case 25: /* fp8 */ \
+ case 26: /* fp9 */ \
+ case 27: /* fp10 */ \
+ case 28: /* fp11 */ \
+ case 29: /* fp12 */ \
+ case 30: /* fp13 */ \
+ case 31: /* fp14 */ \
+ case 32: /* fp15 */ \
+ case 33: /* fp16 */ \
+ case 34: /* fp17 */ \
+ case 35: /* fp18 */ \
+ case 36: /* fp19 */ \
+ case 37: /* fp20 */ \
+ case 38: /* fp21 */ \
+ case 39: /* fp22 */ \
+ case 40: /* fp23 */ \
+ case 41: /* fp24 */ \
+ case 42: /* fp25 */ \
+ case 43: /* fp26 */ \
+ case 44: /* fp27 */ \
+ case 45: /* fp28 */ \
+ case 46: /* fp29 */ \
+ case 47: /* fp30 */ \
+ case 48: /* fp31 */ \
+ addr = blockend - \
+ ((int) &foo.u_fpasave.fpa_regs[(regno)-18] - (int)&foo); \
+ } \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+/* 10 i386 registers, 8 i387 registers, and 31 Weitek 1167 registers */
+#define REGISTER_BYTES ((10 * 4) + (8 * 10) + (31 * 4))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) \
+((N < 3) ? (N * 4) : \
+(N < 5) ? (((N - 2) * 10) + 2) : \
+(N < 8) ? (((N - 5) * 4) + 32) : \
+(N < 14) ? (((N - 8) * 10) + 44) : \
+ (((N - 14) * 4) + 104))
+
+/* Number of bytes of storage in the actual machine representation
+ * for register N. All registers are 4 bytes, except 387 st(0) - st(7),
+ * which are 80 bits each.
+ */
+
+#define REGISTER_RAW_SIZE(N) \
+((N < 3) ? 4 : \
+(N < 5) ? 10 : \
+(N < 8) ? 4 : \
+(N < 14) ? 10 : \
+ 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) \
+((N < 3) ? 0 : \
+(N < 5) ? 1 : \
+(N < 8) ? 0 : \
+(N < 14) ? 1 : \
+ 0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+((REGNUM < 3) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 5) ? i387_to_double((FROM), (TO)) : \
+(REGNUM < 8) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 14) ? i387_to_double((FROM), (TO)) : \
+ bcopy ((FROM), (TO), 4))
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+((REGNUM < 3) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 5) ? double_to_i387((FROM), (TO)) : \
+(REGNUM < 8) ? bcopy ((FROM), (TO), 4) : \
+(REGNUM < 14) ? double_to_i387((FROM), (TO)) : \
+ bcopy ((FROM), (TO), 4))
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+((N < 3) ? builtin_type_int : \
+(N < 5) ? builtin_type_double : \
+(N < 8) ? builtin_type_int : \
+(N < 14) ? builtin_type_double : \
+ builtin_type_int)
+
+/* from m-i386.h */
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { (SP) -= sizeof (ADDR); \
+ write_memory ((SP), &(ADDR), sizeof (ADDR)); \
+ write_register(0, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ symmetry_extract_return_value(TYPE, REGBUF, VALBUF)
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* On Symmetry, %ebp points to caller's %ebp, and the return address
+ is right on top of that.
+*/
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer((thisframe)->frame, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(fi) (read_memory_integer((fi)->frame + 4, 4))
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell.
+
+ The weirdness in the "addl $imm8" case is due to gcc sometimes
+ issuing "addl $-int" after function call returns; this would
+ produce ridiculously huge arg counts. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ \
+ int op = read_memory_integer(FRAME_SAVED_PC((fi)), 4); \
+ int narg; \
+ if ((op & 0xff) == 0x59) /* 0x59 'popl %ecx' */ \
+ { \
+ numargs = 1; \
+ } \
+ else if ((op & 0xffff) == 0xc483) /* 0xc483 'addl $imm8' */ \
+ { \
+ narg = ((op >> 16) & 0xff); \
+ numargs = (narg >= 128) ? -1 : narg / 4; \
+ } \
+ else if ((op & 0xffff) == 0xc481) /* 0xc481 'addl $imm32' */ \
+ { \
+ narg = read_memory_integer(FRAME_SAVED_PC((fi))+2,4); \
+ numargs = (narg < 0) ? -1 : narg / 4; \
+ } \
+ else \
+ { \
+ numargs = -1; \
+ } \
+}
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+\f
+/* Things needed for making the inferior call functions. */
+
+#define PUSH_DUMMY_FRAME \
+{ CORE_ADDR sp = read_register (SP_REGNUM); \
+ int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = 0; regnum < NUM_REGS; regnum++) \
+ sp = push_word (sp, read_register (regnum)); \
+ write_register (SP_REGNUM, sp); \
+}
+
+#define POP_FRAME \
+{ \
+ FRAME frame = get_current_frame (); \
+ CORE_ADDR fp; \
+ int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = 0; regnum < NUM_REGS; regnum++) { \
+ CORE_ADDR adr; \
+ adr = fsr.regs[regnum]; \
+ if (adr) \
+ write_register (regnum, read_memory_integer (adr, 4)); \
+ } \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM), \
+ read_pc ())); \
+}
+
+/* from i386-dep.c, worked better than my original... */
+/* This sequence of words is the instructions
+ * call (32-bit offset)
+ * int 3
+ * This is 6 bytes.
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ int from, to, delta, loc; \
+ loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+ from = loc + 5; \
+ to = (int)(fun); \
+ delta = to - from; \
+ *(int *)((char *)(dummyname) + 1) = delta; \
+}
--- /dev/null
+/* Definitions to make GDB run on an encore under umax 4.2
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Exec files and symbol tables are in COFF format */
+
+#define COFF_FORMAT
+
+/* Need to get function ends by adding this to epilogue address from .bf
+ record, not using x_fsize field. */
+#define FUNCTION_EPILOGUE_SIZE 4
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register unsigned char op = read_memory_integer (pc, 1); \
+ if (op == 0x82) { op = read_memory_integer (pc+2,1); \
+ if ((op & 0x80) == 0) pc += 3; \
+ else if ((op & 0xc0) == 0x80) pc += 4; \
+ else pc += 6; \
+ } \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) \
+ read_memory_integer (read_register (SP_REGNUM), 4)
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR (0xfffff000)
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xf2}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 0x12)
+
+#ifndef NaN
+#include <nan.h>
+#endif NaN
+
+/* Return 1 if P points to an invalid floating point value. */
+/* Surely wrong for cross-debugging. */
+#define INVALID_FLOAT(p, s) \
+ ((s == sizeof (float))? \
+ NaF (*(float *) p) : \
+ NaD (*(double *) p))
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 25
+
+#define NUM_GENERAL_REGS 8
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "sp", "fp", "pc", "ps", \
+ "fsr", \
+ "l0", "l1", "l2", "l3", "xx", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP0_REGNUM 8 /* Floating point register 0 */
+#define SP_REGNUM 16 /* Contains address of top of stack */
+#define AP_REGNUM FP_REGNUM
+#define FP_REGNUM 17 /* Contains address of executing stack frame */
+#define PC_REGNUM 18 /* Contains program counter */
+#define PS_REGNUM 19 /* Contains processor status */
+#define FPS_REGNUM 20 /* Floating point status register */
+#define LP0_REGNUM 21 /* Double register 0 (same as FP0) */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES ((NUM_REGS - 4) * sizeof (int) + 4 * sizeof (double))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) >= LP0_REGNUM ? \
+ LP0_REGNUM * 4 + ((N) - LP0_REGNUM) * 8 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_RAW_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the 32000, all regs are 4 bytes
+ except for the doubled floating registers. */
+
+#define REGISTER_VIRTUAL_SIZE(N) ((N) >= LP0_REGNUM ? 8 : 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), REGISTER_VIRTUAL_SIZE(REGNUM));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) < FP0_REGNUM) ? \
+ builtin_type_int : \
+ ((N) < FP0_REGNUM + 8) ? \
+ builtin_type_float : \
+ ((N) < LP0_REGNUM) ? \
+ builtin_type_int : \
+ builtin_type_double)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+
+ On this machine this is a no-op, because gcc isn't used on it
+ yet. So this calling convention is not used. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF+REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 0), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the ns32000 series, the frame's nominal address is the FP
+ value, and at that address is saved previous FP value as a 4-byte word. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* Compute base of arguments. */
+
+#define FRAME_ARGS_ADDRESS(fi) \
+ ((ns32k_get_enter_addr ((fi)->pc) > 1) ? \
+ ((fi)->frame) : (read_register (SP_REGNUM) - 4))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Get the address of the enter opcode for this function, if it is active.
+ Returns positive address > 1 if pc is between enter/exit,
+ 1 if pc before enter or after exit, 0 otherwise. */
+
+#ifndef CORE_ADDR
+#include "defs.h" /* Make sure CORE_ADDR is defined. */
+#endif
+
+extern CORE_ADDR ns32k_get_enter_addr ();
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell.
+ Encore's C compiler often reuses same area on stack for args,
+ so this will often not work properly. If the arg names
+ are known, it's likely most of them will be printed. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ CORE_ADDR pc; \
+ CORE_ADDR enter_addr; \
+ unsigned int insn; \
+ unsigned int addr_mode; \
+ int width; \
+ \
+ numargs = -1; \
+ enter_addr = ns32k_get_enter_addr ((fi)->pc); \
+ if (enter_addr > 0) \
+ { \
+ pc = (enter_addr == 1) ? \
+ SAVED_PC_AFTER_CALL (fi) : \
+ FRAME_SAVED_PC (fi); \
+ insn = read_memory_integer (pc,2); \
+ addr_mode = (insn >> 11) & 0x1f; \
+ insn = insn & 0x7ff; \
+ if ((insn & 0x7fc) == 0x57c && \
+ addr_mode == 0x14) /* immediate */ \
+ { \
+ if (insn == 0x57c) /* adjspb */ \
+ width = 1; \
+ else if (insn == 0x57d) /* adjspw */ \
+ width = 2; \
+ else if (insn == 0x57f) /* adjspd */ \
+ width = 4; \
+ numargs = read_memory_integer (pc+2,width); \
+ if (width > 1) \
+ flip_bytes (&numargs, width); \
+ numargs = - sign_extend (numargs, width*8) / 4;\
+ } \
+ } \
+}
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ \
+ register int regmask, regnum; \
+ int localcount; \
+ register CORE_ADDR enter_addr; \
+ register CORE_ADDR next_addr; \
+ \
+ bzero (&(frame_saved_regs), sizeof (frame_saved_regs)); \
+ enter_addr = ns32k_get_enter_addr ((frame_info)->pc); \
+ if (enter_addr > 1) \
+ { \
+ regmask = read_memory_integer (enter_addr+1, 1) & 0xff; \
+ localcount = ns32k_localcount (enter_addr); \
+ next_addr = (frame_info)->frame + localcount; \
+ for (regnum = 0; regnum < 8; regnum++, regmask >>= 1) \
+ (frame_saved_regs).regs[regnum] = (regmask & 1) ? \
+ (next_addr -= 4) : 0; \
+ (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame + 4;\
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 4;\
+ (frame_saved_regs).regs[FP_REGNUM] = \
+ (read_memory_integer ((frame_info)->frame, 4));\
+ } \
+ else if (enter_addr == 1) \
+ { \
+ CORE_ADDR sp = read_register (SP_REGNUM); \
+ (frame_saved_regs).regs[PC_REGNUM] = sp; \
+ (frame_saved_regs).regs[SP_REGNUM] = sp + 4; \
+ } \
+}
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ write_register (FP_REGNUM, sp); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ sp = push_word (sp, read_register (regnum)); \
+ write_register (SP_REGNUM, sp); \
+}
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register FRAME frame = get_current_frame (); \
+ register CORE_ADDR fp; \
+ register int regnum; \
+ struct frame_saved_regs fsr; \
+ struct frame_info *fi; \
+ fi = get_frame_info (frame); \
+ fp = fi->frame; \
+ get_frame_saved_regs (fi, &fsr); \
+ for (regnum = 0; regnum < 8; regnum++) \
+ if (fsr.regs[regnum]) \
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4)); \
+ write_register (SP_REGNUM, fp + 8); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ enter 0xff,0 82 ff 00
+ jsr @0x00010203 7f ae c0 01 02 03
+ adjspd 0x69696969 7f a5 01 02 03 04
+ bpt f2
+ Note this is 16 bytes. */
+
+#define CALL_DUMMY { 0x7f00ff82, 0x0201c0ae, 0x01a57f03, 0xf2040302 }
+
+#define CALL_DUMMY_START_OFFSET 3
+#define CALL_DUMMY_LENGTH 16
+#define CALL_DUMMY_ADDR 5
+#define CALL_DUMMY_NARGS 11
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ int flipped; \
+ flipped = fun | 0xc0000000; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_ADDR)) = flipped; \
+ flipped = - nargs * 4; \
+ flip_bytes (&flipped, 4); \
+ *((int *) (((char *) dummyname)+CALL_DUMMY_NARGS)) = flipped; \
+}
--- /dev/null
+/* Definitions to make GDB run on a vax under 4.2bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* There is one known bug with VAX support that I don't know how to
+ fix: if you do a backtrace from a signal handler, you get something
+ like:
+#0 0xbc in kill (592, 3)
+#1 0x7f in hand (...) (...)
+#2 0x7fffec7e in ?? (2, 0, 2147478112, 94)
+ ^^ GDB doesn't know about sigtramp
+#3 0x7fffec70 in ?? (592, 2)
+ ^^^^^^^^^^ wrong address
+#4 0xae in main (...) (...)
+
+when the correct backtrace (as given by adb) is:
+_kill(250,3) from _hand+21
+_hand(2,0,7fffea60,5e) from 7fffec7e
+sigtramp(2,0,7fffea60,5e) from _kill+4
+_kill(250,2) from _main+2e
+_main(1,7fffeac4,7fffeacc) from start+3d
+
+If anyone knows enough about VAX BSD to fix this, please send the
+fix to bug-gdb@prep.ai.mit.edu. */
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Debugger information will be in DBX format. */
+
+#define READ_DBX_FORMAT
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 2
+
+/* Advance PC across any function entry prologue instructions
+ to reach some "real" code. */
+
+#define SKIP_PROLOGUE(pc) \
+{ register int op = (unsigned char) read_memory_integer (pc, 1); \
+ if (op == 0x11) pc += 2; /* skip brb */ \
+ if (op == 0x31) pc += 3; /* skip brw */ \
+ if (op == 0xC2 && \
+ ((unsigned char) read_memory_integer (pc+2, 1)) == 0x5E) \
+ pc += 3; /* skip subl2 */ \
+ if (op == 0x9E && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xAE && \
+ ((unsigned char) read_memory_integer(pc+3, 1)) == 0x5E) \
+ pc += 4; /* skip movab */ \
+ if (op == 0x9E && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xCE && \
+ ((unsigned char) read_memory_integer(pc+4, 1)) == 0x5E) \
+ pc += 5; /* skip movab */ \
+ if (op == 0x9E && \
+ ((unsigned char) read_memory_integer (pc+1, 1)) == 0xEE && \
+ ((unsigned char) read_memory_integer(pc+6, 1)) == 0x5E) \
+ pc += 7; /* skip movab */ \
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't always go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame)
+
+#define TARGET_UPAGES 10
+#define TARGET_NBPG 512
+#define STACK_END_ADDR (0x80000000 - (TARGET_UPAGES * TARGET_NBPG))
+
+/* On the VAX, sigtramp is in the u area. Can't check the exact
+ addresses because for cross-debugging we don't have VAX include
+ files around. This should be close enough. */
+#define IN_SIGTRAMP(pc, name) ((pc) >= STACK_END_ADDR && (pc < 0x80000000))
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {3}
+
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 1) == 04)
+
+/* Return 1 if P points to an invalid floating point value.
+ LEN is the length in bytes -- not relevant on the Vax. */
+
+#define INVALID_FLOAT(p, len) ((*(short *) p & 0xff80) == 0x8000)
+
+/* Say how long (ordinary) registers are. */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 17
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+#define REGISTER_NAMES {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "ap", "fp", "sp", "pc", "ps"}
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define AP_REGNUM 12
+#define FP_REGNUM 13 /* Contains address of executing stack frame */
+#define SP_REGNUM 14 /* Contains address of top of stack */
+#define PC_REGNUM 15 /* Contains program counter */
+#define PS_REGNUM 16 /* Contains processor status */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+#define REGISTER_BYTES (17*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) ((N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_RAW_SIZE(N) 4
+
+/* Number of bytes of storage in the program's representation
+ for register N. On the vax, all regs are 4 bytes. */
+
+#define REGISTER_VIRTUAL_SIZE(N) 4
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 4
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), 4);
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ bcopy ((FROM), (TO), 4);
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) builtin_type_int
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { write_register (1, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ bcopy (REGBUF, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ the address in which a function should return its structure value,
+ as a CORE_ADDR (or an expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+\f
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer.
+
+ FRAME_CHAIN_COMBINE takes the chain pointer and the frame's nominal address
+ and produces the nominal address of the caller frame.
+
+ However, if FRAME_CHAIN_VALID returns zero,
+ it means the given frame is the outermost one and has no caller.
+ In that case, FRAME_CHAIN_COMBINE is not used. */
+
+/* In the case of the Vax, the frame's nominal address is the FP value,
+ and 12 bytes later comes the saved previous FP value as a 4-byte word. */
+
+#define FRAME_CHAIN(thisframe) \
+ (outside_startup_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame + 12, 4) :\
+ 0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+/* On the vax, all functions have frames. */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) = 0;}
+
+/* Saved Pc. */
+
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 16, 4))
+
+/* Cannot find the AP register value directly from the FP value. Must
+ find it saved in the frame called by this one, or in the AP
+ register for the innermost frame. However, there is no way to tell
+ the difference between the innermost frame and a frame for which we
+ just don't know the frame that it called (e.g. "info frame
+ 0x7ffec789"). For the sake of argument suppose that the stack is
+ somewhat trashed (which is one reason that "info frame" exists).
+ So return 0 (indicating we don't know the address of
+ the arglist) if we don't know what frame this frame calls. */
+#define FRAME_ARGS_ADDRESS_CORRECT(fi) \
+ (((fi)->next_frame \
+ ? read_memory_integer ((fi)->next_frame + 8, 4) \
+ : /* read_register (AP_REGNUM) */ 0))
+
+/* In most of GDB, getting the args address is too important to
+ just say "I don't know". This is sometimes wrong for functions
+ that aren't on top of the stack, but c'est la vie. */
+#define FRAME_ARGS_ADDRESS(fi) \
+ (((fi)->next_frame \
+ ? read_memory_integer ((fi)->next_frame + 8, 4) \
+ : read_register (AP_REGNUM) /* 0 */))
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#define FRAME_NUM_ARGS(numargs, fi) \
+{ numargs = (0xff & read_memory_integer (FRAME_ARGS_ADDRESS (fi), 1)); }
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 4
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ register int regnum; \
+ register int regmask = read_memory_integer ((frame_info)->frame+4, 4) >> 16; \
+ register CORE_ADDR next_addr; \
+ bzero (&frame_saved_regs, sizeof frame_saved_regs); \
+ next_addr = (frame_info)->frame + 16; \
+ /* Regmask's low bit is for register 0, \
+ which is the first one that would be pushed. */ \
+ for (regnum = 0; regnum < 12; regnum++, regmask >>= 1) \
+ (frame_saved_regs).regs[regnum] = (regmask & 1) ? (next_addr += 4) : 0; \
+ (frame_saved_regs).regs[SP_REGNUM] = next_addr + 4; \
+ if (read_memory_integer ((frame_info)->frame + 4, 4) & 0x20000000) \
+ (frame_saved_regs).regs[SP_REGNUM] += 4 + 4 * read_memory_integer (next_addr + 4, 4); \
+ (frame_saved_regs).regs[PC_REGNUM] = (frame_info)->frame + 16; \
+ (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame + 12; \
+ (frame_saved_regs).regs[AP_REGNUM] = (frame_info)->frame + 8; \
+ (frame_saved_regs).regs[PS_REGNUM] = (frame_info)->frame + 4; \
+}
+\f
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);\
+ register int regnum; \
+ sp = push_word (sp, 0); /* arglist */ \
+ for (regnum = 11; regnum >= 0; regnum--) \
+ sp = push_word (sp, read_register (regnum)); \
+ sp = push_word (sp, read_register (PC_REGNUM)); \
+ sp = push_word (sp, read_register (FP_REGNUM)); \
+ sp = push_word (sp, read_register (AP_REGNUM)); \
+ sp = push_word (sp, (read_register (PS_REGNUM) & 0xffef) \
+ + 0x2fff0000); \
+ sp = push_word (sp, 0); \
+ write_register (SP_REGNUM, sp); \
+ write_register (FP_REGNUM, sp); \
+ write_register (AP_REGNUM, sp + 17 * sizeof (int)); }
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME \
+{ register CORE_ADDR fp = read_register (FP_REGNUM); \
+ register int regnum; \
+ register int regmask = read_memory_integer (fp + 4, 4); \
+ write_register (PS_REGNUM, \
+ (regmask & 0xffff) \
+ | (read_register (PS_REGNUM) & 0xffff0000)); \
+ write_register (PC_REGNUM, read_memory_integer (fp + 16, 4)); \
+ write_register (FP_REGNUM, read_memory_integer (fp + 12, 4)); \
+ write_register (AP_REGNUM, read_memory_integer (fp + 8, 4)); \
+ fp += 16; \
+ for (regnum = 0; regnum < 12; regnum++) \
+ if (regmask & (0x10000 << regnum)) \
+ write_register (regnum, read_memory_integer (fp += 4, 4)); \
+ fp = fp + 4 + ((regmask >> 30) & 3); \
+ if (regmask & 0x20000000) \
+ { regnum = read_memory_integer (fp, 4); \
+ fp += (regnum + 1) * 4; } \
+ write_register (SP_REGNUM, fp); \
+ flush_cached_frames (); \
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+ read_pc ())); }
+
+/* This sequence of words is the instructions
+ calls #69, @#32323232
+ bpt
+ Note this is 8 bytes. */
+
+#define CALL_DUMMY {0x329f69fb, 0x03323232}
+
+#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ *((char *) dummyname + 1) = nargs; \
+ *(int *)((char *) dummyname + 3) = fun; }
--- /dev/null
+/* Parameters for execution on VxWorks 68k's, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define GDBINIT_FILENAME ".vxgdbinit"
+
+#define DEFAULT_PROMPT "(vxgdb) "
+
+/* Kludge... */
+#include "tm-sun3.h"
+
+/* We have more complex, useful breakpoints on the target. */
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+#undef FRAME_CHAIN
+#undef FRAME_CHAIN_VALID
+
+/* Takes the current frame-struct pointer and returns the chain-pointer
+ to get to the calling frame.
+
+ If our current frame pointer is zero, we're at the top; else read out
+ the saved FP from memory pointed to by the current FP. */
+
+#define FRAME_CHAIN(thisframe) ((thisframe)->frame? read_memory_integer ((thisframe)->frame, 4): 0)
+
+/* If the chain pointer is zero (either because the saved value fetched
+ by FRAME_CHAIN was zero, or because the current FP was zero so FRAME_CHAIN
+ never fetched anything), we are at the top of the stack. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
--- /dev/null
+/* Parameters for VxWorks Intel 960's, for GDB, the GNU debugger.
+ Copyright (C) 1986-1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "tm-i960.h"
+
+#define GDBINIT_FILENAME ".vxgdbinit"
+
+#define DEFAULT_PROMPT "(vxgdb) "
+
+/* We have more complex, useful breakpoints on the target.
+ Amount ip must be decremented by after a breakpoint. */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* We are guaranteed to have a zero frame pointer at bottom of stack, too. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) (chain != 0)
+
+/* Breakpoint patching is handled at the target end in VxWorks. */
+/* #define BREAKPOINT {0x00, 0x3e, 0x00, 0x66} */
+
+/* Not needed, because we don't support core files:
+ #define KERNEL_U_ADDR
+ #define REGISTER_U_ADDR(addr, blockend, regno)
+ */
+
+/* Address of end of stack space.
+ This doesn't matter for VxWorks, because it's only used
+ in manipulation of core files, which we don't support. */
+
+/* #define STACK_END_ADDR (0xfe000000) */
--- /dev/null
+/* umax host stuff.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+#include <sys/ptrace.h>
+#define PTRACE_ATTACH PT_ATTACH
+#define PTRACE_DETACH PT_FREEPROC
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in core.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the inferior with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct ptrace_user u;
+ int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name (filename);
+ data_start = exec_data_start;
+
+ data_end = data_start + u.pt_dsize;
+ stack_start = stack_end - u.pt_ssize;
+ data_offset = sizeof u;
+ stack_offset = data_offset + u.pt_dsize;
+ reg_offset = 0;
+
+ bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
+ printf ("Core file is from \"%s\".\n", u.pt_comm);
+ if (u.pt_signal > 0)
+ printf ("Program terminated with signal %d, %s.\n",
+ u.pt_signal,
+ u.pt_signal < NSIG
+ ? sys_siglist[u.pt_signal]
+ : "(undocumented)");
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0)
+ perror_with_name (filename);
+
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename);
+ }
+
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
--- /dev/null
+/* Low level packing and unpacking of values for GDB.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "command.h"
+
+/* The value-history records all the values printed
+ by print commands during this session. Each chunk
+ records 60 consecutive values. The first chunk on
+ the chain records the most recent values.
+ The total number of values is in value_history_count. */
+
+#define VALUE_HISTORY_CHUNK 60
+
+struct value_history_chunk
+{
+ struct value_history_chunk *next;
+ value values[VALUE_HISTORY_CHUNK];
+};
+
+/* Chain of chunks now in use. */
+
+static struct value_history_chunk *value_history_chain;
+
+static int value_history_count; /* Abs number of last entry stored */
+
+\f
+/* List of all value objects currently allocated
+ (except for those released by calls to release_value)
+ This is so they can be freed after each command. */
+
+static value all_values;
+
+/* Allocate a value that has the correct length for type TYPE. */
+
+value
+allocate_value (type)
+ struct type *type;
+{
+ register value val;
+
+ check_stub_type (type);
+
+ val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type));
+ VALUE_NEXT (val) = all_values;
+ all_values = val;
+ VALUE_TYPE (val) = type;
+ VALUE_LVAL (val) = not_lval;
+ VALUE_ADDRESS (val) = 0;
+ VALUE_FRAME (val) = 0;
+ VALUE_OFFSET (val) = 0;
+ VALUE_BITPOS (val) = 0;
+ VALUE_BITSIZE (val) = 0;
+ VALUE_REPEATED (val) = 0;
+ VALUE_REPETITIONS (val) = 0;
+ VALUE_REGNO (val) = -1;
+ VALUE_LAZY (val) = 0;
+ VALUE_OPTIMIZED_OUT (val) = 0;
+ return val;
+}
+
+/* Allocate a value that has the correct length
+ for COUNT repetitions type TYPE. */
+
+value
+allocate_repeat_value (type, count)
+ struct type *type;
+ int count;
+{
+ register value val;
+
+ val = (value) xmalloc (sizeof (struct value) + TYPE_LENGTH (type) * count);
+ VALUE_NEXT (val) = all_values;
+ all_values = val;
+ VALUE_TYPE (val) = type;
+ VALUE_LVAL (val) = not_lval;
+ VALUE_ADDRESS (val) = 0;
+ VALUE_FRAME (val) = 0;
+ VALUE_OFFSET (val) = 0;
+ VALUE_BITPOS (val) = 0;
+ VALUE_BITSIZE (val) = 0;
+ VALUE_REPEATED (val) = 1;
+ VALUE_REPETITIONS (val) = count;
+ VALUE_REGNO (val) = -1;
+ VALUE_LAZY (val) = 0;
+ VALUE_OPTIMIZED_OUT (val) = 0;
+ return val;
+}
+
+/* Free all the values that have been allocated (except for those released).
+ Called after each command, successful or not. */
+
+void
+free_all_values ()
+{
+ register value val, next;
+
+ for (val = all_values; val; val = next)
+ {
+ next = VALUE_NEXT (val);
+ value_free (val);
+ }
+
+ all_values = 0;
+}
+
+/* Remove VAL from the chain all_values
+ so it will not be freed automatically. */
+
+void
+release_value (val)
+ register value val;
+{
+ register value v;
+
+ if (all_values == val)
+ {
+ all_values = val->next;
+ return;
+ }
+
+ for (v = all_values; v; v = v->next)
+ {
+ if (v->next == val)
+ {
+ v->next = val->next;
+ break;
+ }
+ }
+}
+
+/* Return a copy of the value ARG.
+ It contains the same contents, for same memory address,
+ but it's a different block of storage. */
+
+static value
+value_copy (arg)
+ value arg;
+{
+ register value val;
+ register struct type *type = VALUE_TYPE (arg);
+ if (VALUE_REPEATED (arg))
+ val = allocate_repeat_value (type, VALUE_REPETITIONS (arg));
+ else
+ val = allocate_value (type);
+ VALUE_LVAL (val) = VALUE_LVAL (arg);
+ VALUE_ADDRESS (val) = VALUE_ADDRESS (arg);
+ VALUE_OFFSET (val) = VALUE_OFFSET (arg);
+ VALUE_BITPOS (val) = VALUE_BITPOS (arg);
+ VALUE_BITSIZE (val) = VALUE_BITSIZE (arg);
+ VALUE_REGNO (val) = VALUE_REGNO (arg);
+ VALUE_LAZY (val) = VALUE_LAZY (arg);
+ if (!VALUE_LAZY (val))
+ {
+ bcopy (VALUE_CONTENTS_RAW (arg), VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (VALUE_TYPE (arg))
+ * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
+ }
+ return val;
+}
+\f
+/* Access to the value history. */
+
+/* Record a new value in the value history.
+ Returns the absolute history index of the entry.
+ Result of -1 indicates the value was not saved; otherwise it is the
+ value history index of this new item. */
+
+int
+record_latest_value (val)
+ value val;
+{
+ int i;
+
+ /* Check error now if about to store an invalid float. We return -1
+ to the caller, but allow them to continue, e.g. to print it as "Nan". */
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) {
+ (void) unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i);
+ if (i) return -1; /* Indicate value not saved in history */
+ }
+
+ /* Here we treat value_history_count as origin-zero
+ and applying to the value being stored now. */
+
+ i = value_history_count % VALUE_HISTORY_CHUNK;
+ if (i == 0)
+ {
+ register struct value_history_chunk *new
+ = (struct value_history_chunk *)
+ xmalloc (sizeof (struct value_history_chunk));
+ bzero (new->values, sizeof new->values);
+ new->next = value_history_chain;
+ value_history_chain = new;
+ }
+
+ value_history_chain->values[i] = val;
+ release_value (val);
+
+ /* Now we regard value_history_count as origin-one
+ and applying to the value just stored. */
+
+ return ++value_history_count;
+}
+
+/* Return a copy of the value in the history with sequence number NUM. */
+
+value
+access_value_history (num)
+ int num;
+{
+ register struct value_history_chunk *chunk;
+ register int i;
+ register int absnum = num;
+
+ if (absnum <= 0)
+ absnum += value_history_count;
+
+ if (absnum <= 0)
+ {
+ if (num == 0)
+ error ("The history is empty.");
+ else if (num == 1)
+ error ("There is only one value in the history.");
+ else
+ error ("History does not go back to $$%d.", -num);
+ }
+ if (absnum > value_history_count)
+ error ("History has not yet reached $%d.", absnum);
+
+ absnum--;
+
+ /* Now absnum is always absolute and origin zero. */
+
+ chunk = value_history_chain;
+ for (i = (value_history_count - 1) / VALUE_HISTORY_CHUNK - absnum / VALUE_HISTORY_CHUNK;
+ i > 0; i--)
+ chunk = chunk->next;
+
+ return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]);
+}
+
+/* Clear the value history entirely.
+ Must be done when new symbol tables are loaded,
+ because the type pointers become invalid. */
+
+void
+clear_value_history ()
+{
+ register struct value_history_chunk *next;
+ register int i;
+ register value val;
+
+ while (value_history_chain)
+ {
+ for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
+ if (val = value_history_chain->values[i])
+ free (val);
+ next = value_history_chain->next;
+ free (value_history_chain);
+ value_history_chain = next;
+ }
+ value_history_count = 0;
+}
+
+static void
+value_history_info (num_exp, from_tty)
+ char *num_exp;
+ int from_tty;
+{
+ register int i;
+ register value val;
+ static int num = 1;
+
+ if (num_exp)
+ {
+ if (num_exp[0] == '+' && num_exp[1] == '\0')
+ /* "info history +" should print from the stored position. */
+ ;
+ else
+ /* "info history <exp>" should print around value number <exp>. */
+ num = parse_and_eval_address (num_exp) - 5;
+ }
+ else
+ {
+ /* "info history" means print the last 10 values. */
+ num = value_history_count - 9;
+ }
+
+ if (num <= 0)
+ num = 1;
+
+ for (i = num; i < num + 10 && i <= value_history_count; i++)
+ {
+ val = access_value_history (i);
+ printf_filtered ("$%d = ", i);
+ value_print (val, stdout, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+
+ /* The next "info history +" should start after what we just printed. */
+ num += 10;
+
+ /* Hitting just return after this command should do the same thing as
+ "info history +". If num_exp is null, this is unnecessary, since
+ "info history +" is not useful after "info history". */
+ if (from_tty && num_exp)
+ {
+ num_exp[0] = '+';
+ num_exp[1] = '\0';
+ }
+}
+\f
+/* Internal variables. These are variables within the debugger
+ that hold values assigned by debugger commands.
+ The user refers to them with a '$' prefix
+ that does not appear in the variable names stored internally. */
+
+static struct internalvar *internalvars;
+
+/* Look up an internal variable with name NAME. NAME should not
+ normally include a dollar sign.
+
+ If the specified internal variable does not exist,
+ one is created, with a void value. */
+
+struct internalvar *
+lookup_internalvar (name)
+ char *name;
+{
+ register struct internalvar *var;
+
+ for (var = internalvars; var; var = var->next)
+ if (!strcmp (var->name, name))
+ return var;
+
+ var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
+ var->name = concat (name, "", "");
+ var->value = allocate_value (builtin_type_void);
+ release_value (var->value);
+ var->next = internalvars;
+ internalvars = var;
+ return var;
+}
+
+value
+value_of_internalvar (var)
+ struct internalvar *var;
+{
+ register value val;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ return VALUE_OF_TRAPPED_INTERNALVAR (var);
+#endif
+
+ val = value_copy (var->value);
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+ VALUE_LVAL (val) = lval_internalvar;
+ VALUE_INTERNALVAR (val) = var;
+ return val;
+}
+
+void
+set_internalvar_component (var, offset, bitpos, bitsize, newval)
+ struct internalvar *var;
+ int offset, bitpos, bitsize;
+ value newval;
+{
+ register char *addr = VALUE_CONTENTS (var->value) + offset;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ SET_TRAPPED_INTERNALVAR (var, newval, bitpos, bitsize, offset);
+#endif
+
+ if (bitsize)
+ modify_field (addr, (int) value_as_long (newval),
+ bitpos, bitsize);
+ else
+ bcopy (VALUE_CONTENTS (newval), addr,
+ TYPE_LENGTH (VALUE_TYPE (newval)));
+}
+
+void
+set_internalvar (var, val)
+ struct internalvar *var;
+ value val;
+{
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0);
+#endif
+
+ free (var->value);
+ var->value = value_copy (val);
+ release_value (var->value);
+}
+
+char *
+internalvar_name (var)
+ struct internalvar *var;
+{
+ return var->name;
+}
+
+/* Free all internalvars. Done when new symtabs are loaded,
+ because that makes the values invalid. */
+
+void
+clear_internalvars ()
+{
+ register struct internalvar *var;
+
+ while (internalvars)
+ {
+ var = internalvars;
+ internalvars = var->next;
+ free (var->name);
+ free (var->value);
+ free (var);
+ }
+}
+
+static void
+convenience_info ()
+{
+ register struct internalvar *var;
+ int varseen = 0;
+
+ for (var = internalvars; var; var = var->next)
+ {
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ continue;
+#endif
+ if (!varseen)
+ {
+#if 0
+ /* Useless noise. */
+ printf ("Debugger convenience variables:\n\n");
+#endif
+ varseen = 1;
+ }
+ printf ("$%s = ", var->name);
+ value_print (var->value, stdout, 0, Val_pretty_default);
+ printf ("\n");
+ }
+ if (!varseen)
+ printf ("No debugger convenience variables now defined.\n\
+Convenience variables have names starting with \"$\";\n\
+use \"set\" as in \"set $foo = 5\" to define them.\n");
+}
+\f
+/* Extract a value as a C number (either long or double).
+ Knows how to convert fixed values to double, or
+ floating values to long.
+ Does not deallocate the value. */
+
+LONGEST
+value_as_long (val)
+ register value val;
+{
+ /* This coerces arrays and functions, which is necessary (e.g.
+ in disassemble_command). It also dereferences references, which
+ I suspect is the most logical thing to do. */
+ if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_ENUM)
+ COERCE_ARRAY (val);
+ return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
+}
+
+double
+value_as_double (val)
+ register value val;
+{
+ double foo;
+ int inv;
+
+ foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv);
+ if (inv)
+ error ("Invalid floating value found in program.");
+ return foo;
+}
+\f
+/* Unpack raw data (copied from debugee, target byte order) at VALADDR
+ as a long, or as a double, assuming the raw data is described
+ by type TYPE. Knows how to convert different sizes of values
+ and can convert between fixed and floating point. We don't assume
+ any alignment for the raw data. Return value is in host byte order.
+
+ If you want functions and arrays to be coerced to pointers, and
+ references to be dereferenced, call value_as_long() instead.
+
+ C++: It is assumed that the front-end has taken care of
+ all matters concerning pointers to members. A pointer
+ to member which reaches here is considered to be equivalent
+ to an INT (or some size). After all, it is only an offset. */
+
+LONGEST
+unpack_long (type, valaddr)
+ struct type *type;
+ char *valaddr;
+{
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+ register int nosign = TYPE_UNSIGNED (type);
+
+ if (code == TYPE_CODE_ENUM)
+ code = TYPE_CODE_INT;
+ if (code == TYPE_CODE_FLT)
+ {
+ if (len == sizeof (float))
+ {
+ float retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (double))
+ {
+ double retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+ else
+ {
+ error ("Unexpected type of floating point number.");
+ }
+ }
+ else if (code == TYPE_CODE_INT && nosign)
+ {
+ if (len == sizeof (char))
+ {
+ unsigned char retval = * (unsigned char *) valaddr;
+ /* SWAP_TARGET_AND_HOST (&retval, sizeof (unsigned char)); */
+ return retval;
+ }
+
+ if (len == sizeof (short))
+ {
+ unsigned short retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (int))
+ {
+ unsigned int retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (long))
+ {
+ unsigned long retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+#ifdef LONG_LONG
+ if (len == sizeof (long long))
+ {
+ unsigned long long retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+#endif
+ else
+ {
+ error ("That operation is not possible on an integer of that size.");
+ }
+ }
+ else if (code == TYPE_CODE_INT)
+ {
+ if (len == sizeof (char))
+ {
+ char retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (short))
+ {
+ short retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (int))
+ {
+ int retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (long))
+ {
+ long retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+#ifdef LONG_LONG
+ if (len == sizeof (long long))
+ {
+ long long retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+#endif
+ else
+ {
+ error ("That operation is not possible on an integer of that size.");
+ }
+ }
+ else if (code == TYPE_CODE_PTR
+ || code == TYPE_CODE_REF)
+ {
+ if (len == sizeof (char *))
+ {
+ CORE_ADDR retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+ }
+ else if (code == TYPE_CODE_MEMBER)
+ error ("not implemented: member types in unpack_long");
+
+ error ("Value not integer or pointer.");
+ return 0; /* For lint -- never reached */
+}
+
+/* Return a double value from the specified type and address.
+ INVP points to an int which is set to 0 for valid value,
+ 1 for invalid value (bad float format). In either case,
+ the returned double is OK to use. Argument is in target
+ format, result is in host format. */
+
+double
+unpack_double (type, valaddr, invp)
+ struct type *type;
+ char *valaddr;
+ int *invp;
+{
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+ register int nosign = TYPE_UNSIGNED (type);
+
+ *invp = 0; /* Assume valid. */
+ if (code == TYPE_CODE_FLT)
+ {
+ if (INVALID_FLOAT (valaddr, len))
+ {
+ *invp = 1;
+ return 1.234567891011121314;
+ }
+
+ if (len == sizeof (float))
+ {
+ float retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (double))
+ {
+ double retval;
+ bcopy (valaddr, &retval, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+ else
+ {
+ error ("Unexpected type of floating point number.");
+ }
+ }
+ else if (nosign) {
+ /* Unsigned -- be sure we compensate for signed LONGEST. */
+#ifdef LONG_LONG
+ return (unsigned long long) unpack_long (type, valaddr);
+#else
+ return (unsigned long ) unpack_long (type, valaddr);
+#endif
+ } else {
+ /* Signed -- we are OK with unpack_long. */
+ return unpack_long (type, valaddr);
+ }
+}
+\f
+/* Given a value ARG1 (offset by OFFSET bytes)
+ of a struct or union type ARG_TYPE,
+ extract and return the value of one of its fields.
+ FIELDNO says which field.
+
+ For C++, must also be able to return values from static fields */
+
+value
+value_primitive_field (arg1, offset, fieldno, arg_type)
+ register value arg1;
+ int offset;
+ register int fieldno;
+ register struct type *arg_type;
+{
+ register value v;
+ register struct type *type;
+
+ check_stub_type (arg_type);
+ type = TYPE_FIELD_TYPE (arg_type, fieldno);
+
+ /* Handle packed fields */
+
+ offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+ if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
+ {
+ v = value_from_long (type,
+ unpack_field_as_long (arg_type,
+ VALUE_CONTENTS (arg1),
+ fieldno));
+ VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
+ VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+ }
+ else
+ {
+ v = allocate_value (type);
+ if (VALUE_LAZY (arg1))
+ VALUE_LAZY (v) = 1;
+ else
+ bcopy (VALUE_CONTENTS_RAW (arg1) + offset,
+ VALUE_CONTENTS_RAW (v),
+ TYPE_LENGTH (type));
+ }
+ VALUE_LVAL (v) = VALUE_LVAL (arg1);
+ if (VALUE_LVAL (arg1) == lval_internalvar)
+ VALUE_LVAL (v) = lval_internalvar_component;
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
+ VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1);
+ return v;
+}
+
+/* Given a value ARG1 of a struct or union type,
+ extract and return the value of one of its fields.
+ FIELDNO says which field.
+
+ For C++, must also be able to return values from static fields */
+
+value
+value_field (arg1, fieldno)
+ register value arg1;
+ register int fieldno;
+{
+ return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
+}
+
+value
+value_fn_field (arg1, fieldno, subfieldno)
+ register value arg1;
+ register int fieldno;
+ int subfieldno;
+{
+ register value v;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno);
+ register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno);
+ struct symbol *sym;
+
+ sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno),
+ 0, VAR_NAMESPACE, 0, NULL);
+ if (! sym) error ("Internal error: could not find physical method named %s",
+ TYPE_FN_FIELD_PHYSNAME (f, subfieldno));
+
+ v = allocate_value (type);
+ VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ VALUE_TYPE (v) = type;
+ return v;
+}
+
+/* Return a virtual function as a value.
+ ARG1 is the object which provides the virtual function
+ table pointer. ARG1 is side-effected in calling this function.
+ F is the list of member functions which contains the desired virtual
+ function.
+ J is an index into F which provides the desired virtual function. */
+value
+value_virtual_fn_field (arg1, f, j)
+ value arg1;
+ struct fn_field *f;
+ int j;
+{
+ /* First, get the virtual function table pointer. That comes
+ with a strange type, so cast it to type `pointer to long' (which
+ should serve just fine as a function type). Then, index into
+ the table, and convert final value to appropriate function type. */
+ value entry, vfn, vtbl;
+ value vi = value_from_long (builtin_type_int,
+ (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ struct type *context = lookup_pointer_type (TYPE_FN_FIELD_FCONTEXT (f, j));
+ if (TYPE_TARGET_TYPE (context) != VALUE_TYPE (arg1))
+ arg1 = value_ind (value_cast (context, value_addr (arg1)));
+
+ context = VALUE_TYPE (arg1);
+
+ /* This type may have been defined before its virtual function table
+ was. If so, fill in the virtual function table entry for the
+ type now. */
+ if (TYPE_VPTR_FIELDNO (context) < 0)
+ TYPE_VPTR_FIELDNO (context)
+ = fill_in_vptr_fieldno (context);
+
+ /* The virtual function table is now an array of structures
+ which have the form { int16 offset, delta; void *pfn; }. */
+ vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (context)));
+
+ /* Index into the virtual function table. This is hard-coded because
+ looking up a field is not cheap, and it may be important to save
+ time, e.g. if the user has set a conditional breakpoint calling
+ a virtual function. */
+ entry = value_subscript (vtbl, vi);
+
+ /* Move the `this' pointer according to the virtual function table. */
+ VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
+ if (! VALUE_LAZY (arg1))
+ {
+ VALUE_LAZY (arg1) = 1;
+ value_fetch_lazy (arg1);
+ }
+
+ vfn = value_field (entry, 2);
+ /* Reinstantiate the function pointer with the correct type. */
+ VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+
+ return vfn;
+}
+
+/* The value of a static class member does not depend
+ on its instance, only on its type. If FIELDNO >= 0,
+ then fieldno is a valid field number and is used directly.
+ Otherwise, FIELDNAME is the name of the field we are
+ searching for. If it is not a static field name, an
+ error is signaled. TYPE is the type in which we look for the
+ static field member. */
+value
+value_static_field (type, fieldname, fieldno)
+ register struct type *type;
+ char *fieldname;
+ register int fieldno;
+{
+ register value v;
+ struct symbol *sym;
+ char *phys_name;
+
+ if (fieldno < 0)
+ {
+ register struct type *t = type;
+ /* Look for static field. */
+ while (t)
+ {
+ int i;
+ for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
+ if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
+ {
+ if (TYPE_FIELD_STATIC (t, i))
+ {
+ fieldno = i;
+ goto found;
+ }
+ else
+ error ("field `%s' is not static");
+ }
+ /* FIXME: this does not recursively check multiple baseclasses. */
+ t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0;
+ }
+
+ t = type;
+
+ if (destructor_name_p (fieldname, t))
+ error ("Cannot get value of destructor");
+
+ while (t)
+ {
+ int i;
+
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
+ {
+ if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname))
+ {
+ error ("Cannot get value of method \"%s\"", fieldname);
+ }
+ }
+ t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0;
+ }
+ error("there is no field named %s", fieldname);
+ }
+
+ found:
+ phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
+ sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+ if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name);
+
+ type = TYPE_FIELD_TYPE (type, fieldno);
+ v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+ return v;
+}
+
+/* Compute the address of the baseclass which is
+ the INDEXth baseclass of TYPE. The TYPE base
+ of the object is at VALADDR. */
+
+char *
+baseclass_addr (type, index, valaddr, valuep)
+ struct type *type;
+ int index;
+ char *valaddr;
+ value *valuep;
+{
+ struct type *basetype = TYPE_BASECLASS (type, index);
+
+ if (BASETYPE_VIA_VIRTUAL (type, index))
+ {
+ /* Must hunt for the pointer to this virtual baseclass. */
+ register int i, len = TYPE_NFIELDS (type);
+ register int n_baseclasses = TYPE_N_BASECLASSES (type);
+ char *vbase_name, *type_name = type_name_no_tag (basetype);
+
+ if (TYPE_MAIN_VARIANT (basetype))
+ basetype = TYPE_MAIN_VARIANT (basetype);
+
+ vbase_name = (char *)alloca (strlen (type_name) + 8);
+ sprintf (vbase_name, "_vb$%s", type_name);
+ /* First look for the virtual baseclass pointer
+ in the fields. */
+ for (i = n_baseclasses; i < len; i++)
+ {
+ if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i)))
+ {
+ value v = value_at (basetype,
+ unpack_long (TYPE_FIELD_TYPE (type, i),
+ valaddr + (TYPE_FIELD_BITPOS (type, i) / 8)));
+ if (valuep)
+ *valuep = v;
+ return (char *) VALUE_CONTENTS (v);
+ }
+ }
+ /* Not in the fields, so try looking through the baseclasses. */
+ for (i = index+1; i < n_baseclasses; i++)
+ {
+ char *baddr;
+
+ baddr = baseclass_addr (type, i, valaddr, valuep);
+ if (baddr)
+ return baddr;
+ }
+ /* Not found. */
+ if (valuep)
+ *valuep = 0;
+ return 0;
+ }
+
+ /* Baseclass is easily computed. */
+ if (valuep)
+ *valuep = 0;
+ return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
+}
+
+/* Ugly hack to convert method stubs into method types.
+
+ He ain't kiddin'. This demangles the name of the method into a string
+ including argument types, parses out each argument type, generates
+ a string casting a zero to that type, evaluates the string, and stuffs
+ the resulting type into an argtype vector!!! Then it knows the type
+ of the whole function (including argument types for overloading),
+ which info used to be in the stab's but was removed to hack back
+ the space required for them. */
+void
+check_stub_method (type, i, j)
+ struct type *type;
+ int i, j;
+{
+ extern char *gdb_mangle_typename (), *strchr ();
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ char *inner_name = gdb_mangle_typename (type);
+ char *mangled_name
+ = (char *)xmalloc (strlen (TYPE_FN_FIELDLIST_NAME (type, i))
+ + strlen (inner_name)
+ + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
+ + 1);
+ char *demangled_name, *cplus_demangle ();
+ char *argtypetext, *p;
+ int depth = 0, argcount = 1;
+ struct type **argtypes;
+
+ strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
+ strcat (mangled_name, inner_name);
+ strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
+ demangled_name = cplus_demangle (mangled_name, 0);
+
+ /* Now, read in the parameters that define this type. */
+ argtypetext = strchr (demangled_name, '(') + 1;
+ p = argtypetext;
+ while (*p)
+ {
+ if (*p == '(')
+ depth += 1;
+ else if (*p == ')')
+ depth -= 1;
+ else if (*p == ',' && depth == 0)
+ argcount += 1;
+
+ p += 1;
+ }
+ /* We need one more slot for the void [...] or NULL [end of arglist] */
+ argtypes = (struct type **)xmalloc ((argcount+1) * sizeof (struct type *));
+ p = argtypetext;
+ argtypes[0] = lookup_pointer_type (type);
+ argcount = 1;
+
+ if (*p != ')') /* () means no args, skip while */
+ {
+ while (*p)
+ {
+ if (*p == '(')
+ depth += 1;
+ else if (*p == ')')
+ depth -= 1;
+
+ if (depth <= 0 && (*p == ',' || *p == ')'))
+ {
+ char *tmp = (char *)alloca (p - argtypetext + 4);
+ value val;
+ tmp[0] = '(';
+ bcopy (argtypetext, tmp+1, p - argtypetext);
+ tmp[p-argtypetext+1] = ')';
+ tmp[p-argtypetext+2] = '0';
+ tmp[p-argtypetext+3] = '\0';
+ val = parse_and_eval (tmp);
+ argtypes[argcount] = VALUE_TYPE (val);
+ argcount += 1;
+ argtypetext = p + 1;
+ }
+ p += 1;
+ }
+ }
+
+ if (p[-2] != '.') /* ... */
+ argtypes[argcount] = builtin_type_void; /* Ellist terminator */
+ else
+ argtypes[argcount] = NULL; /* List terminator */
+
+ free (demangled_name);
+ smash_to_method_type (TYPE_FN_FIELD_TYPE (f, j), type,
+ TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
+ argtypes);
+ TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
+ TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) &= ~TYPE_FLAG_STUB;
+}
+\f
+long
+unpack_field_as_long (type, valaddr, fieldno)
+ struct type *type;
+ char *valaddr;
+ int fieldno;
+{
+ long val;
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+
+ bcopy (valaddr + bitpos / 8, &val, sizeof val);
+ SWAP_TARGET_AND_HOST (&val, sizeof val);
+
+ /* Extracting bits depends on endianness of the machine. */
+#ifdef BITS_BIG_ENDIAN
+ val = val >> (sizeof val * 8 - bitpos % 8 - bitsize);
+#else
+ val = val >> (bitpos % 8);
+#endif
+
+ val &= (1 << bitsize) - 1;
+ return val;
+}
+
+void
+modify_field (addr, fieldval, bitpos, bitsize)
+ char *addr;
+ int fieldval;
+ int bitpos, bitsize;
+{
+ long oword;
+
+ /* Reject values too big to fit in the field in question.
+ Otherwise adjoining fields may be corrupted. */
+ if (fieldval & ~((1<<bitsize)-1))
+ error ("Value %d does not fit in %d bits.", fieldval, bitsize);
+
+ bcopy (addr, &oword, sizeof oword);
+
+ /* Shifting for bit field depends on endianness of the machine. */
+#ifdef BITS_BIG_ENDIAN
+ bitpos = sizeof (oword) * 8 - bitpos - bitsize;
+#endif
+
+ oword &= ~(((1 << bitsize) - 1) << bitpos);
+ oword |= fieldval << bitpos;
+ bcopy (&oword, addr, sizeof oword);
+}
+\f
+/* Convert C numbers into newly allocated values */
+
+value
+value_from_long (type, num)
+ struct type *type;
+ register LONGEST num;
+{
+ register value val = allocate_value (type);
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+
+ if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM)
+ {
+ if (len == sizeof (char))
+ * (char *) VALUE_CONTENTS_RAW (val) = num;
+ else if (len == sizeof (short))
+ * (short *) VALUE_CONTENTS_RAW (val) = num;
+ else if (len == sizeof (int))
+ * (int *) VALUE_CONTENTS_RAW (val) = num;
+ else if (len == sizeof (long))
+ * (long *) VALUE_CONTENTS_RAW (val) = num;
+#ifdef LONG_LONG
+ else if (len == sizeof (long long))
+ * (long long *) VALUE_CONTENTS_RAW (val) = num;
+#endif
+ else
+ error ("Integer type encountered with unexpected data length.");
+ }
+ else
+ error ("Unexpected type encountered for integer constant.");
+
+ /* num was in host byte order. So now put the value's contents
+ into target byte order. */
+ SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len);
+
+ return val;
+}
+
+value
+value_from_double (type, num)
+ struct type *type;
+ double num;
+{
+ register value val = allocate_value (type);
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+
+ if (code == TYPE_CODE_FLT)
+ {
+ if (len == sizeof (float))
+ * (float *) VALUE_CONTENTS_RAW (val) = num;
+ else if (len == sizeof (double))
+ * (double *) VALUE_CONTENTS_RAW (val) = num;
+ else
+ error ("Floating type encountered with unexpected data length.");
+ }
+ else
+ error ("Unexpected type encountered for floating constant.");
+
+ /* num was in host byte order. So now put the value's contents
+ into target byte order. */
+ SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len);
+
+ return val;
+}
+\f
+/* Deal with the value that is "about to be returned". */
+
+/* Return the value that a function returning now
+ would be returning to its caller, assuming its type is VALTYPE.
+ RETBUF is where we look for what ought to be the contents
+ of the registers (in raw form). This is because it is often
+ desirable to restore old values to those registers
+ after saving the contents of interest, and then call
+ this function using the saved values.
+ struct_return is non-zero when the function in question is
+ using the structure return conventions on the machine in question;
+ 0 when it is using the value returning conventions (this often
+ means returning pointer to where structure is vs. returning value). */
+
+value
+value_being_returned (valtype, retbuf, struct_return)
+ register struct type *valtype;
+ char retbuf[REGISTER_BYTES];
+ int struct_return;
+ /*ARGSUSED*/
+{
+ register value val;
+ CORE_ADDR addr;
+
+#if defined (EXTRACT_STRUCT_VALUE_ADDRESS)
+ /* If this is not defined, just use EXTRACT_RETURN_VALUE instead. */
+ if (struct_return) {
+ addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
+ if (!addr)
+ error ("Function return value unknown");
+ return value_at (valtype, addr);
+ }
+#endif
+
+ val = allocate_value (valtype);
+ EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
+
+ return val;
+}
+
+/* Should we use EXTRACT_STRUCT_VALUE_ADDRESS instead of
+ EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc
+ and TYPE is the type (which is known to be struct, union or array).
+
+ On most machines, the struct convention is used unless we are
+ using gcc and the type is of a special size. */
+#if !defined (USE_STRUCT_CONVENTION)
+#define USE_STRUCT_CONVENTION(gcc_p, type)\
+ (!((gcc_p) && (TYPE_LENGTH (value_type) == 1 \
+ || TYPE_LENGTH (value_type) == 2 \
+ || TYPE_LENGTH (value_type) == 4 \
+ || TYPE_LENGTH (value_type) == 8 \
+ ) \
+ ))
+#endif
+
+/* Return true if the function specified is using the structure returning
+ convention on this machine to return arguments, or 0 if it is using
+ the value returning convention. FUNCTION is the value representing
+ the function, FUNCADDR is the address of the function, and VALUE_TYPE
+ is the type returned by the function. GCC_P is nonzero if compiled
+ with GCC. */
+
+int
+using_struct_return (function, funcaddr, value_type, gcc_p)
+ value function;
+ CORE_ADDR funcaddr;
+ struct type *value_type;
+ int gcc_p;
+ /*ARGSUSED*/
+{
+ register enum type_code code = TYPE_CODE (value_type);
+
+ if (code == TYPE_CODE_ERROR)
+ error ("Function return type unknown.");
+
+ if (code == TYPE_CODE_STRUCT ||
+ code == TYPE_CODE_UNION ||
+ code == TYPE_CODE_ARRAY)
+ return USE_STRUCT_CONVENTION (gcc_p, value_type);
+
+ return 0;
+}
+
+/* Store VAL so it will be returned if a function returns now.
+ Does not verify that VAL's type matches what the current
+ function wants to return. */
+
+void
+set_return_value (val)
+ value val;
+{
+ register enum type_code code = TYPE_CODE (VALUE_TYPE (val));
+ double dbuf;
+ LONGEST lbuf;
+
+ if (code == TYPE_CODE_ERROR)
+ error ("Function return type unknown.");
+
+ if (code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION)
+ error ("Specifying a struct or union return value is not supported.");
+
+ /* FIXME, this is bogus. We don't know what the return conventions
+ are, or how values should be promoted.... */
+ if (code == TYPE_CODE_FLT)
+ {
+ dbuf = value_as_double (val);
+
+ STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&dbuf);
+ }
+ else
+ {
+ lbuf = value_as_long (val);
+ STORE_RETURN_VALUE (VALUE_TYPE (val), (char *)&lbuf);
+ }
+}
+\f
+void
+_initialize_values ()
+{
+ add_info ("convenience", convenience_info,
+ "Debugger convenience (\"$foo\") variables.\n\
+These variables are created when you assign them values;\n\
+thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\
+A few convenience variables are given values automatically:\n\
+\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\
+\"$__\" holds the contents of the last address examined with \"x\".");
+
+ add_info ("values", value_history_info,
+ "Elements of value history around item number IDX (or last ten).");
+ add_info_alias ("history", "values", 0);
+}
--- /dev/null
+/* Vax opcde list.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+GDB and GAS are free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB and GAS are distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB or GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef vax_opcodeT
+#define vax_opcodeT int
+#endif /* no vax_opcodeT */
+
+struct vot_wot /* vax opcode table: wot to do with this */
+ /* particular opcode */
+{
+ char * args; /* how to compile said opcode */
+ vax_opcodeT code; /* op-code (may be > 8 bits!) */
+};
+
+struct vot /* vax opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct vot_wot detail; /* rest of opcode table [datum] */
+};
+
+#define vot_how args
+#define vot_code code
+#define vot_detail detail
+#define vot_name name
+
+static struct vot
+votstrs[] =
+{
+{ "halt", {"", 0x00 } },
+{ "nop", {"", 0x01 } },
+{ "rei", {"", 0x02 } },
+{ "bpt", {"", 0x03 } },
+{ "ret", {"", 0x04 } },
+{ "rsb", {"", 0x05 } },
+{ "ldpctx", {"", 0x06 } },
+{ "svpctx", {"", 0x07 } },
+{ "cvtps", {"rwabrwab", 0x08 } },
+{ "cvtsp", {"rwabrwab", 0x09 } },
+{ "index", {"rlrlrlrlrlwl", 0x0a } },
+{ "crc", {"abrlrwab", 0x0b } },
+{ "prober", {"rbrwab", 0x0c } },
+{ "probew", {"rbrwab", 0x0d } },
+{ "insque", {"abab", 0x0e } },
+{ "remque", {"abwl", 0x0f } },
+{ "bsbb", {"bb", 0x10 } },
+{ "brb", {"bb", 0x11 } },
+{ "bneq", {"bb", 0x12 } },
+{ "bnequ", {"bb", 0x12 } },
+{ "beql", {"bb", 0x13 } },
+{ "beqlu", {"bb", 0x13 } },
+{ "bgtr", {"bb", 0x14 } },
+{ "bleq", {"bb", 0x15 } },
+{ "jsb", {"ab", 0x16 } },
+{ "jmp", {"ab", 0x17 } },
+{ "bgeq", {"bb", 0x18 } },
+{ "blss", {"bb", 0x19 } },
+{ "bgtru", {"bb", 0x1a } },
+{ "blequ", {"bb", 0x1b } },
+{ "bvc", {"bb", 0x1c } },
+{ "bvs", {"bb", 0x1d } },
+{ "bcc", {"bb", 0x1e } },
+{ "bgequ", {"bb", 0x1e } },
+{ "blssu", {"bb", 0x1f } },
+{ "bcs", {"bb", 0x1f } },
+{ "addp4", {"rwabrwab", 0x20 } },
+{ "addp6", {"rwabrwabrwab", 0x21 } },
+{ "subp4", {"rwabrwab", 0x22 } },
+{ "subp6", {"rwabrwabrwab", 0x23 } },
+{ "cvtpt", {"rwababrwab", 0x24 } },
+{ "mulp", {"rwabrwabrwab", 0x25 } },
+{ "cvttp", {"rwababrwab", 0x26 } },
+{ "divp", {"rwabrwabrwab", 0x27 } },
+{ "movc3", {"rwabab", 0x28 } },
+{ "cmpc3", {"rwabab", 0x29 } },
+{ "scanc", {"rwababrb", 0x2a } },
+{ "spanc", {"rwababrb", 0x2b } },
+{ "movc5", {"rwabrbrwab", 0x2c } },
+{ "cmpc5", {"rwabrbrwab", 0x2d } },
+{ "movtc", {"rwabrbabrwab", 0x2e } },
+{ "movtuc", {"rwabrbabrwab", 0x2f } },
+{ "bsbw", {"bw", 0x30 } },
+{ "brw", {"bw", 0x31 } },
+{ "cvtwl", {"rwwl", 0x32 } },
+{ "cvtwb", {"rwwb", 0x33 } },
+{ "movp", {"rwabab", 0x34 } },
+{ "cmpp3", {"rwabab", 0x35 } },
+{ "cvtpl", {"rwabwl", 0x36 } },
+{ "cmpp4", {"rwabrwab", 0x37 } },
+{ "editpc", {"rwababab", 0x38 } },
+{ "matchc", {"rwabrwab", 0x39 } },
+{ "locc", {"rbrwab", 0x3a } },
+{ "skpc", {"rbrwab", 0x3b } },
+{ "movzwl", {"rwwl", 0x3c } },
+{ "acbw", {"rwrwmwbw", 0x3d } },
+{ "movaw", {"awwl", 0x3e } },
+{ "pushaw", {"aw", 0x3f } },
+{ "addf2", {"rfmf", 0x40 } },
+{ "addf3", {"rfrfwf", 0x41 } },
+{ "subf2", {"rfmf", 0x42 } },
+{ "subf3", {"rfrfwf", 0x43 } },
+{ "mulf2", {"rfmf", 0x44 } },
+{ "mulf3", {"rfrfwf", 0x45 } },
+{ "divf2", {"rfmf", 0x46 } },
+{ "divf3", {"rfrfwf", 0x47 } },
+{ "cvtfb", {"rfwb", 0x48 } },
+{ "cvtfw", {"rfww", 0x49 } },
+{ "cvtfl", {"rfwl", 0x4a } },
+{ "cvtrfl", {"rfwl", 0x4b } },
+{ "cvtbf", {"rbwf", 0x4c } },
+{ "cvtwf", {"rwwf", 0x4d } },
+{ "cvtlf", {"rlwf", 0x4e } },
+{ "acbf", {"rfrfmfbw", 0x4f } },
+{ "movf", {"rfwf", 0x50 } },
+{ "cmpf", {"rfrf", 0x51 } },
+{ "mnegf", {"rfwf", 0x52 } },
+{ "tstf", {"rf", 0x53 } },
+{ "emodf", {"rfrbrfwlwf", 0x54 } },
+{ "polyf", {"rfrwab", 0x55 } },
+{ "cvtfd", {"rfwd", 0x56 } },
+ /* opcode 57 is not defined yet */
+{ "adawi", {"rwmw", 0x58 } },
+ /* opcode 59 is not defined yet */
+ /* opcode 5a is not defined yet */
+ /* opcode 5b is not defined yet */
+{ "insqhi", {"abaq", 0x5c } },
+{ "insqti", {"abaq", 0x5d } },
+{ "remqhi", {"aqwl", 0x5e } },
+{ "remqti", {"aqwl", 0x5f } },
+{ "addd2", {"rdmd", 0x60 } },
+{ "addd3", {"rdrdwd", 0x61 } },
+{ "subd2", {"rdmd", 0x62 } },
+{ "subd3", {"rdrdwd", 0x63 } },
+{ "muld2", {"rdmd", 0x64 } },
+{ "muld3", {"rdrdwd", 0x65 } },
+{ "divd2", {"rdmd", 0x66 } },
+{ "divd3", {"rdrdwd", 0x67 } },
+{ "cvtdb", {"rdwb", 0x68 } },
+{ "cvtdw", {"rdww", 0x69 } },
+{ "cvtdl", {"rdwl", 0x6a } },
+{ "cvtrdl", {"rdwl", 0x6b } },
+{ "cvtbd", {"rbwd", 0x6c } },
+{ "cvtwd", {"rwwd", 0x6d } },
+{ "cvtld", {"rlwd", 0x6e } },
+{ "acbd", {"rdrdmdbw", 0x6f } },
+{ "movd", {"rdwd", 0x70 } },
+{ "cmpd", {"rdrd", 0x71 } },
+{ "mnegd", {"rdwd", 0x72 } },
+{ "tstd", {"rd", 0x73 } },
+{ "emodd", {"rdrbrdwlwd", 0x74 } },
+{ "polyd", {"rdrwab", 0x75 } },
+{ "cvtdf", {"rdwf", 0x76 } },
+ /* opcode 77 is not defined yet */
+{ "ashl", {"rbrlwl", 0x78 } },
+{ "ashq", {"rbrqwq", 0x79 } },
+{ "emul", {"rlrlrlwq", 0x7a } },
+{ "ediv", {"rlrqwlwl", 0x7b } },
+{ "clrd", {"wd", 0x7c } },
+{ "clrg", {"wg", 0x7c } },
+{ "clrq", {"wd", 0x7c } },
+{ "movq", {"rqwq", 0x7d } },
+{ "movaq", {"aqwl", 0x7e } },
+{ "movad", {"adwl", 0x7e } },
+{ "pushaq", {"aq", 0x7f } },
+{ "pushad", {"ad", 0x7f } },
+{ "addb2", {"rbmb", 0x80 } },
+{ "addb3", {"rbrbwb", 0x81 } },
+{ "subb2", {"rbmb", 0x82 } },
+{ "subb3", {"rbrbwb", 0x83 } },
+{ "mulb2", {"rbmb", 0x84 } },
+{ "mulb3", {"rbrbwb", 0x85 } },
+{ "divb2", {"rbmb", 0x86 } },
+{ "divb3", {"rbrbwb", 0x87 } },
+{ "bisb2", {"rbmb", 0x88 } },
+{ "bisb3", {"rbrbwb", 0x89 } },
+{ "bicb2", {"rbmb", 0x8a } },
+{ "bicb3", {"rbrbwb", 0x8b } },
+{ "xorb2", {"rbmb", 0x8c } },
+{ "xorb3", {"rbrbwb", 0x8d } },
+{ "mnegb", {"rbwb", 0x8e } },
+{ "caseb", {"rbrbrb", 0x8f } },
+{ "movb", {"rbwb", 0x90 } },
+{ "cmpb", {"rbrb", 0x91 } },
+{ "mcomb", {"rbwb", 0x92 } },
+{ "bitb", {"rbrb", 0x93 } },
+{ "clrb", {"wb", 0x94 } },
+{ "tstb", {"rb", 0x95 } },
+{ "incb", {"mb", 0x96 } },
+{ "decb", {"mb", 0x97 } },
+{ "cvtbl", {"rbwl", 0x98 } },
+{ "cvtbw", {"rbww", 0x99 } },
+{ "movzbl", {"rbwl", 0x9a } },
+{ "movzbw", {"rbww", 0x9b } },
+{ "rotl", {"rbrlwl", 0x9c } },
+{ "acbb", {"rbrbmbbw", 0x9d } },
+{ "movab", {"abwl", 0x9e } },
+{ "pushab", {"ab", 0x9f } },
+{ "addw2", {"rwmw", 0xa0 } },
+{ "addw3", {"rwrwww", 0xa1 } },
+{ "subw2", {"rwmw", 0xa2 } },
+{ "subw3", {"rwrwww", 0xa3 } },
+{ "mulw2", {"rwmw", 0xa4 } },
+{ "mulw3", {"rwrwww", 0xa5 } },
+{ "divw2", {"rwmw", 0xa6 } },
+{ "divw3", {"rwrwww", 0xa7 } },
+{ "bisw2", {"rwmw", 0xa8 } },
+{ "bisw3", {"rwrwww", 0xa9 } },
+{ "bicw2", {"rwmw", 0xaa } },
+{ "bicw3", {"rwrwww", 0xab } },
+{ "xorw2", {"rwmw", 0xac } },
+{ "xorw3", {"rwrwww", 0xad } },
+{ "mnegw", {"rwww", 0xae } },
+{ "casew", {"rwrwrw", 0xaf } },
+{ "movw", {"rwww", 0xb0 } },
+{ "cmpw", {"rwrw", 0xb1 } },
+{ "mcomw", {"rwww", 0xb2 } },
+{ "bitw", {"rwrw", 0xb3 } },
+{ "clrw", {"ww", 0xb4 } },
+{ "tstw", {"rw", 0xb5 } },
+{ "incw", {"mw", 0xb6 } },
+{ "decw", {"mw", 0xb7 } },
+{ "bispsw", {"rw", 0xb8 } },
+{ "bicpsw", {"rw", 0xb9 } },
+{ "popr", {"rw", 0xba } },
+{ "pushr", {"rw", 0xbb } },
+{ "chmk", {"rw", 0xbc } },
+{ "chme", {"rw", 0xbd } },
+{ "chms", {"rw", 0xbe } },
+{ "chmu", {"rw", 0xbf } },
+{ "addl2", {"rlml", 0xc0 } },
+{ "addl3", {"rlrlwl", 0xc1 } },
+{ "subl2", {"rlml", 0xc2 } },
+{ "subl3", {"rlrlwl", 0xc3 } },
+{ "mull2", {"rlml", 0xc4 } },
+{ "mull3", {"rlrlwl", 0xc5 } },
+{ "divl2", {"rlml", 0xc6 } },
+{ "divl3", {"rlrlwl", 0xc7 } },
+{ "bisl2", {"rlml", 0xc8 } },
+{ "bisl3", {"rlrlwl", 0xc9 } },
+{ "bicl2", {"rlml", 0xca } },
+{ "bicl3", {"rlrlwl", 0xcb } },
+{ "xorl2", {"rlml", 0xcc } },
+{ "xorl3", {"rlrlwl", 0xcd } },
+{ "mnegl", {"rlwl", 0xce } },
+{ "casel", {"rlrlrl", 0xcf } },
+{ "movl", {"rlwl", 0xd0 } },
+{ "cmpl", {"rlrl", 0xd1 } },
+{ "mcoml", {"rlwl", 0xd2 } },
+{ "bitl", {"rlrl", 0xd3 } },
+{ "clrf", {"wf", 0xd4 } },
+{ "clrl", {"wl", 0xd4 } },
+{ "tstl", {"rl", 0xd5 } },
+{ "incl", {"ml", 0xd6 } },
+{ "decl", {"ml", 0xd7 } },
+{ "adwc", {"rlml", 0xd8 } },
+{ "sbwc", {"rlml", 0xd9 } },
+{ "mtpr", {"rlrl", 0xda } },
+{ "mfpr", {"rlwl", 0xdb } },
+{ "movpsl", {"wl", 0xdc } },
+{ "pushl", {"rl", 0xdd } },
+{ "moval", {"alwl", 0xde } },
+{ "movaf", {"afwl", 0xde } },
+{ "pushal", {"al", 0xdf } },
+{ "pushaf", {"af", 0xdf } },
+{ "bbs", {"rlabbb", 0xe0 } },
+{ "bbc", {"rlabbb", 0xe1 } },
+{ "bbss", {"rlabbb", 0xe2 } },
+{ "bbcs", {"rlabbb", 0xe3 } },
+{ "bbsc", {"rlabbb", 0xe4 } },
+{ "bbcc", {"rlabbb", 0xe5 } },
+{ "bbssi", {"rlabbb", 0xe6 } },
+{ "bbcci", {"rlabbb", 0xe7 } },
+{ "blbs", {"rlbb", 0xe8 } },
+{ "blbc", {"rlbb", 0xe9 } },
+{ "ffs", {"rlrbvbwl", 0xea } },
+{ "ffc", {"rlrbvbwl", 0xeb } },
+{ "cmpv", {"rlrbvbrl", 0xec } },
+{ "cmpzv", {"rlrbvbrl", 0xed } },
+{ "extv", {"rlrbvbwl", 0xee } },
+{ "extzv", {"rlrbvbwl", 0xef } },
+{ "insv", {"rlrlrbvb", 0xf0 } },
+{ "acbl", {"rlrlmlbw", 0xf1 } },
+{ "aoblss", {"rlmlbb", 0xf2 } },
+{ "aobleq", {"rlmlbb", 0xf3 } },
+{ "sobgeq", {"mlbb", 0xf4 } },
+{ "sobgtr", {"mlbb", 0xf5 } },
+{ "cvtlb", {"rlwb", 0xf6 } },
+{ "cvtlw", {"rlww", 0xf7 } },
+{ "ashp", {"rbrwabrbrwab", 0xf8 } },
+{ "cvtlp", {"rlrwab", 0xf9 } },
+{ "callg", {"abab", 0xfa } },
+{ "calls", {"rlab", 0xfb } },
+{ "xfc", {"", 0xfc } },
+ /* undefined opcodes here */
+{ "cvtdh", {"rdwh", 0x32fd } },
+{ "cvtgf", {"rgwh", 0x33fd } },
+{ "addg2", {"rgmg", 0x40fd } },
+{ "addg3", {"rgrgwg", 0x41fd } },
+{ "subg2", {"rgmg", 0x42fd } },
+{ "subg3", {"rgrgwg", 0x43fd } },
+{ "mulg2", {"rgmg", 0x44fd } },
+{ "mulg3", {"rgrgwg", 0x45fd } },
+{ "divg2", {"rgmg", 0x46fd } },
+{ "divg3", {"rgrgwg", 0x47fd } },
+{ "cvtgb", {"rgwb", 0x48fd } },
+{ "cvtgw", {"rgww", 0x49fd } },
+{ "cvtgl", {"rgwl", 0x4afd } },
+{ "cvtrgl", {"rgwl", 0x4bfd } },
+{ "cvtbg", {"rbwg", 0x4cfd } },
+{ "cvtwg", {"rwwg", 0x4dfd } },
+{ "cvtlg", {"rlwg", 0x4efd } },
+{ "acbg", {"rgrgmgbw", 0x4ffd } },
+{ "movg", {"rgwg", 0x50fd } },
+{ "cmpg", {"rgrg", 0x51fd } },
+{ "mnegg", {"rgwg", 0x52fd } },
+{ "tstg", {"rg", 0x53fd } },
+{ "emodg", {"rgrwrgwlwg", 0x54fd } },
+{ "polyg", {"rgrwab", 0x55fd } },
+{ "cvtgh", {"rgwh", 0x56fd } },
+ /* undefined opcodes here */
+{ "addh2", {"rhmh", 0x60fd } },
+{ "addh3", {"rhrhwh", 0x61fd } },
+{ "subh2", {"rhmh", 0x62fd } },
+{ "subh3", {"rhrhwh", 0x63fd } },
+{ "mulh2", {"rhmh", 0x64fd } },
+{ "mulh3", {"rhrhwh", 0x65fd } },
+{ "divh2", {"rhmh", 0x66fd } },
+{ "divh3", {"rhrhwh", 0x67fd } },
+{ "cvthb", {"rhwb", 0x68fd } },
+{ "cvthw", {"rhww", 0x69fd } },
+{ "cvthl", {"rhwl", 0x6afd } },
+{ "cvtrhl", {"rhwl", 0x6bfd } },
+{ "cvtbh", {"rbwh", 0x6cfd } },
+{ "cvtwh", {"rwwh", 0x6dfd } },
+{ "cvtlh", {"rlwh", 0x6efd } },
+{ "acbh", {"rhrhmhbw", 0x6ffd } },
+{ "movh", {"rhwh", 0x70fd } },
+{ "cmph", {"rhrh", 0x71fd } },
+{ "mnegh", {"rhwh", 0x72fd } },
+{ "tsth", {"rh", 0x73fd } },
+{ "emodh", {"rhrwrhwlwh", 0x74fd } },
+{ "polyh", {"rhrwab", 0x75fd } },
+{ "cvthg", {"rhwg", 0x76fd } },
+ /* undefined opcodes here */
+{ "clrh", {"wh", 0x7cfd } },
+{ "clro", {"wo", 0x7cfd } },
+{ "movo", {"rowo", 0x7dfd } },
+{ "movah", {"ahwl", 0x7efd } },
+{ "movao", {"aowl", 0x7efd } },
+{ "pushah", {"ah", 0x7ffd } },
+{ "pushao", {"ao", 0x7ffd } },
+ /* undefined opcodes here */
+{ "cvtfh", {"rfwh", 0x98fd } },
+{ "cvtfg", {"rfwg", 0x99fd } },
+ /* undefined opcodes here */
+{ "cvthf", {"rhwf", 0xf6fd } },
+{ "cvthd", {"rhwd", 0xf7fd } },
+ /* undefined opcodes here */
+{ "bugl", {"rl", 0xfdff } },
+{ "bugw", {"rw", 0xfeff } },
+ /* undefined opcodes here */
+
+{ "" , "" } /* empty is end sentinel */
+
+}; /* votstrs */
+
+/* end: vax.opcode.h */
--- /dev/null
+/* Print vax instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "param.h"
+#include "symtab.h"
+#include "vax-opcode.h"
+
+/* Vax instructions are never longer than this. */
+#define MAXLEN 62
+
+/* Number of elements in the opcode table. */
+#define NOPCODES (sizeof votstrs / sizeof votstrs[0])
+
+extern char *reg_names[];
+
+static unsigned char *print_insn_arg ();
+\f
+/* Print the vax instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i;
+ register unsigned char *p;
+ register char *d;
+
+ read_memory (memaddr, buffer, MAXLEN);
+
+ for (i = 0; i < NOPCODES; i++)
+ if (votstrs[i].detail.code == buffer[0]
+ || votstrs[i].detail.code == *(unsigned short *)buffer)
+ break;
+
+ /* Handle undefined instructions. */
+ if (i == NOPCODES)
+ {
+ fprintf (stream, "0%o", buffer[0]);
+ return 1;
+ }
+
+ fprintf (stream, "%s", votstrs[i].name);
+
+ /* Point at first byte of argument data,
+ and at descriptor for first argument. */
+ p = buffer + 1 + (votstrs[i].detail.code >= 0x100);
+ d = votstrs[i].detail.args;
+
+ if (*d)
+ fputc (' ', stream);
+
+ while (*d)
+ {
+ p = print_insn_arg (d, p, memaddr + (p - buffer), stream);
+ d += 2;
+ if (*d)
+ fprintf (stream, ",");
+ }
+ return p - buffer;
+}
+
+static unsigned char *
+print_insn_arg (d, p, addr, stream)
+ char *d;
+ register char *p;
+ CORE_ADDR addr;
+ FILE *stream;
+{
+ register int regnum = *p & 0xf;
+ float floatlitbuf;
+
+ if (*d == 'b')
+ {
+ if (d[1] == 'b')
+ fprintf (stream, "0x%x", addr + *p++ + 1);
+ else
+ {
+ fprintf (stream, "0x%x", addr + *(short *)p + 2);
+ p += 2;
+ }
+ }
+ else
+ switch ((*p++ >> 4) & 0xf)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3: /* Literal mode */
+ if (d[1] == 'd' || d[1] == 'f' || d[1] == 'g' || d[1] == 'h')
+ {
+ *(int *)&floatlitbuf = 0x4000 + ((p[-1] & 0x3f) << 4);
+ fprintf (stream, "$%f", floatlitbuf);
+ }
+ else
+ fprintf (stream, "$%d", p[-1] & 0x3f);
+ break;
+
+ case 4: /* Indexed */
+ p = (char *) print_insn_arg (d, p, addr + 1, stream);
+ fprintf (stream, "[%s]", reg_names[regnum]);
+ break;
+
+ case 5: /* Register */
+ fprintf (stream, reg_names[regnum]);
+ break;
+
+ case 7: /* Autodecrement */
+ fputc ('-', stream);
+ case 6: /* Register deferred */
+ fprintf (stream, "(%s)", reg_names[regnum]);
+ break;
+
+ case 9: /* Autoincrement deferred */
+ fputc ('@', stream);
+ if (regnum == PC_REGNUM)
+ {
+ fputc ('#', stream);
+ print_address (*(long *)p, stream);
+ p += 4;
+ break;
+ }
+ case 8: /* Autoincrement */
+ if (regnum == PC_REGNUM)
+ {
+ fputc ('#', stream);
+ switch (d[1])
+ {
+ case 'b':
+ fprintf (stream, "%d", *p++);
+ break;
+
+ case 'w':
+ fprintf (stream, "%d", *(short *)p);
+ p += 2;
+ break;
+
+ case 'l':
+ fprintf (stream, "%d", *(long *)p);
+ p += 4;
+ break;
+
+ case 'q':
+ fprintf (stream, "0x%x%08x", ((long *)p)[1], ((long *)p)[0]);
+ p += 8;
+ break;
+
+ case 'o':
+ fprintf (stream, "0x%x%08x%08x%08x",
+ ((long *)p)[3], ((long *)p)[2],
+ ((long *)p)[1], ((long *)p)[0]);
+ p += 16;
+ break;
+
+ case 'f':
+ if (INVALID_FLOAT (p, 4))
+ fprintf (stream, "<<invalid float 0x%x>>", *(int *) p);
+ else
+ fprintf (stream, "%f", *(float *) p);
+ p += 4;
+ break;
+
+ case 'd':
+ if (INVALID_FLOAT (p, 8))
+ fprintf (stream, "<<invalid float 0x%x%08x>>",
+ ((long *)p)[1], ((long *)p)[0]);
+ else
+ fprintf (stream, "%f", *(double *) p);
+ p += 8;
+ break;
+
+ case 'g':
+ fprintf (stream, "g-float");
+ p += 8;
+ break;
+
+ case 'h':
+ fprintf (stream, "h-float");
+ p += 16;
+ break;
+
+ }
+ }
+ else
+ fprintf (stream, "(%s)+", reg_names[regnum]);
+ break;
+
+ case 11: /* Byte displacement deferred */
+ fputc ('@', stream);
+ case 10: /* Byte displacement */
+ if (regnum == PC_REGNUM)
+ print_address (addr + *p + 2, stream);
+ else
+ fprintf (stream, "%d(%s)", *p, reg_names[regnum]);
+ p += 1;
+ break;
+
+ case 13: /* Word displacement deferred */
+ fputc ('@', stream);
+ case 12: /* Word displacement */
+ if (regnum == PC_REGNUM)
+ print_address (addr + *(short *)p + 3, stream);
+ else
+ fprintf (stream, "%d(%s)", *(short *)p, reg_names[regnum]);
+ p += 2;
+ break;
+
+ case 15: /* Long displacement deferred */
+ fputc ('@', stream);
+ case 14: /* Long displacement */
+ if (regnum == PC_REGNUM)
+ print_address (addr + *(long *)p + 5, stream);
+ else
+ fprintf (stream, "%d(%s)", *(long *)p, reg_names[regnum]);
+ p += 4;
+ }
+
+ return (unsigned char *) p;
+}
--- /dev/null
+/* dbgRpcLib.h - header file for remote debugging via rpc */
+
+/*
+modification history
+--------------------
+01b,04oct90,maf added VX_BOOT_FILE_INQ.
+01a,05jun90,llk extracted from xdr_dbx.h.
+*/
+
+#ifndef INCdbxRpcLibh
+#define INCdbxRpcLibh 1
+
+#define PROCESS_START 50
+#define PROCESS_WAIT 51
+#define VX_STATE_INQ 60
+#define VX_LOAD 61
+#define VX_SYMBOL_INQ 62
+#define VX_BREAK_ADD 63
+#define VX_BREAK_DELETE 64
+#define VX_FP_INQUIRE 65
+#define VX_TASK_SUSPEND 66
+#define VX_CALL_FUNC 67
+#define VX_CONV_FROM_68881 68
+#define VX_CONV_TO_68881 69
+#define VX_BOOT_FILE_INQ 70
+#define VX_SOURCE_STEP 71
+
+#endif INCdbxRpcLibh
--- /dev/null
+/* @(#)ptrace.h 1.1 86/07/07 SMI */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk borrowed.
+*/
+
+#ifndef _PTRACE_
+#define _PTRACE_
+
+/*
+ * Request values for the ptrace system call
+ */
+enum ptracereq {
+ PTRACE_TRACEME = 0, /* 0, by tracee to begin tracing */
+ PTRACE_CHILDDONE = 0, /* 0, tracee is done with his half */
+ PTRACE_PEEKTEXT, /* 1, read word from text segment */
+ PTRACE_PEEKDATA, /* 2, read word from data segment */
+ PTRACE_PEEKUSER, /* 3, read word from user struct */
+ PTRACE_POKETEXT, /* 4, write word into text segment */
+ PTRACE_POKEDATA, /* 5, write word into data segment */
+ PTRACE_POKEUSER, /* 6, write word into user struct */
+ PTRACE_CONT, /* 7, continue process */
+ PTRACE_KILL, /* 8, terminate process */
+ PTRACE_SINGLESTEP, /* 9, single step process */
+ PTRACE_ATTACH, /* 10, attach to an existing process */
+ PTRACE_DETACH, /* 11, detach from a process */
+ PTRACE_GETREGS, /* 12, get all registers */
+ PTRACE_SETREGS, /* 13, set all registers */
+ PTRACE_GETFPREGS, /* 14, get all floating point regs */
+ PTRACE_SETFPREGS, /* 15, set all floating point regs */
+ PTRACE_READDATA, /* 16, read data segment */
+ PTRACE_WRITEDATA, /* 17, write data segment */
+ PTRACE_READTEXT, /* 18, read text segment */
+ PTRACE_WRITETEXT, /* 19, write text segment */
+ PTRACE_GETFPAREGS, /* 20, get all fpa regs */
+ PTRACE_SETFPAREGS, /* 21, set all fpa regs */
+};
+#endif !_PTRACE
--- /dev/null
+/* @(#)reg.h 1.1 86/07/07 SMI */
+
+/*
+ * Copyright (c) 1986 by Sun Microsystems, Inc.
+ */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk borrowed.
+*/
+
+#ifndef _REG_
+#define _REG_
+
+#ifdef I80960
+
+/* Intel 960 register values passed over the wire by RPC: */
+
+struct regs
+{
+ int r_lreg[16]; /* local registers */
+ int r_greg[16]; /* global registers */
+ int r_pcw; /* process control word */
+ int r_acw; /* arithmetic control word */
+ int r_tcw; /* trace control word */
+};
+
+#define FP_REG_SIZE 12
+
+struct fp_status {
+ char fps_regs[4][FP_REG_SIZE]; /* floating point regs */
+};
+
+#else /* For now, just 68000 */
+
+/*
+ * Location of the users' stored
+ * registers relative to R0.
+ * Usage is u.u_ar0[XX].
+ */
+#define R0 (0)
+#define R1 (1)
+#define R2 (2)
+#define R3 (3)
+#define R4 (4)
+#define R5 (5)
+#define R6 (6)
+#define R7 (7)
+#define AR0 (8)
+#define AR1 (9)
+#define AR2 (10)
+#define AR3 (11)
+#define AR4 (12)
+#define AR5 (13)
+#define AR6 (14)
+#define AR7 (15)
+#define SP (15)
+#define PS (16)
+#define PC (17)
+
+/*
+ * And now for something completely the same...
+ */
+#ifndef LOCORE
+struct regs {
+ int r_dreg[8]; /* data registers */
+#define r_r0 r_dreg[0] /* r0 for portability */
+ int r_areg[8]; /* address registers */
+#define r_sp r_areg[7] /* user stack pointer */
+ int r_sr; /* status register (actually a short) */
+#define r_ps r_sr
+ int r_pc; /* program counter */
+};
+
+struct stkfmt {
+ int f_stkfmt : 4; /* stack format */
+ int : 2;
+ int f_vector : 10; /* vector offset */
+ short f_beibase; /* start of bus error info (if any) */
+};
+
+
+/*
+ * Struct for floating point registers and general state
+ * for the MC68881 (the sky fpp has no user visible state).
+ * If fps_flags == FPS_UNUSED, the other 68881 fields have no meaning.
+ * fps_code and fps_flags are software implemented fields.
+ * fps_flags is not used when set by user level programs,
+ * but changing fps_code has the side effect of changing u.u_code.
+ */
+
+typedef struct ext_fp {
+ int fp[3];
+} ext_fp; /* extended 96-bit 68881 fp registers */
+
+struct fp_status {
+ ext_fp fps_regs[8]; /* 68881 floating point regs */
+ int fps_control; /* 68881 control reg */
+ int fps_status; /* 68881 status reg */
+ int fps_iaddr; /* 68881 instruction address reg */
+ int fps_code; /* additional word for signals */
+ int fps_flags; /* r/o - unused, idle or busy */
+};
+#endif !LOCORE
+
+/*
+ * Values defined for `fps_flags'.
+ */
+#define FPS_UNUSED 0 /* 68881 never used yet */
+#define FPS_IDLE 1 /* 68881 instruction completed */
+#define FPS_BUSY 2 /* 68881 instruction interrupted */
+
+/*
+ * The EXT_FPS_FLAGS() macro is used to convert a pointer to an
+ * fp_istate into a value to be used for the user visible state
+ * found in fps_flags. As a speed optimization, this convertion
+ * is only done is required (e.g. the PTRACE_GETFPREGS ptrace
+ * call or when dumping core) instead of on each context switch.
+ * The tests that we base the state on are that a fpis_vers of
+ * FPIS_VERSNULL means NULL state, else a fpis_bufsiz of FPIS_IDLESZ
+ * means IDLE state, else we assume BUSY state.
+ */
+#define FPIS_VERSNULL 0x0
+#define FPIS_IDLESIZE 0x18
+
+#define EXT_FPS_FLAGS(istatep) \
+ ((istatep)->fpis_vers == FPIS_VERSNULL ? FPS_UNUSED : \
+ (istatep)->fpis_bufsiz == FPIS_IDLESIZE ? FPS_IDLE : FPS_BUSY)
+
+#ifndef LOCORE
+/*
+ * Struct for the internal state of the MC68881
+ * Although the MC68881 can have a smaller maximum for
+ * internal state, we allow for more to allow for expansion.
+ */
+#define FPIS_BUFSIZ 0xc0
+
+struct fp_istate {
+ unsigned char fpis_vers; /* version number */
+ unsigned char fpis_bufsiz; /* size of info in fpis_buf */
+ unsigned short fpis_reserved; /* reserved word */
+ unsigned char fpis_buf[FPIS_BUFSIZ]; /* fpp internal state buffer */
+};
+
+/*
+ * Structures for the status and data registers are defined here.
+ * Struct fpa_status are included in the u area.
+ * Struct fpa_regs is included in struct core.
+ */
+
+/* struct fpa_status is saved/restored during context switch */
+struct fpa_status {
+ unsigned int fpas_state; /* STATE, supervisor privileged reg */
+ unsigned int fpas_imask; /* IMASK */
+ unsigned int fpas_load_ptr; /* LOAD_PTR */
+ unsigned int fpas_ierr; /* IERR */
+ unsigned int fpas_act_instr; /* pipe active instruction halves */
+ unsigned int fpas_nxt_instr; /* pipe next instruction halves */
+ unsigned int fpas_act_d1half;/* pipe active data first half */
+ unsigned int fpas_act_d2half;/* pipe active data second half */
+ unsigned int fpas_nxt_d1half;/* pipe next data first half */
+ unsigned int fpas_nxt_d2half;/* pipe next data second half */
+ unsigned int fpas_mode3_0; /* FPA MODE3_0 register */
+ unsigned int fpas_wstatus; /* FPA WSTATUS register */
+};
+
+/*
+ * Since there are 32 contexts supported by the FPA hardware,
+ * when we do context switch on the FPA, we don't save/restore
+ * the data registers between the FPA and the u area.
+ * If there are already 32 processes using the fpa concurrently,
+ * we give an error message to the 33rd process trying to use the fpa.
+ * (Hopefully there will not be this many processes using FPA concurrently.)
+ */
+
+#define FPA_NCONTEXTS 32
+#define FPA_NDATA_REGS 32
+
+typedef struct fpa_long {
+ int fpl_data[2];
+} fpa_long; /* 64 bit double precision registers */
+
+/* Struct fpa_regs is included in struct core. */
+struct fpa_regs {
+ unsigned int fpar_flags; /* if zero, other fields are meaningless */
+ struct fpa_status fpar_status;
+ fpa_long fpar_data[FPA_NDATA_REGS];
+};
+
+/*
+ * The size of struct fpa_regs is changed from 141 ints in 3.0 to
+ * 77 ints in 3.x. A pad of this size difference is added to struct core.
+ */
+#define CORE_PADLEN 64
+
+/*
+ * If there is going to be external FPU state then we must define the FPU
+ * variable
+ */
+struct fpu {
+ struct fp_status f_fpstatus; /* External FPP state, if any */
+ struct fpa_regs f_fparegs; /* FPA registers, if any */
+ int f_pad[CORE_PADLEN]; /* see comment above */
+};
+
+#endif !LOCORE
+#endif /* !I80960 */
+#endif !_REG_
--- /dev/null
+/* vxTypes.h - VxWorks type definition header */
+
+/* Copyright 1984-1990 Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01c,05oct90,shl added copyright notice.
+ made #endif ANSI style.
+01b,10aug90,dnw added VOIDFUNCPTR
+01a,29may90,del written.
+*/
+
+#ifndef INCvxTypesh
+#define INCvxTypesh
+
+/* The following stuff must NOT be included if this include file is used
+ * from assembly language. Just #define ASMLANGUAGE before the include,
+ * to get rid of it.
+ */
+
+#ifndef ASMLANGUAGE
+
+/* vxWorks types */
+
+typedef char INT8;
+typedef short INT16;
+typedef int INT32;
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+
+typedef int BOOL;
+typedef int VOID;
+typedef int STATUS;
+typedef int ARGINT;
+
+typedef int (*FUNCPTR) (); /* ptr to function returning int */
+typedef VOID (*VOIDFUNCPTR) (); /* ptr to function returning VOID */
+
+
+/* historical definitions - now obsolete */
+
+typedef char TINY; /* obsolete */
+typedef char TBOOL; /* obsolete */
+typedef unsigned char UTINY; /* obsolete */
+
+
+/* architecture dependent typedefs */
+
+#ifdef CPU_FAMILY
+
+#if CPU_FAMILY==MC680X0
+typedef unsigned short INSTR; /* word-aligned instructions */
+#endif /* CPU_FAMILY==MC680X0 */
+
+#if CPU_FAMILY==SPARC
+typedef unsigned long INSTR; /* 32 bit word-aligned instructions */
+#endif /* CPU_FAMILY==SPARC */
+
+#endif
+
+#endif /* ASMLANGUAGE */
+#endif /* INCvxTypesh */
--- /dev/null
+/* vxWorks.h - VxWorks standard definitions header */
+
+/* Copyright 1984-1990 Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+01z,05oct90,shl added copyright notice.
+ made #endif ANSI style.
+01y,28sep90,del added I960 defines.
+01x,29may90,del moved types to vxTypes.h
+01w,09apr90,jcf added timeout definitions.
+01v,24jan90,gae moved network configuration flags here from makefile's.
+01u,01sep88,mcl definition of INSTR dependent on processor family; added SPARC.
+ +gae added MC680X0 and defined CPU_FAMILY.
+01t,08apr89,dnw added ifdef to prevent inclusion of vxWorks.h more than once.
+01s,22jun88,dnw moved READ, WRITE, and UPDATE back here from ioLib.h.
+01r,22apr88,gae oops! forgot some #endif's in 01q.
+01q,12apr88,gae removed QUICK & WAIT; added STD_{IN,OUT,ERR}.
+ fixed #define's of FALSE, TRUE, etc.
+ moved READ, WRITE, and UPDATE to ioLib.h.
+01p,04dec87,dnw added undefine of MC68000 to get around Green Hills bug that
+ pre-defines MC68000.
+01o,12nov87,ecs added type ULONG.
+01n,08feb86,dnw added types INSTR, UINT, USHORT.
+01m,14oct85,rdc added BUS types.
+01l,16jul85,jlf added conditional for NULL and EOF.
+01k,24jun85,rdc installed condtional compile so we can include in
+ assembly language files. See instructions below.
+ Added System type macro and CPU type macro.
+01j,13jun85,dnw cleaned-up, removed more obsolete stuff to wrs.h
+01i,11sep84,jlf changed name from wrs.h to vxWorks.h. removed GLOBAL.
+01h,03jun84,dnw removed IGNORE declaration.
+01g,09apr84,jlf added MEMBER_SIZE macro.
+01f,14dec83,dnw added MSB, LSB macros
+01e,17nov83,jlf added STATUS type, for routines which return a status.
+01d,13jul83,dnw added NELEMENTS macro
+01c,14May83,dnw added OFFSET macro
+01b,17Feb83,dnw added stuff from Whitesmiths std.h
+01a,15Feb83,dnw written
+*/
+
+#ifndef INCvxWorksh
+#define INCvxWorksh
+
+#if !defined(NULL) || (NULL!=0)
+#define NULL 0
+#endif
+
+#if !defined(EOF) || (EOF!=(-1))
+#define EOF (-1)
+#endif
+
+#if !defined(FALSE) || (FALSE!=0)
+#define FALSE 0
+#endif
+
+#if !defined(TRUE) || (TRUE!=1)
+#define TRUE 1
+#endif
+
+
+#define NONE (-1) /* for times when NULL won't do */
+#define EOS '\0' /* C string terminator */
+
+
+/* return status values */
+
+#define OK 0
+#define ERROR (-1)
+
+/* timeout defines */
+
+#define NO_WAIT 0
+#define WAIT_FOREVER (-1)
+
+/* low-level I/O input, output, error fd's */
+
+#define STD_IN 0
+#define STD_OUT 1
+#define STD_ERR 2
+
+/* modes - must match O_RDONLY/O_WRONLY/O_RDWR in ioLib.h! */
+
+#define READ 0
+#define WRITE 1
+#define UPDATE 2
+
+/* SYSTEM types */
+
+#define V7 1 /* ATT version 7 */
+#define SYS_V 2 /* ATT System 5 */
+#define BSD_4_2 3 /* Berkeley BSD 4.2 */
+
+/* CPU types */
+
+/* The Green Hills compiler pre-defines "MC68000"!! */
+#ifdef MC68000
+#undef MC68000
+#endif
+
+#define MC68000 1
+#define MC68010 2
+#define MC68020 3
+#define MC68030 4
+#define MC68040 5
+#define MC680X0 9
+
+#define SPARC 10
+
+#ifndef I960
+#define I960 20
+#endif
+
+#define I960KB 21
+#define I960CA 22
+
+#if CPU==MC68000 || CPU==MC68010 || CPU==MC68020 || CPU==MC68030
+#define CPU_FAMILY MC680X0
+#endif /* CPU==MC68000 || CPU==MC68010 || CPU==MC68020 || CPU==MC68030 */
+
+#if CPU==SPARC
+#define CPU_FAMILY SPARC
+#endif /* CPU==SPARC */
+
+#if CPU==I960KB
+#define CPU_FAMILY I960
+#endif /* CPU==I960KB */
+
+#if CPU==I960CA
+#define CPU_FAMILY I960
+#endif /* CPU==I960CA */
+
+/* BUS types */
+
+#define VME_BUS 1
+#define MULTI_BUS 2
+
+/* network configuration parameters */
+
+#define INET /* include internet protocols */
+#define BSD 43 /* BSD 4.3 -like OS */
+#define BSDDEBUG /* turn on debug */
+#define GATEWAY /* tables to be initialized for gateway routing */
+
+/* common macros */
+
+#define MSB(x) (((x) >> 8) & 0xff) /* most signif byte of 2-byte integer */
+#define LSB(x) ((x) & 0xff) /* least signif byte of 2-byte integer*/
+
+#define OFFSET(structure, member) /* byte offset of member in structure*/\
+ ((int) &(((structure *) 0) -> member))
+
+#define MEMBER_SIZE(structure, member) /* size of a member of a structure */\
+ (sizeof (((structure *) 0) -> member))
+
+#define NELEMENTS(array) /* number of elements in an array */ \
+ (sizeof (array) / sizeof ((array) [0]))
+
+#define FOREVER for (;;)
+
+#define max(x, y) (((x) < (y)) ? (y) : (x))
+#define min(x, y) (((x) < (y)) ? (x) : (y))
+
+
+/* storage class specifier definitions */
+
+#define FAST register
+#define IMPORT extern
+#define LOCAL static
+
+
+/* include typedefs - must come after CPU_FAMILY definitions above */
+
+#include "vxTypes.h"
+
+#endif /* INCvxWorksh */
--- /dev/null
+/* wait.h - header file for remote wait call */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk borrowed.
+*/
+
+/* Define how to access the structure that the wait system call stores.
+ On many systems, there is a structure defined for this.
+ But on vanilla-ish USG systems there is not. */
+
+#ifndef HAVE_WAIT_STRUCT
+#define WAITTYPE int
+#define WIFSTOPPED(w) (((w)&0377) == 0177)
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#define WIFEXITED(w) (((w)&0377) == 0)
+#define WRETCODE(w) ((w) >> 8)
+#define WSTOPSIG(w) ((w) >> 8)
+#define WCOREDUMP(w) (((w)&0200) != 0)
+#define WTERMSIG(w) ((w) & 0177)
+#define WSETEXIT(w, status) ((w) = (status))
+#define WSETSTOP(w,sig) ((w) = (0177 | ((sig) << 8)))
+#else
+#if FALSE
+#ifndef ORIG
+
+/* don't include sys/wait.h */
+
+#else ORIG
+#include <sys/wait.h>
+#endif ORIG
+#endif FALSE
+#define WAITTYPE union wait
+#define WRETCODE(w) (w).w_retcode
+#define WSTOPSIG(w) (w).w_stopsig
+#define WCOREDUMP(w) (w).w_coredump
+#define WTERMSIG(w) (w).w_termsig
+#define WSETEXIT(w, status) ((w).w_status = (status))
+#define WSETSTOP(w,sig) \
+ ((w).w_stopsig = (sig), (w).w_coredump = 0, (w).w_termsig = 0177)
+#endif
--- /dev/null
+/* xdr_ld.c - xdr routines for remote dbx interface to VxWorks */
+
+/* Copyright 1984,1985,1986,1987,1988,1989 Wind River Systems, Inc. */
+/*extern char copyright_wind_river[]; static char *copyright=copyright_wind_river;*/
+
+/*
+modification history
+--------------------
+01a,05jun90,llk extracted from xdr_dbx.c.
+*/
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for object files that are downloaded to VxWorks. They are used by
+remote debuggers that use RPC (such as dbxWorks and vxGdb).
+*/
+
+#include "vxWorks.h"
+#include "rpc/rpc.h"
+#include "xdr_ld.h"
+
+/* forward declarations */
+
+bool_t xdr_String(); /* xdr routine for argument list */
+
+
+/*******************************************************************************
+*
+* xdr_String - xdr routine for strings.
+*
+* Used by xdr_arg_info to handle the actual argument
+* strings. normally calls xdr_string - but does something
+* reasonable encode of null pointer.
+*/
+
+bool_t xdr_String (xdrs, strp)
+ XDR *xdrs;
+ char **strp;
+
+ {
+ if ((*strp == NULL) & (xdrs->x_op == XDR_ENCODE))
+ return(FALSE);
+ else
+ return(xdr_string(xdrs, strp, MAXSTRLEN));
+ }
+/*******************************************************************************
+*
+* xdr_ldfile - xdr routine for a single element in the load table
+*/
+
+bool_t xdr_ldfile (xdrs, objp)
+ XDR *xdrs;
+ ldfile *objp;
+
+ {
+ if (! xdr_String(xdrs, &objp->name))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->txt_addr))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->data_addr))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->bss_addr))
+ return(FALSE);
+
+ return(TRUE);
+ }
+/*******************************************************************************
+*
+* xdr_ldtabl -
+*
+* xdr routine for a list of files and load addresses loaded into VxWorks.
+*/
+
+bool_t xdr_ldtabl (xdrs,objp)
+ XDR *xdrs;
+ ldtabl *objp;
+
+ {
+ return (xdr_array (xdrs, (char *) &objp->tbl_ent, (UINT *) &objp->tbl_size,
+ MAXTBLSZ, sizeof(ldfile), xdr_ldfile));
+ }
--- /dev/null
+/* xdr_ld.h - xdr for additional dbxWorks structures */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk extracted from xdr_dbx.h.
+*/
+
+#ifndef INCxdrldh
+#define INCxdrldh
+
+#define MAXSTRLEN 256
+#define MAXTBLSZ 100
+
+/*
+ * structure used to pass back the information for a single file
+ * loaded in VxWorks
+ */
+struct ldfile {
+ char *name;
+ int txt_addr;
+ int data_addr;
+ int bss_addr;
+};
+typedef struct ldfile ldfile;
+
+/*
+ * structure used to return a list of all files loaded over to
+ * VxWorks. (VX_STATE_INQ return)
+ */
+struct ldtabl {
+ u_int tbl_size;
+ ldfile *tbl_ent;
+};
+typedef struct ldtabl ldtabl;
+
+
+bool_t xdr_ldfile();
+bool_t xdr_ldtabl();
+
+#endif INCxdrldh
--- /dev/null
+/* xdr_ptrace.c - xdr routines for remote ptrace calls */
+
+/* Copyright 1984,1985,1986,1987,1988,1989 Wind River Systems, Inc. */
+/* extern char copyright_wind_river[]; static char *copyright=copyright_wind_river;*/
+
+/*
+modification history
+--------------------
+01a,05jun90,llk extracted from xdr_ptrace.h, version 01c.
+*/
+
+#include <vxWorks.h>
+#include <rpc/rpc.h>
+#include <xdr_ptrace.h>
+
+#define MAX_LEN 32000
+
+/********************************************************************
+*
+* xdr_regs_ptr -
+*
+* xdr routine to get regs* branch of discriminated union ptrace_info
+*
+*/
+
+LOCAL bool_t xdr_regs_ptr(xdrs,objp)
+ XDR *xdrs;
+ struct regs **objp;
+ {
+ return (xdr_pointer(xdrs, (char **) objp, sizeof(struct regs), xdr_regs));
+ } /* xdr_regs_ptr */
+
+/********************************************************************
+*
+* xdr_fp_status_ptr -
+*
+* xdr routine for fp_status * branch of discrimanated union
+*
+*/
+
+LOCAL bool_t xdr_fp_status_ptr(xdrs,objp)
+ XDR *xdrs;
+ struct fp_status **objp;
+ {
+ return(xdr_pointer(xdrs, (char **) objp, sizeof(struct fp_status),
+ xdr_fp_status));
+ } /* xdr_fp_status_ptr */
+
+#ifndef I80960
+/********************************************************************
+*
+* xdr_fpa_regs_ptr -
+*
+* xdr routine for fpa_regs* branch of ptrace_info
+*
+*/
+
+LOCAL bool_t xdr_fpa_regs_ptr(xdrs,objp)
+ XDR *xdrs;
+ struct fpa_regs **objp;
+ {
+ if (! xdr_pointer(xdrs, (char **) objp, sizeof(struct fpa_regs),
+ xdr_fpa_regs))
+ return(FALSE);
+ else
+ return(TRUE);
+ } /* xdr_fpa_regs_ptr */
+#endif
+
+/********************************************************************
+*
+* xdr_c_bytes_ptr -
+*
+* xdr routine for counted bytes branch of ptrace_info
+*
+*/
+
+LOCAL bool_t xdr_c_bytes_ptr(xdrs,objp)
+ XDR *xdrs;
+ C_bytes **objp;
+ {
+ return(xdr_pointer(xdrs, (char **) objp, sizeof(C_bytes), xdr_c_bytes));
+ } /* xdr_c_bytes_ptr */
+
+/********************************************************************
+*
+* xdr_ptrace_info -
+*
+* xdr routine for discriminated union ptrace_info
+*
+*/
+
+bool_t xdr_ptrace_info(xdrs,objp)
+ XDR *xdrs;
+ Ptrace_info *objp;
+ {
+ static struct xdr_discrim choices[] =
+ {
+ { (int) REGS, xdr_regs_ptr },
+ { (int) FPREGS, xdr_fp_status_ptr },
+#ifndef I80960
+ { (int) FPAREGS, xdr_fpa_regs_ptr },
+#endif
+ { (int) DATA, xdr_c_bytes_ptr },
+ { __dontcare__, NULL }
+ };
+
+ return(xdr_union(xdrs, (enum_t *) &objp->ttype,
+ (char *) &objp->more_data, choices, xdr_void));
+ } /* xdr_ptrace_info */
+
+/********************************************************************
+*
+* xdr_rptrace -
+*
+* xdr routine for remote ptrace data into server
+*
+*/
+
+bool_t xdr_rptrace(xdrs,objp)
+ XDR *xdrs;
+ Rptrace *objp;
+ {
+ if (! xdr_int(xdrs, &objp->pid))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->data))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->addr))
+ return(FALSE);
+ if (! xdr_ptrace_info(xdrs, &objp->info))
+ return(FALSE);
+
+ return(TRUE);
+ } /* xdr_rptrace */
+
+/********************************************************************
+*
+* xdr_ptrace_return -
+*
+* xdr routine for remote ptrace data returned by server
+*
+*/
+
+bool_t xdr_ptrace_return(xdrs, objp)
+ XDR *xdrs;
+ Ptrace_return *objp;
+ {
+ if (! xdr_int(xdrs, &objp->status))
+ return(FALSE);
+ if (! xdr_int(xdrs, &objp->errno))
+ return(FALSE);
+ if (! xdr_ptrace_info(xdrs, &objp->info))
+ return(FALSE);
+
+ return(TRUE);
+ } /* xdr_ptrace_return */
+
+/********************************************************************
+*
+* xdr_c_bytes -
+*
+* xdr routine for counted bytes
+*
+*/
+bool_t xdr_c_bytes(xdrs,objp)
+ XDR *xdrs;
+ C_bytes *objp;
+ {
+ return(xdr_bytes(xdrs, &objp->bytes, (u_int *) &objp->len, MAX_LEN));
+ } /* xdr_c_bytes */
+
--- /dev/null
+/* xdr_ptrace.h - xdr header for remote ptrace structures */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk extracted from xdr_ptrace.h.
+*/
+
+
+#include "xdr_regs.h"
+#include "reg.h"
+
+/*
+ * Counted byte structure used by READ/WRITE TEXT/DATA
+ */
+struct c_bytes {
+ u_int len;
+ caddr_t bytes;
+};
+typedef struct c_bytes C_bytes;
+
+/*
+ * enum for discriminated union ptrace_info
+ */
+enum ptype {
+ NOINFO = 0, /* no additional infomation */
+ REGS = 1, /* regs (SETREGS) */
+ FPREGS = 2, /* fp_status (SETFPREGS) */
+ FPAREGS = 3, /* fpa_regs (SETFPAREGS) */
+ DATA = 4, /* c_bytes (WRITETEXT/DATA)*/
+};
+typedef enum ptype ptype;
+
+/*
+ * discrimnated union for passing additional data to be
+ * written to the debugged process. With the exception of
+ * c_bytes, the structures are defined in <machine/reg.h>
+ */
+struct ptrace_info {
+ ptype ttype;
+ caddr_t more_data;
+};
+typedef struct ptrace_info Ptrace_info;
+
+/*
+ * structure passed to server on all remote ptrace calls
+ */
+struct rptrace {
+ int pid;
+ int data;
+ int addr; /* FIX! this really should be caddr_t or something */
+ Ptrace_info info;
+};
+typedef struct rptrace Rptrace;
+/*
+ * structure returned by server on all remote ptrace calls
+ */
+struct ptrace_return {
+ int status;
+ int errno;
+ Ptrace_info info;
+};
+typedef struct ptrace_return Ptrace_return;
+
+bool_t xdr_c_bytes();
+bool_t xdr_ptrace_info();
+bool_t xdr_rptrace();
+bool_t xdr_ptrace_return();
--- /dev/null
+/* xdr_rdb.c - xdr routines for Remote Debug interface to VxWorks */
+
+/*
+modification history
+--------------------
+01a,21mar90,llk created using modification 01d of xdr_dbx.c.
+*/
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for the RDB interface for VxWorks.
+*/
+
+#include "vxWorks.h"
+#include <rpc/rpc.h>
+#include "xdr_rdb.h"
+
+/* forward declarations */
+
+bool_t
+xdr_arg_type(xdrs, objp)
+ XDR *xdrs;
+ arg_type *objp;
+{
+ if (!xdr_enum(xdrs, (enum_t *)objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_arg_value(xdrs, objp)
+ XDR *xdrs;
+ arg_value *objp;
+{
+ if (!xdr_arg_type(xdrs, &objp->type)) {
+ return (FALSE);
+ }
+ switch (objp->type) {
+ case T_BYTE:
+ if (!xdr_char(xdrs, &objp->arg_value_u.v_byte)) {
+ return (FALSE);
+ }
+ break;
+ case T_WORD:
+ if (!xdr_short(xdrs, &objp->arg_value_u.v_word)) {
+ return (FALSE);
+ }
+ break;
+ case T_INT:
+ if (!xdr_int(xdrs, &objp->arg_value_u.v_int)) {
+ return (FALSE);
+ }
+ break;
+ case T_FLOAT:
+ if (!xdr_float(xdrs, &objp->arg_value_u.v_fp)) {
+ return (FALSE);
+ }
+ break;
+ case T_DOUBLE:
+ if (!xdr_double(xdrs, &objp->arg_value_u.v_dp)) {
+ return (FALSE);
+ }
+ break;
+ case T_UNKNOWN:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_func_call(xdrs, objp)
+ XDR *xdrs;
+ func_call *objp;
+{
+ if (!xdr_int(xdrs, &objp->func_addr)) {
+ return (FALSE);
+ }
+ if (!xdr_array(xdrs, (char **)&objp->args.args_val, (u_int *)&objp->args.args_len, MAX_FUNC_ARGS, sizeof(arg_value), xdr_arg_value)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_arg_one(xdrs, objp)
+ XDR *xdrs;
+ arg_one *objp;
+{
+ if (!xdr_string(xdrs, objp, MAX_ARG_LEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+
+
+bool_t
+xdr_arg_array(xdrs, objp)
+ XDR *xdrs;
+ arg_array *objp;
+{
+ if (!xdr_array(xdrs, (char **)&objp->arg_array_val, (u_int *)&objp->arg_array_len, MAX_ARG_CNT, sizeof(arg_one), xdr_arg_one)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*********************************************************************
+*
+* xdr_EVENT_TYPE -
+*
+*/
+
+bool_t xdr_EVENT_TYPE(xdrs, objp)
+ XDR *xdrs;
+ EVENT_TYPE *objp;
+
+ {
+ if (!xdr_enum (xdrs, (enum_t *) objp))
+ return (FALSE);
+ return (TRUE);
+ }
+
+/*********************************************************************
+*
+* xdr_RDB_EVENT -
+*
+*/
+
+bool_t xdr_RDB_EVENT (xdrs, objp)
+ XDR *xdrs;
+ RDB_EVENT *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->status))
+ return (FALSE);
+ if (!xdr_int (xdrs, &objp->taskId))
+ return (FALSE);
+ if (!xdr_EVENT_TYPE (xdrs, &objp->eventType))
+ return (FALSE);
+ if (!xdr_int (xdrs, &objp->sigType))
+ return (FALSE);
+ return (TRUE);
+ }
+
+/*********************************************************************
+*
+* xdr_TASK_START -
+*
+*/
+
+bool_t
+xdr_TASK_START (xdrs, objp)
+ XDR *xdrs;
+ TASK_START *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->status))
+ return (FALSE);
+ if (!xdr_int (xdrs, &objp->pid))
+ return (FALSE);
+ return (TRUE);
+ }
+
+
+/*********************************************************************
+*
+* xdr_SYMBOL_ADDR -
+*
+*/
+
+bool_t
+xdr_SYMBOL_ADDR (xdrs, objp)
+ XDR *xdrs;
+ SYMBOL_ADDR *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->status))
+ return (FALSE);
+ if (!xdr_u_int (xdrs, &objp->addr))
+ return (FALSE);
+ return (TRUE);
+ }
+
+/*********************************************************************
+*
+* xdr_SOURCE_STEP -
+*
+*/
+
+bool_t
+xdr_SOURCE_STEP (xdrs, objp)
+ XDR *xdrs;
+ SOURCE_STEP *objp;
+
+ {
+ if (!xdr_int (xdrs, &objp->taskId))
+ return (FALSE);
+ if (!xdr_u_int (xdrs, &objp->startAddr))
+ return (FALSE);
+ if (!xdr_u_int (xdrs, &objp->endAddr))
+ return (FALSE);
+ return (TRUE);
+ }
--- /dev/null
+/* xdr_rdb.h - xdr for additional rdb structures */
+
+/*
+modification history
+--------------------
+01a,23may90,llk created using xdr_dbx.h.
+ added arg_array to replace arg_info. arg_info had
+ MAXNCMDARGS (= 100) as the max limit of char strings,
+ but it should be MAX_TASK_ARGS (= 10).
+*/
+
+#ifndef INCxdrrdbh
+#define INCxdrrdbh
+
+enum arg_type {
+ T_UNKNOWN = 0,
+ T_BYTE = 1,
+ T_WORD = 2,
+ T_INT = 3,
+ T_FLOAT = 4,
+ T_DOUBLE = 5,
+};
+typedef enum arg_type arg_type;
+bool_t xdr_arg_type();
+
+
+struct arg_value {
+ arg_type type;
+ union {
+ char v_byte;
+ short v_word;
+ int v_int;
+ float v_fp;
+ double v_dp;
+ } arg_value_u;
+};
+typedef struct arg_value arg_value;
+bool_t xdr_arg_value();
+
+struct func_call {
+ int func_addr;
+ struct {
+ u_int args_len;
+ arg_value *args_val;
+ } args;
+};
+typedef struct func_call func_call;
+bool_t xdr_func_call();
+
+
+typedef char *arg_one;
+bool_t xdr_arg_one();
+
+
+typedef struct {
+ u_int arg_array_len;
+ arg_one *arg_array_val;
+} arg_array;
+bool_t xdr_arg_array();
+
+
+/*
+ * Structures used to pass structures required for
+ * process control but not part of the standard ptrace interface
+ */
+
+/*
+ * arg_info is used to pass arguments into process start
+ */
+struct arg_info {
+ int rargc;
+ char **rargv;
+};
+typedef struct arg_info Arg_info;
+
+
+enum EVENT_TYPE {
+ EVENT_BREAK = 0,
+ EVENT_STOP = 1,
+ EVENT_EXIT = 2,
+ EVENT_BUS_ERR = 3,
+ EVENT_SUSPEND = 4,
+ EVENT_ZERO_DIV = 5,
+ EVENT_SIGNAL = 6,
+ EVENT_START = 7,
+};
+typedef enum EVENT_TYPE EVENT_TYPE;
+
+
+struct RDB_EVENT {
+ int status;
+ int taskId;
+ EVENT_TYPE eventType;
+ int sigType;
+};
+typedef struct RDB_EVENT RDB_EVENT;
+
+
+struct TASK_START {
+ int status;
+ int pid;
+};
+typedef struct TASK_START TASK_START;
+
+
+struct SYMBOL_ADDR {
+ int status;
+ u_int addr;
+};
+typedef struct SYMBOL_ADDR SYMBOL_ADDR;
+
+struct SOURCE_STEP {
+ int taskId;
+ u_int startAddr;
+ u_int endAddr;
+};
+typedef struct SOURCE_STEP SOURCE_STEP;
+
+#define MAX_ARG_CNT 10
+#define MAX_FUNC_ARGS 100
+#define MAX_ARG_LEN 100
+
+bool_t xdr_arg_info();
+bool_t xdr_EVENT_TYPE();
+bool_t xdr_RDB_EVENT();
+bool_t xdr_TASK_START();
+bool_t xdr_SYMBOL_ADDR();
+bool_t xdr_SOURCE_STEP();
+
+#define RDBPROG (u_long) 0x44444444
+#define RDBVERS (u_long) 1
+#endif INCxdrrdbh
--- /dev/null
+/* xdr_regs.c - xdr routines for 68k registers */
+
+/* Copyright 1984,1985,1986,1987,1988,1989 Wind River Systems, Inc. */
+
+/*
+DESCRIPTION
+This module contains the eXternal Data Representation (XDR) routines
+for the GDB interface for VxWorks.
+*/
+
+#include <vxWorks.h>
+#include <rpc/rpc.h>
+#include <reg.h>
+#include <xdr_regs.h>
+
+
+#ifdef I80960
+/*******************************************************************************
+*
+* xdr_regs - xdr routine for i960 registers
+*/
+
+bool_t xdr_regs (xdrs, objp)
+ XDR *xdrs;
+ struct regs *objp;
+
+ {
+ if (! xdr_opaque(xdrs, (char *) objp->r_lreg, 16 * sizeof(int)))
+ return(FALSE);
+ if (! xdr_opaque(xdrs, (char *) objp->r_greg, 16 * sizeof(int)))
+ return(FALSE);
+ if (! xdr_opaque(xdrs, (char *) &objp->r_pcw, sizeof(int)))
+ return(FALSE);
+ if (! xdr_opaque(xdrs, (char *) &objp->r_acw, sizeof(int)))
+ return(FALSE);
+ if (! xdr_opaque(xdrs, (char *) &objp->r_tcw, sizeof(int)))
+ return(FALSE);
+
+ return(TRUE);
+ }
+
+/*******************************************************************************
+*
+* xdr_fp_status - xdr routine for i960 floating point registers
+*/
+
+bool_t xdr_fp_status (xdrs, objp)
+ XDR *xdrs;
+ struct fp_status *objp;
+
+ {
+ unsigned int size = 4 * FP_REG_SIZE;
+
+ /* We use xdr_bytes to indicate how many bytes of FP regs there are! */
+ if (! xdr_bytes (xdrs, (char *) objp->fps_regs, &size, 4 * FP_REG_SIZE))
+ return (FALSE);
+ return (TRUE);
+ }
+
+/*******************************************************************************
+*
+* xdr_ext_fp - xdr for a single fp register
+*/
+
+bool_t xdr_ext_fp (xdrs, objp)
+ XDR *xdrs;
+ char *objp;
+
+ {
+ unsigned int size = FP_REG_SIZE;
+
+ if (! xdr_bytes (xdrs, objp, &size, FP_REG_SIZE))
+ return(FALSE);
+
+ return(TRUE);
+ }
+#else /* Must be 68K if it isn't i960 -- for now. FIXME! */
+
+/*******************************************************************************
+*
+* xdr_regs - xdr routine for 68k registers
+*/
+
+bool_t xdr_regs (xdrs, objp)
+ XDR *xdrs;
+ struct regs *objp;
+
+ {
+ if (! xdr_opaque(xdrs, (char *) objp->r_dreg, 8 * sizeof(int)))
+ return(FALSE);
+ if (! xdr_opaque(xdrs, (char *) objp->r_areg, 8 * sizeof(int)))
+ return(FALSE);
+ if (! xdr_opaque(xdrs, (char *) &objp->r_sr, sizeof(int)))
+ return(FALSE);
+ if (! xdr_opaque(xdrs, (char *) &objp->r_pc, sizeof(int)))
+ return(FALSE);
+
+ return(TRUE);
+ }
+
+/*******************************************************************************
+*
+* xdr_ext_fp - xdr for a single fp register
+*/
+
+bool_t xdr_ext_fp (xdrs, objp)
+ XDR *xdrs;
+ ext_fp *objp;
+
+ {
+ if (! xdr_vector(xdrs, (char *) objp->fp, 3, sizeof(int), xdr_int))
+ return(FALSE);
+
+ return(TRUE);
+ }
+/*******************************************************************************
+*
+* xdr_fp_status - xdr routine for floating point registers
+*/
+
+bool_t xdr_fp_status (xdrs, objp)
+ XDR *xdrs;
+ struct fp_status *objp;
+
+ {
+ if (! xdr_vector (xdrs, (char *) objp->fps_regs, 8,
+ sizeof(ext_fp), xdr_ext_fp))
+ return (FALSE);
+ if (! xdr_int (xdrs, &objp->fps_control))
+ return (FALSE);
+ if (! xdr_int (xdrs, &objp->fps_status))
+ return (FALSE);
+ if (! xdr_int (xdrs, &objp->fps_iaddr))
+ return (FALSE);
+ if (! xdr_int (xdrs, &objp->fps_code))
+ return (FALSE);
+ if (! xdr_int (xdrs, &objp->fps_flags))
+ return (FALSE);
+
+ return (TRUE);
+ }
+/*******************************************************************************
+*
+* xdr_fpa_status - xdr for fpa status
+*/
+
+bool_t xdr_fpa_status (xdrs, objp)
+ XDR *xdrs;
+ struct fpa_status *objp;
+
+ {
+ if (! xdr_u_int (xdrs, &objp->fpas_state))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_imask))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_load_ptr))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_ierr))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_act_instr))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_nxt_instr))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_act_d1half))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_act_d2half))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_nxt_d1half))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_nxt_d2half))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_mode3_0))
+ return (FALSE);
+ if (! xdr_u_int (xdrs, &objp->fpas_wstatus))
+ return (FALSE);
+
+ return (TRUE);
+ }
+/*******************************************************************************
+*
+* xdr_fpa_long - xdr for fpa data register
+*/
+
+bool_t xdr_fpa_long (xdrs,objp)
+ XDR *xdrs;
+ fpa_long *objp;
+
+ {
+ if (! xdr_vector (xdrs, (char *) objp->fpl_data, 2, sizeof(int), xdr_int))
+ return (FALSE);
+
+ return (TRUE);
+ }
+/*******************************************************************************
+*
+* xdr_fpa_regs - xdr for fpa_regs
+*/
+
+bool_t xdr_fpa_regs (xdrs, objp)
+ XDR *xdrs;
+ struct fpa_regs *objp;
+
+ {
+ if (! xdr_u_int (xdrs, &objp->fpar_flags))
+ return (FALSE);
+ if (! xdr_fpa_status (xdrs, &objp->fpar_status))
+ return (FALSE);
+ if (! xdr_vector (xdrs, (char *) objp->fpar_data,
+ FPA_NDATA_REGS, sizeof(fpa_long), xdr_fpa_long))
+ return (FALSE);
+
+ return (TRUE);
+ }
+
+#endif /* I80960 */
+
--- /dev/null
+/* xdr_regs.h - xdr header for 68k registers */
+
+/*
+modification history
+--------------------
+01a,05jun90,llk extracted from xdr_regs.h.
+*/
+
+/* xdr structures are defined in reg.h (a bad place for them, i might add) */
+
+bool_t xdr_regs();
+bool_t xdr_ext_fp();
+bool_t xdr_fp_status();
+bool_t xdr_fpa_status();
+bool_t xdr_fpa_long();
+bool_t xdr_fpa_regs();
--- /dev/null
+/* Parameters for execution on a 3b1.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_TERMIO
+#define USG
+
+#define MAXPATHLEN 200
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0x70000
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = blockend + regno * 4; }
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+
+#endif
--- /dev/null
+/* Definitions to make GDB run on an Altos 3068 (m68k running SVR2)
+ Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* The altos support would make a good base for a port to other USGR2 systems
+ (like the 3b1 and the Convergent miniframe). */
+
+/* This is only needed in one file, but it's cleaner to put it here than
+ putting in more #ifdef's. */
+#include <sys/page.h>
+#include <sys/net.h>
+
+#define USG
+
+#define HAVE_TERMIO
+
+#define CBREAK XTABS /* It takes all kinds... */
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#define F_OK 0
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN (1024)
+#endif
+
+/* Get sys/wait.h ie. from a Sun and edit it a little (mc68000 to m68k) */
+/* Why bother? */
+#if 0
+#define HAVE_WAIT_STRUCT
+#endif
+
+#define vfork fork
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0x1fbf000
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ if (regno <= SP_REGNUM) \
+ addr = blockend + regno * 4; \
+ else if (regno == PS_REGNUM) \
+ addr = blockend + regno * 4 + 4; \
+ else if (regno == PC_REGNUM) \
+ addr = blockend + regno * 4 + 2; \
+}
+
+#define REGISTER_ADDR(u_ar0, regno) \
+ (((regno) < PS_REGNUM) \
+ ? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)]) \
+ : (((regno) == PS_REGNUM) \
+ ? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS)) \
+ : (&((struct exception_stack *) (u_ar0))->e_PC)))
+
+#define FP_REGISTER_ADDR(u, regno) \
+ (((char *) \
+ (((regno) < FPC_REGNUM) \
+ ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
+ : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \
+ - ((char *) (& u)))
+
+\f
+#ifndef __GNUC__
+#undef USE_GAS
+#define ALTOS_AS
+#else
+#define USE_GAS
+#endif
+
+/* Motorola assembly format */
+#if !defined(USE_GAS) && !defined(ALTOS)
+#define MOTOROLA
+#endif
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#ifdef MOTOROLA
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("move.l $ end, sp"); \
+ asm ("clr.l fp"); }
+#else
+#ifdef ALTOS_AS
+#define INIT_STACK(beg, end) \
+{ asm ("global end"); \
+ asm ("mov.l &end,%sp"); \
+ asm ("clr.l %fp"); }
+#else
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+#endif
+#endif
+
+/* Push the frame pointer register on the stack. */
+#ifdef MOTOROLA
+#define PUSH_FRAME_PTR \
+ asm ("move.l fp, -(sp)");
+#else
+#ifdef ALTOS_AS
+#define PUSH_FRAME_PTR \
+ asm ("mov.l %fp, -(%sp)");
+#else
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+#endif
+#endif
+
+/* Copy the top-of-stack to the frame pointer register. */
+#ifdef MOTOROLA
+#define POP_FRAME_PTR \
+ asm ("move.l (sp), fp");
+#else
+#ifdef ALTOS_AS
+#define POP_FRAME_PTR \
+ asm ("mov.l (%sp), %fp");
+#else
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+#endif
+#endif
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#ifdef MOTOROLA
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(sp)"); \
+ asm ("pea (10,sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#else
+#ifdef ALTOS_AS
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(%sp)"); \
+ asm ("pea (10,%sp)"); \
+ asm ("movm.l &0xfffe,-(%sp)"); }
+#else
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#endif
+#endif
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#ifdef MOTOROLA
+#define POP_REGISTERS \
+{ asm ("subi.l $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#else
+#ifdef ALTOS_AS
+#define POP_REGISTERS \
+{ asm ("sub.l &8,28(%sp)"); \
+ asm ("movem (%sp),&0xffff"); \
+ asm ("rte"); }
+#else
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#endif
+#endif
--- /dev/null
+/* Definitions to make GDB run on an ARM under RISCiX (4.3bsd).
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x01000000 - (UPAGES * NBPG))
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+\f
+#if 0
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("pushl 8(sp)"); \
+ asm ("pushl 8(sp)"); \
+ asm ("pushal 0x14(sp)"); \
+ asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("popr $037777"); \
+ asm ("subl2 $8,(sp)"); \
+ asm ("movl (sp),sp"); \
+ asm ("rei"); }
+#endif /* 0 */
--- /dev/null
+/* Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#include "xm-mips.h"
--- /dev/null
+/* Definitions to make GDB run on Convex Unix (4bsd)
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define LONG_LONG
+#define ATTACH_DETACH
+#define HAVE_WAIT_STRUCT
+#define NO_SIGINTERRUPT
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Use SIGCONT rather than SIGTSTP because convex Unix occasionally
+ turkeys SIGTSTP. I think. */
+
+#define STOP_SIGNAL SIGCONT
+
+/* Use csh to do argument expansion so we get ~ and such. */
+
+/* Doesn't work. */
+/* #define SHELL_FILE "/bin/csh" */
+
+/* Compensate for lack of `vprintf' function. */
+#define MISSING_VPRINTF
+
+/* Hook to call after creating inferior process. */
+
+#define CREATE_INFERIOR_HOOK create_inferior_hook
+
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* (no kdb) */
--- /dev/null
+/* Parameters for execution on a Hewlett-Packard 9000/300, running bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Configuration file for HP9000/300 series machine running
+ * University of Utah's 4.3bsd port. This is NOT for HP-UX.
+ * Problems to hpbsd-bugs@cs.utah.edu
+ */
+
+#include <machine/endian.h>
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Get kernel u area address at run-time using BSD style nlist (). */
+#define KERNEL_U_ADDR_BSD
+
+/* This is a piece of magic that is given a register number REGNO
+ and as BLOCKEND the address in the system of the end of the user structure
+ and stores in ADDR the address in the kernel or core dump
+ of that register. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ \
+ if (regno < PS_REGNUM) \
+ addr = (int) &((struct frame *)(blockend))->f_regs[regno]; \
+ else if (regno == PS_REGNUM) \
+ addr = (int) &((struct frame *)(blockend))->f_stackadj; \
+ else if (regno == PC_REGNUM) \
+ addr = (int) &((struct frame *)(blockend))->f_pc; \
+ else if (regno < FPC_REGNUM) \
+ addr = (int) \
+ &((struct user *)0)->u_pcb.pcb_fpregs.fpf_regs[((regno)-FP0_REGNUM)*3];\
+ else if (regno == FPC_REGNUM) \
+ addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpcr; \
+ else if (regno == FPS_REGNUM) \
+ addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpsr; \
+ else \
+ addr = (int) &((struct user *)0)->u_pcb.pcb_fpregs.fpf_fpiar; \
+}
+
+/* Compensate for lack of `vprintf' function. */
+#define MISSING_VPRINTF
+
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel #end, sp"); \
+ asm ("movel #0,a6"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel a6,sp@-");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl sp@,a6");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea sp@(10)"); \
+ asm ("movem #0xfffe,sp@-"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil #8,sp@(28)"); \
+ asm ("movem sp@,#0xffff"); \
+ asm ("rte"); }
--- /dev/null
+/* Parameters for execution on an HP 9000 model 320, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Define this to indicate problems with traps after continuing. */
+#define HP_OS_BUG
+
+/* fetch_inferior_registers is in hp300hpux-dep.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* Set flag to indicate whether HP's assembler is in use. */
+#ifdef __GNUC__
+#ifdef __HPUX_ASM__
+#define HPUX_ASM
+#endif
+#else /* not GNU C. */
+#define HPUX_ASM
+#endif /* not GNU C. */
+
+/* Define this for versions of hp-ux older than 6.0 */
+/* #define HPUX_VERSION_5 */
+
+/* define USG if you are using sys5 /usr/include's */
+#undef USG /* In case it was defined in the Makefile for cplus-dem.c */
+#define USG
+
+#define HAVE_TERMIO
+
+/* Get rid of any system-imposed stack limit if possible. */
+/* The hp9k320.h doesn't seem to have this feature. */
+/* #define SET_STACK_LIMIT_HUGE */
+/* So we'll just have to avoid big alloca's. */
+#define BROKEN_LARGE_ALLOCA
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#ifdef HPUX_VERSION_5
+#define KERNEL_U_ADDR 0x00979000
+#else /* Not HPUX version 5. */
+/* Use HPUX-style nlist() to get kernel_u_addr. */
+#define KERNEL_U_ADDR_HPUX
+#endif /* Not HPUX version 5. */
+
+#define REGISTER_ADDR(u_ar0, regno) \
+ (unsigned int) \
+ (((regno) < PS_REGNUM) \
+ ? (&((struct exception_stack *) (u_ar0))->e_regs[(regno + R0)]) \
+ : (((regno) == PS_REGNUM) \
+ ? ((int *) (&((struct exception_stack *) (u_ar0))->e_PS)) \
+ : (&((struct exception_stack *) (u_ar0))->e_PC)))
+
+#define FP_REGISTER_ADDR(u, regno) \
+ (((char *) \
+ (((regno) < FPC_REGNUM) \
+ ? (&u.u_pcb.pcb_mc68881[FMC68881_R0 + (((regno) - FP0_REGNUM) * 3)]) \
+ : (&u.u_pcb.pcb_mc68881[FMC68881_C + ((regno) - FPC_REGNUM)]))) \
+ - ((char *) (& u)))
+\f
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+#ifndef HPUX_ASM
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+
+#else /* HPUX_ASM */
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm ("global end"); \
+ asm ("mov.l &end,%sp"); \
+ asm ("clr.l %a6"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("mov.l %fp,-(%sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("mov.l (%sp),%fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(%sp)"); \
+ asm ("pea 10(%sp)"); \
+ asm ("movm.l &0xfffe,-(%sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subi.l &8,28(%sp)"); \
+ asm ("mov.m (%sp),&0xffff"); \
+ asm ("rte"); }
+
+#endif /* HPUX_ASM */
--- /dev/null
+/* Macro defintions for i386.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
+Sys V/386 3.2.
+
+On some machines, gdb crashes when it's starting up while calling the
+vendor's termio tgetent() routine. It always works when run under
+itself (actually, under 3.2, it's not an infinitely recursive bug.)
+After some poking around, it appears that depending on the environment
+size, or whether you're running YP, or the phase of the moon or something,
+the stack is not always long-aligned when main() is called, and tgetent()
+takes strong offense at that. On some machines this bug never appears, but
+on those where it does, it occurs quite reliably. */
+#define ALIGN_STACK_ON_STARTUP
+
+/* define USG if you are using sys5 /usr/include's */
+#define USG
+
+/* USG systems need these */
+#define vfork() fork()
+#define MAXPATHLEN 500
+
+#define HAVE_TERMIO
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+/* #define SET_STACK_LIMIT_HUGE not in sys5 */
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0xe0000000
+
+\f
+#if 0
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) {}
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR {}
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR {}
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS {}
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS {}
+#endif /* 0 */
--- /dev/null
+/* Macro defintions for i386, running System V 3.2.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "xm-i386v.h"
+
+/* Apparently there is inconsistency among various System V's about what
+ the name of this field is. */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
+
+/* TIOCGETC is defined in System V 3.2 termio.h, but struct tchars
+ is not. This makes problems for inflow.c. */
+#define TIOCGETC_BROKEN
--- /dev/null
+/* Definitions to make GDB run on an ISI Optimum V (3.05) under 4.3bsd.
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This has not been tested on ISI's running BSD 4.2, but it will probably
+ work. */
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+/*#define KERNEL_U_ADDR 0x10800000*/
+#define KERNEL_U_ADDR 0
+
+/* expects blockend to be u.u_ar0 */
+extern int rloc[]; /* Defined in isi-dep.c */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ blockend &= UPAGES*NBPG - 1; \
+ if (regno < 18) addr = (int)blockend + rloc[regno]*4; \
+ else if (regno < 26) addr = (int) &((struct user *)0)->u_68881_regs \
+ + (regno - 18) * 12; \
+ else if (regno < 29) addr = (int) &((struct user *)0)->u_68881_regs \
+ + 8 * 12 + (regno - 26) * 4; \
+}
+
+/* Compensate for lack of `vprintf' function. */
+#define MISSING_VPRINTF
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
--- /dev/null
+/* Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is currently for a 88000 running DGUX. If other 88k ports are
+ done, OS-specific stuff should be moved (see tm-68k.h, for example). */
+/* g++ support is not yet included. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define USG
+/* DGUX has bcopy(), etc. */
+#define USG_UTILS 0
+
+#include <sys/param.h>
+
+#define vfork() fork()
+#define index strchr
+#define rindex strrchr
+#define getwd(BUF) getcwd(BUF,MAXPATHLEN);
+#define bzero(ptr,count) (memset((ptr),0,(count)))
+#define bcopy(src,dst,count) (memcpy((dst),(src),(count)))
+#define bcmp(left,right,count) (memcmp((right),(left),(count)))
+#ifdef __GNUC__
+#define memcpy __builtin_memcpy
+#define memset __builtin_memset
+#define strcmp __builtin_strcmp
+#endif
+
+#ifdef DGUX
+#define x_foff _x_x._x_offset
+#define x_fname _x_name
+#define USER ptrace_user
+#define _BSD_WAIT_FLAVOR
+#endif
+
+#define HAVE_TERMIO
+
+
+#define USIZE 2048
+#define NBPG NBPC
+#define UPAGES USIZE
+
+#define HAVE_GETPAGESIZE
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* number of traps that happen between exec'ing the shell
+ * to run an inferior, and when we finally get to
+ * the inferior code. This is 2 on most implementations.
+ */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+/* Since registers r0 through r31 are stored directly in the struct ptrace_user,
+ (for m88k BCS)
+ the ptrace_user offsets are sufficient and KERNEL_U_ADDRESS can be 0 */
+
+#define KERNEL_U_ADDR 0
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = m88k_register_u_addr ((blockend),(regno));
+
+#define HAVE_WAIT_STRUCT
+
+#define FETCH_INFERIOR_REGISTERS
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) {}
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR {}
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR {}
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS {}
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS {}
--- /dev/null
+/* Definitions to make GDB run on a merlin under utek 2.1
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This machine doesn't have the siginterrupt call. */
+#define NO_SIGINTERRUPT
+
+/* Under Utek, a ptrace'd process can be the only active process for
+ an executable. Therefore instead of /bin/sh use gdb-sh (which should
+ just be a copy of /bin/sh which is world readable and writeable). */
+#define SHELL_FILE "/usr/gnu/lib/gdb-sh"
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0xfef000)
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ \
+ switch (regno) { \
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
+ addr = blockend + (R0 - regno) * sizeof (int); break; \
+ case PC_REGNUM: \
+ addr = blockend + PC * sizeof (int); break; \
+ case SP_REGNUM: \
+ addr = blockend + SP * sizeof (int); break; \
+ case FP_REGNUM: \
+ addr = blockend + FP * sizeof (int); break; \
+ case PS_REGNUM: \
+ addr = blockend + 12 * sizeof (int); break; \
+ case FPS_REGNUM: \
+ addr = 108; break; \
+ case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
+ case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
+ case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
+ case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
+ addr = 76 + (regno - FP0_REGNUM) * sizeof (float); break; \
+ case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
+ case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
+ addr = 76 + (regno - LP0_REGNUM) * sizeof (double); break; \
+ default: \
+ printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
+ abort (); \
+ } \
+}
+
+/* Compensate for lack of `vprintf' function. */
+#define MISSING_VPRINTF
+\f
+#if 0
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("pushl 8(sp)"); \
+ asm ("pushl 8(sp)"); \
+ asm ("pushal 0x14(sp)"); \
+ asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("popr $037777"); \
+ asm ("subl2 $8,(sp)"); \
+ asm ("movl (sp),sp"); \
+ asm ("rei"); }
+#endif /* 0 */
--- /dev/null
+/* Definitions to make GDB run on a mips box under 4.3bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin
+ and by Alessandro Forin(af@cs.cmu.edu) at CMU
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (HOST_BYTE_ORDER)
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* wait.h */
+#define HAVE_WAIT_STRUCT
+
+/* Get rid of any system-imposed stack limit if possible */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This WOULD BE the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values.
+ But Mips' ptrace works on regnums, not displacements */
+
+#define KERNEL_U_ADDR (int)u.u_ar0
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+\f
+/* Interface definitions for kernel debugger KDB */
+
+/* I am not going to pretend I've done anything about this */
--- /dev/null
+/* Parameters for execution on a Sony/NEWS, for GDB, the GNU debugger.
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_WAIT_STRUCT
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* We can't use "isatty" or "fileno" on this machine. This isn't good,
+ but it will have to do. */
+#define ISATTY(FP) ((FP) == stdin || (FP) == stdout)
+
+/* THis is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR UADDR
+
+/* The offsets in this macro are from /usr/include/machine/reg.h */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ static char offsets[] = { \
+ /*d0-d7:*/1,2,3,4,5,6,7,8, \
+ /*a0-a6:*/9,10,11,12,13,14,15, /*sp:*/-4, /*ps:*/0, /*pc:*/-1, \
+ /*fp0-fp7:*/19,22,25,28,31,34,37,40, /*fpc:*/16,17,18 }; \
+ addr = blockend + 4 * offsets[regno]; \
+}
+
+/* Compensate for lack of `vprintf' function. */
+#define MISSING_VPRINTF
+
+/* NewsOS 3 apparently dies on large alloca's -- roland@ai.mit.edu. */
+#define BROKEN_LARGE_ALLOCA
+
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Use GNU assembler instead of standard assembler */
+#define USE_GAS
+
+/* Motorola assembly format */
+#ifndef USE_GAS
+#define MOTOROLA
+#endif
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#ifdef MOTOROLA
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("move.l $ end, sp"); \
+ asm ("clr.l fp"); }
+#else
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+#endif
+
+/* Push the frame pointer register on the stack. */
+#ifdef MOTOROLA
+#define PUSH_FRAME_PTR \
+ asm ("move.l fp, -(sp)");
+#else
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+#endif
+
+/* Copy the top-of-stack to the frame pointer register. */
+#ifdef MOTOROLA
+#define POP_FRAME_PTR \
+ asm ("move.l (sp), fp");
+#else
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+#endif
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#ifdef MOTOROLA
+#define PUSH_REGISTERS \
+{ asm ("clr.w -(sp)"); \
+ asm ("pea (10,sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#else
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+#endif
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#ifdef MOTOROLA
+#define POP_REGISTERS \
+{ asm ("subi.l $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#else
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
+#endif
--- /dev/null
+/* Parameters for a Sony/NEWS series 1000 with News-OS version 3,
+ for GDB, the GNU debugger.
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is required by Sony include files like <sys/user.h> so we
+ get the right offset into the u area. Relying on the compiler
+ to define this only works for cc, not gcc. */
+#undef mc68030
+#define mc68030
+#include "xm-news.h"
--- /dev/null
+/* Parameters for execution on a Gould NP1, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+#define SET_STACK_LIMIT_HUGE
+
+/* Address of U in kernel space */
+#define KERNEL_U_ADDR 0x7fffc000
+
+/* This is a piece of magic that is given a register number REGNO
+ and as BLOCKEND the address in the system of the end of the user structure
+ and stores in ADDR the address in the kernel or core dump
+ of that register. */
+#define REGISTER_U_ADDR(addr, blockend, regno) { \
+ addr = blockend + regno * 4; \
+ if (regno == VE_REGNUM) addr = blockend - 9 * 4; \
+ if (regno == PC_REGNUM) addr = blockend - 8 * 4; \
+ if (regno == PS_REGNUM) addr = blockend - 7 * 4; \
+ if (regno == FP_REGNUM) addr = blockend - 6 * 4; \
+ if (regno >= V1_REGNUM) \
+ addr = blockend + 16 * 4 + (regno - V1_REGNUM) * VR_SIZE; \
+}
+
+/* Don't try to write the frame pointer. */
+#define CANNOT_STORE_REGISTER(regno) ((regno) == FP_REGNUM)
+
+#define MISSING_VPRINTF
+\f
+/*
+ * No KDB support, Yet! */
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
--- /dev/null
+/* Parameters for execution on a Gould PN, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+#define SET_STACK_LIMIT_HUGE
+
+#define MISSING_VPRINTF
+
+/* Address of U in kernel space */
+#define KERNEL_U_ADDR 0x3fc000
+\f
+/*
+ * No KDB support, Yet! */
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
--- /dev/null
+/* Definitions to make GDB run on a Pyramidax under OSx 4.0 (4.2bsd).
+ Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Define PYRAMID_CONTROL_FRAME_DEBUGGING to get copious messages
+ about reading the control stack on standard output. This
+ makes gdb unusable as a debugger. */
+
+/* #define PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+/* Define PYRAMID_FRAME_DEBUGGING for ? */
+
+/* use Pyramid's slightly strange ptrace */
+#define PYRAMID_PTRACE
+
+/* Traditional Unix virtual address spaces have thre regions: text,
+ data and stack. The text, initialised data, and uninitialised data
+ are represented in separate segments of the a.out file.
+ When a process dumps core, the data and stack regions are written
+ to a core file. This gives a debugger enough information to
+ reconstruct (and debug) the virtual address space at the time of
+ the coredump.
+ Pyramids have an distinct fourth region of the virtual address
+ space, in which the contents of the windowed registers are stacked
+ in fixed-size frames. Pyramid refer to this region as the control
+ stack. Each call (or trap) automatically allocates a new register
+ frame; each return deallocates the current frame and restores the
+ windowed registers to their values before the call.
+
+ When dumping core, the control stack is written to a core files as
+ a third segment. The core-handling functions need to know to deal
+ with it. */
+
+/* Tell dep.c what the extra segment is. */
+#define PYRAMID_CORE
+
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* Define offsets of registers in the core file (or maybe u area) */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ struct user __u; \
+ addr = blockend + (regno - 16 ) * 4; \
+ if (regno == 67) { \
+ printf("\\geting reg 67\\"); \
+ addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u; \
+ } else if (regno == KSP_REGNUM) { \
+ printf("\\geting KSP (reg %d)\\", KSP_REGNUM); \
+ addr = (int)(&__u.u_pcb.pcb_ksp) - (int) &__u; \
+ } else if (regno == CSP_REGNUM) { \
+ printf("\\geting CSP (reg %d\\",CSP_REGNUM); \
+ addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u; \
+ } else if (regno == 64) { \
+ printf("\\geting reg 64\\"); \
+ addr = (int)(&__u.u_pcb.pcb_csp) - (int) &__u; \
+ } else if (regno == PS_REGNUM) \
+ addr = blockend - 4; \
+ else if (1 && ((16 > regno) && (regno > 11))) \
+ addr = last_frame_offset + (4 *(regno+32)); \
+ else if (0 && (12 > regno)) \
+ addr = global_reg_offset + (4 *regno); \
+ else if (16 > regno) \
+ addr = global_reg_offset + (4 *regno); \
+ else \
+ addr = blockend + (regno - 16 ) * 4; \
+}
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* Compensate for lack of `vprintf' function. */
+#define MISSING_VPRINTF
+
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* I have *no idea* how to debug OSx kernels, so this
+ is flushed, possible forever. */
--- /dev/null
+/* Parameters for execution on a Sun 4, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@mcc.com)
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Enable use of alternate code for Sun's format of core dump file. */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Before storing, we need to read all the registers. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* It does have a wait structure, and it might help things out . . . */
+
+#define HAVE_WAIT_STRUCT
+
+/* Optimization for storing registers to the inferior. The hook
+ DO_DEFERRED_STORES
+ actually executes any deferred stores. It is called any time
+ we are going to proceed the child, or read its registers.
+ The hook CLEAR_DEFERRED_STORES is called when we want to throw
+ away the inferior process, e.g. when it dies or we kill it.
+ FIXME, this does not handle remote debugging cleanly. */
+
+extern int deferred_stores;
+extern int store_inferior_registers ();
+#define DO_DEFERRED_STORES \
+ if (deferred_stores) \
+ store_inferior_registers (-2);
+#define CLEAR_DEFERRED_STORES \
+ deferred_stores = 0;
--- /dev/null
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0x2800
+
+/* Enable use of alternate code for Sun's format of core dump file. */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+/* This is a piece of magic that is given a register number REGNO
+ and as BLOCKEND the address in the system of the end of the user structure
+ and stores in ADDR the address in the kernel or core dump
+ of that register. */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = blockend + regno * 4; }
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel fp, -(sp)");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea 10(sp)"); \
+ asm ("movem $ 0xfffe,-(sp)"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil $8,28(sp)"); \
+ asm ("movem (sp),$ 0xffff"); \
+ asm ("rte"); }
--- /dev/null
+/* Parameters for execution on a Sun, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Enable use of alternate code for Sun's format of core dump file. */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We have to grab the regs since we store all regs at once. */
+
+#define CHILD_PREPARE_TO_STORE() \
+ read_register_bytes (0, (char *)NULL, REGISTER_BYTES)
+\f
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, 0, 0, 0, SIGTRAP, 0, 0, 0, \
+ 0, SIGTRAP, 0, 0, 0, 0, 0, SIGKILL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ SIGILL }
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movel #end, sp"); \
+ asm ("movel #0,a6"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("movel a6,sp@-");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl sp@,a6");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("clrw -(sp)"); \
+ asm ("pea sp@(10)"); \
+ asm ("movem #0xfffe,sp@-"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("subil #8,sp@(28)"); \
+ asm ("movem sp@,#0xffff"); \
+ asm ("rte"); }
--- /dev/null
+/* Parameters for execution on a Sun 386i, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* Enable use of alternate code for Sun's format of core dump file. */
+
+#define NEW_SUN_CORE
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#define PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
--- /dev/null
+/* Macro definitions for a sun 3 running os 4.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "xm-sun3.h"
+#define FPU
+
+/* There is a bug which can cause alloca to fail to allocate large
+ areas of memory one time in every 4096 (we think). */
+/* chase@orc.olivetti.com says that 4 megabyte alloca's consistently fail,
+ even though the stack limit (SET_STACK_LIMIT_HUGE) has been set
+ to 250 megabytes. */
+#define BROKEN_LARGE_ALLOCA
--- /dev/null
+/* Macro definitions for running gdb on a Sun 4 running sunos 4.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "xm-sparc.h"
+
+#define FPU
--- /dev/null
+/* Definitions to make GDB run on a Sequent Symmetry under dynix 3.0,
+ with Weitek 1167 and i387 support.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Symmetry version by Jay Vosburgh (uunet!sequent!fubar) */
+
+/* This machine doesn't have the siginterrupt call. */
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+/* XPT_DEBUG doesn't work yet under Dynix 3.0.12, but UNDEBUG does... */
+/* #define PTRACE_ATTACH XPT_DEBUG
+#define PTRACE_DETACH XPT_UNDEBUG
+#define ATTACH_DETACH */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* Compensate for lack of `vprintf' function. */
+
+#define MISSING_VPRINTF
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We must fetch all the regs before storing, since we store all at once. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+\f
+/* Interface definitions for kernel debugger KDB. */
+/* This doesn't work... */
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, %esp"); \
+ asm ("movl %ebp, $0"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("pushl %ebp");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (%esp), %ebp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm("pushad"); }
+/*
+{ asm("pushl %eax"); \
+ asm("pushl %edx"); \
+ asm("pushl %ecx"); \
+ asm("pushl %st(0)"); \
+ asm("pushl %st(1)"); \
+ asm("pushl %ebx"); \
+ asm("pushl %esi"); \
+ asm("pushl %edi"); \
+ asm("pushl %st(2)"); \
+ asm("pushl %st(3)"); \
+ asm("pushl %st(4)"); \
+ asm("pushl %st(5)"); \
+ asm("pushl %st(6)"); \
+ asm("pushl %st(7)"); \
+ asm("pushl %esp"); \
+ asm("pushl %ebp"); \
+ asm("pushl %eip"); \
+ asm("pushl %eflags"); \
+ asm("pushl %fp1"); \
+ asm("pushl %fp2"); \
+ asm("pushl %fp3"); \
+ asm("pushl %fp4"); \
+ asm("pushl %fp5"); \
+ asm("pushl %fp6"); \
+ asm("pushl %fp7"); \
+ asm("pushl %fp8"); \
+ asm("pushl %fp9"); \
+ asm("pushl %fp10"); \
+ asm("pushl %fp11"); \
+ asm("pushl %fp12"); \
+ asm("pushl %fp13"); \
+ asm("pushl %fp14"); \
+ asm("pushl %fp15"); \
+ asm("pushl %fp16"); \
+ asm("pushl %fp17"); \
+ asm("pushl %fp18"); \
+ asm("pushl %fp19"); \
+ asm("pushl %fp20"); \
+ asm("pushl %fp21"); \
+ asm("pushl %fp22"); \
+ asm("pushl %fp23"); \
+ asm("pushl %fp24"); \
+ asm("pushl %fp25"); \
+ asm("pushl %fp26"); \
+ asm("pushl %fp27"); \
+ asm("pushl %fp28"); \
+ asm("pushl %fp29"); \
+ asm("pushl %fp30"); \
+ asm("pushl %fp31"); \
+}
+*/
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("popad"); }
--- /dev/null
+/* Definitions to make GDB run on an encore under umax 4.2
+ Copyright (C) 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#define HAVE_WAIT_STRUCT
+
+/* Offset of registers within u area. */
+#define U_REGS_OFFSET 0
+
+/* Do implement the attach and detach commands... */
+#define ATTACH_DETACH
+
+/* Doesn't have siginterupt. */
+#define NO_SIGINTERRUPT
+
+/* called from register_addr() -- blockend not used for now */
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ \
+ switch (regno) { \
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: \
+ addr = PU_R0 - (regno * sizeof (int)); break; \
+ case SP_REGNUM: \
+ addr = PU_SP; break; \
+ case PC_REGNUM: \
+ addr = PU_PC; break; \
+ case FP_REGNUM: \
+ addr = PU_FP; break; \
+ case PS_REGNUM: \
+ addr = PU_PSL; break; \
+ case FPS_REGNUM: \
+ addr = PU_FSR; break; \
+ case FP0_REGNUM + 0: case FP0_REGNUM + 1: \
+ case FP0_REGNUM + 2: case FP0_REGNUM + 3: \
+ case FP0_REGNUM + 4: case FP0_REGNUM + 5: \
+ case FP0_REGNUM + 6: case FP0_REGNUM + 7: \
+ addr = PU_F0 + (regno - FP0_REGNUM) * sizeof (float); break; \
+ case LP0_REGNUM + 0: case LP0_REGNUM + 1: \
+ case LP0_REGNUM + 2: case LP0_REGNUM + 3: \
+ addr = PU_F0 + (regno - LP0_REGNUM) * sizeof (double); break; \
+ default: \
+ printf ("bad argument to REGISTER_U_ADDR %d\n", regno); \
+ abort (); \
+ } \
+}
+
+/* Compensate for lack of `vprintf' function. */
+#define MISSING_VPRINTF
--- /dev/null
+/* Definitions to make GDB run on a vax under 4.2bsd.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ addr = blockend - 0110 + regno * 4; \
+ if (regno == PC_REGNUM) addr = blockend - 8; \
+ if (regno == PS_REGNUM) addr = blockend - 4; \
+ if (regno == FP_REGNUM) addr = blockend - 0120; \
+ if (regno == AP_REGNUM) addr = blockend - 0124; \
+ if (regno == SP_REGNUM) addr = blockend - 20; }
+
+/* Interface definitions for kernel debugger KDB. */
+
+/* Map machine fault codes into signal numbers.
+ First subtract 0, divide by 4, then index in a table.
+ Faults for which the entry in this table is 0
+ are not handled by KDB; the program's own trap handler
+ gets to handle then. */
+
+#define FAULT_CODE_ORIGIN 0
+#define FAULT_CODE_UNITS 4
+#define FAULT_TABLE \
+{ 0, SIGKILL, SIGSEGV, 0, 0, 0, 0, 0, \
+ 0, 0, SIGTRAP, SIGTRAP, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+
+/* Start running with a stack stretching from BEG to END.
+ BEG and END should be symbols meaningful to the assembler.
+ This is used only for kdb. */
+
+#define INIT_STACK(beg, end) \
+{ asm (".globl end"); \
+ asm ("movl $ end, sp"); \
+ asm ("clrl fp"); }
+
+/* Push the frame pointer register on the stack. */
+#define PUSH_FRAME_PTR \
+ asm ("pushl fp");
+
+/* Copy the top-of-stack to the frame pointer register. */
+#define POP_FRAME_PTR \
+ asm ("movl (sp), fp");
+
+/* After KDB is entered by a fault, push all registers
+ that GDB thinks about (all NUM_REGS of them),
+ so that they appear in order of ascending GDB register number.
+ The fault code will be on the stack beyond the last register. */
+
+#define PUSH_REGISTERS \
+{ asm ("pushl 8(sp)"); \
+ asm ("pushl 8(sp)"); \
+ asm ("pushal 0x14(sp)"); \
+ asm ("pushr $037777"); }
+
+/* Assuming the registers (including processor status) have been
+ pushed on the stack in order of ascending GDB register number,
+ restore them and return to the address in the saved PC register. */
+
+#define POP_REGISTERS \
+{ asm ("popr $037777"); \
+ asm ("subl2 $8,(sp)"); \
+ asm ("movl (sp),sp"); \
+ asm ("rei"); }
--- /dev/null
+/* Special version of <a.out.h> for use under hp-ux.
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* The `exec' structure and overall layout must be close to HP's when
+ we are running on an HP system, otherwise we will not be able to
+ execute the resulting file. */
+
+/* Allow this file to be included twice. */
+#ifndef __GNU_EXEC_MACROS__
+
+struct exec
+{
+ unsigned short a_machtype; /* machine type */
+ unsigned short a_magic; /* magic number */
+ unsigned long a_spare1;
+ unsigned long a_spare2;
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned long a_trsize; /* length of relocation info for text, in bytes */
+ unsigned long a_drsize; /* length of relocation info for data, in bytes */
+ unsigned long a_spare3; /* HP = pascal interface size */
+ unsigned long a_spare4; /* HP = symbol table size */
+ unsigned long a_spare5; /* HP = debug name table size */
+ unsigned long a_entry; /* start address */
+ unsigned long a_spare6; /* HP = source line table size */
+ unsigned long a_spare7; /* HP = value table size */
+ unsigned long a_syms; /* length of symbol table data in file, in bytes */
+ unsigned long a_spare8;
+};
+
+/* Tell a.out.gnu.h not to define `struct exec'. */
+#define __STRUCT_EXEC_OVERRIDE__
+
+#include "../a.out.gnu.h"
+
+#undef N_MAGIC
+#undef N_MACHTYPE
+#undef N_FLAGS
+#undef N_SET_INFO
+#undef N_SET_MAGIC
+#undef N_SET_MACHTYPE
+#undef N_SET_FLAGS
+
+#define N_MAGIC(exec) ((exec) . a_magic)
+#define N_MACHTYPE(exec) ((exec) . a_machtype)
+#define N_SET_MAGIC(exec, magic) (((exec) . a_magic) = (magic))
+#define N_SET_MACHTYPE(exec, machtype) (((exec) . a_machtype) = (machtype))
+
+#undef N_BADMAG
+#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x)))
+
+#define _N_BADMACH(x) \
+(((N_MACHTYPE (x)) != HP9000S200_ID) && \
+ ((N_MACHTYPE (x)) != HP98x6_ID))
+
+#define HP98x6_ID 0x20A
+#define HP9000S200_ID 0x20C
+
+#undef _N_HDROFF
+#define _N_HDROFF(x) (SEGMENT_SIZE - (sizeof (struct exec)))
+
+#define SEGMENT_SIZE 0x1000
+
+#endif /* __GNU_EXEC_MACROS__ */
--- /dev/null
+Sun Mar 11 04:32:03 1990 Brian Fox (bfox at gnuwest.fsf.org)
+
+ * Signals are now supposedly handled inside of SYSV compilation.
+
+Wed Jan 17 19:24:09 1990 Brian Fox (bfox at sbphy.ucsb.edu)
+
+ * history.c: history_expand (); fixed overwriting memory error,
+ added needed argument to call to get_history_event ().
+
+Thu Jan 11 10:54:04 1990 Brian Fox (bfox at sbphy.ucsb.edu)
+
+ * readline.c, readline.h: added rl_show_star to control the
+ display of an asterisk on modified history lines.
+
+Thu Jan 4 10:38:05 1990 Brian Fox (bfox at sbphy.ucsb.edu)
+
+ * readline.c: start_insert (). Only use IC if we don't have an im
+ capability.
+
+Fri Sep 8 09:00:45 1989 Brian Fox (bfox at aurel)
+
+ * readline.c: rl_prep_terminal (). Only turn on 8th bit
+ as meta-bit iff the terminal is not using parity.
+
+Sun Sep 3 08:57:40 1989 Brian Fox (bfox at aurel)
+
+ * readline.c: start_insert (). Uses multiple
+ insertion call in cases where that makes sense.
+
+ rl_insert (). Read type-ahead buffer for additional
+ keys that are bound to rl_insert, and insert them
+ all at once. Make insertion of single keys given
+ with an argument much more efficient.
+
+Tue Aug 8 18:13:57 1989 Brian Fox (bfox at aurel)
+
+ * readline.c: Changed handling of EOF. readline () returns
+ (char *)EOF or consed string. The EOF character is read from the
+ tty, or if the tty doesn't have one, defaults to C-d.
+
+ * readline.c: Added support for event driven programs.
+ rl_event_hook is the address of a function you want called
+ while Readline is waiting for input.
+
+ * readline.c: Cleanup time. Functions without type declarations
+ do not use return with a value.
+
+ * history.c: history_expand () has new variable which is the
+ characters to ignore immediately following history_expansion_char.
+
+Sun Jul 16 08:14:00 1989 Brian Fox (bfox at aurel)
+
+ * rl_prep_terminal ()
+ BSD version turns off C-s, C-q, C-y, C-v.
+
+ * readline.c -- rl_prep_terminal ()
+ SYSV version hacks readline_echoing_p.
+ BSD version turns on passing of the 8th bit for the duration
+ of reading the line.
+
+Tue Jul 11 06:25:01 1989 Brian Fox (bfox at aurel)
+
+ * readline.c: new variable rl_tilde_expander.
+ If non-null, this contains the address of a function to call if
+ the standard meaning for expanding a tilde fails. The function is
+ called with the text sans tilde (as in "foo"), and returns a
+ malloc()'ed string which is the expansion, or a NULL pointer if
+ there is no expansion.
+
+ * readline.h - new file chardefs.h
+ Separates things that only readline.c needs from the standard
+ header file publishing interesting things about readline.
+
+ * readline.c:
+ readline_default_bindings () now looks at terminal chararacters
+ and binds those as well.
+
+Wed Jun 28 20:20:51 1989 Brian Fox (bfox at aurel)
+
+ * Made readline and history into independent libraries.
+
+
--- /dev/null
+\input texinfo.tex
+@setfilename history.info
+
+@ifinfo
+This file documents the GNU History library.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@node Top, Introduction, , (DIR)
+
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+@menu
+* Introduction:: What is the GNU History library for?
+* Interactive Use:: What it feels like using History as a user.
+* Programming:: How to use History in your programs.
+@end menu
+
+@node Introduction, Interactive Use, , Top
+@unnumbered Introduction
+
+Many programs read input from the user a line at a time. The GNU history
+library is able to keep track of those lines, associate arbitrary data with
+each line, and utilize information from previous lines in making up new
+ones.
+
+The programmer using the History library has available to him functions for
+remembering lines on a history stack, associating arbitrary data with a
+line, removing lines from the stack, searching through the stack for a
+line containing an arbitrary text string, and referencing any line on the
+stack directly. In addition, a history @dfn{expansion} function is
+available which provides for a consistent user interface across many
+different programs.
+
+The end-user using programs written with the History library has the
+benifit of a consistent user interface, with a set of well-known commands
+for manipulating the text of previous lines and using that text in new
+commands. The basic history manipulation commands are similar to the
+history substitution used by Csh.
+
+If the programmer desires, he can use the Readline library, which includes
+history manipulation by default, and has the added advantage of Emacs style
+command line editing.
+
+@node Interactive Use, Programming, Introduction, Top
+@chapter Interactive Use
+
+@section History Expansion
+@cindex expansion
+
+The History library provides a history expansion feature that is similar to
+the history expansion in Csh. The following text describes what syntax
+features are available.
+
+History expansion takes place in two parts. The first is to determine
+which line from the previous history should be used during substitution.
+The second is to select portions of that line for inclusion into the
+current one. The line selected from the previous history is called the
+@dfn{event}, and the portions of that line that are acted upon are called
+@dfn{words}. The line is broken into words in the same fashion that the
+Bash shell does, so that several English (or Unix) words surrounded by
+quotes are considered as one word.
+
+@menu
+* Event Designators:: How to specify which history line to use.
+* Word Designators:: Specifying which words are of interest.
+* Modifiers:: Modifying the results of susbstitution.
+@end menu
+
+@node Event Designators, Word Designators, , Interactive Use
+@subsection Event Designators
+@cindex event designators
+
+An event designator is a reference to a command line entry in the history
+list.
+
+@table @var
+
+@item !
+Start a history subsititution, except when followed by a @key{SPC},
+@key{TAB}, @key{RET}, @key{=} or @key{(}.
+
+@item !!
+Refer to the previous command. This is a synonym for @code{!-1}.
+
+@item !n
+Refer to command line @var{n}.
+
+@item !-n
+Refer to the current command line minus @var{n}.
+
+@item !string
+Refer to the most recent command starting with @var{string}.
+
+@item !?string[?]
+Refer to the most recent command containing @var{string}.
+
+@end table
+
+@node Word Designators, Modifiers, Event Designators, Interactive Use
+@subsection Word Designators
+
+A @key{:} separates the event specification from the word designator. It
+can be omitted if the word designator begins with a @key{^}, @key{$},
+@key{*} or @key{%}. Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+
+@table @asis
+
+@item @var{0} (zero)
+The zero'th word. For many applications, this is the command word.
+
+@item n
+The @var{n}'th word.
+
+@item @var{^}
+The first argument. that is, word 1.
+
+@item @var{$}
+The last argument.
+
+@item @var{%}
+The word matched by the most recent @code{?string?} search.
+
+@item @var{x}-@var{y}
+A range of words; @code{-@var{y}} is equivalent to @code{0-@var{y}}.
+
+@item @var{*}
+All of the words, excepting the zero'th. This is a synonym for @samp{1-$}.
+It is not an error to use @samp{*} if there is just one word in the event.
+The empty string is returned in that case.
+
+@end table
+
+@node Modifiers, , Word Designators, Interactive Use
+@subsection Modifiers
+
+After the optional word designator, you can add a sequence of one or more
+of the following modifiers, each preceded by a @key{:}.
+
+@table @code
+
+@item #
+The entire command line typed so far. This means the current command,
+not the previous command, so it really isn't a word designator, and doesn't
+belong in this section.
+
+@item h
+Remove a trailing pathname component, leaving only the head.
+
+@item r
+Remove a trailing suffix of the form ".xxx", leaving the basename (root).
+
+@item e
+Remove all but the suffix (end).
+
+@item t
+Remove all leading pathname components (before the last slash), leaving
+the tail.
+
+@item p
+Print the new command but do not execute it. This takes effect
+immediately, so it should be the last specifier on the line.
+
+@end table
+
+@node Programming, , Interactive Use, Top
+@chapter Programming
+
+@bye
--- /dev/null
+\input texinfo @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename readline.info
+@settitle Line Editing Commands
+@comment %**end of header (This is for running Texinfo on a region.)
+@synindex fn vr
+
+@iftex
+@comment finalout
+@end iftex
+
+@ifinfo
+This document describes the GNU Readline Library, a utility for aiding
+in the consitency of user interface across discrete programs that need
+to provide a command line interface.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@setchapternewpage odd
+@titlepage
+@sp 11
+@center @titlefont{GNU Readline Library}
+@sp 2
+@center by Brian Fox
+@sp 2
+@center Version 1.0
+@sp 2
+@center February 1989
+
+@comment Include the Distribution inside the titlepage environment so
+@c that headings are turned off.
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989 Free Software Foundation, Inc.
+
+@sp 2
+This document describes the GNU Readline Library, a utility for aiding
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+@sp 2
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@end titlepage
+
+@node Top, Readline Top, ,(DIR)
+@chapter GNU Readline Library
+
+@ifinfo
+This document describes the GNU Readline Library, a utility for aiding
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+@end ifinfo
+
+@menu
+* Readline Top:: GNU Readline User's Manual
+* Readline Technical:: GNU Readline Programmer's Manual
+@end menu
+@include inc-readline.texinfo
+@node Readline Technical, , Top, Top
+@chapter Readline Programmer's Manual
+
+This manual describes the interface between the GNU Readline Library and
+user programs. If you are a programmer, and you wish to include the
+features found in GNU Readline in your own programs, such as completion,
+line editing, and interactive history manipulation, this documentation
+is for you.
+
+@menu
+* Default Behaviour:: Using the default behaviour of Readline.
+* Custom Functions:: Adding your own functions to Readline.
+* Custom Completers:: Supplanting or supplementing Readline's
+ completion functions.
+* Variable Index:: Index of externally tweakable variables.
+@end menu
+
+@node Default Behaviour, Custom Functions, Readline Technical, Readline Technical
+@section Default Behaviour
+
+Many programs provide a command line interface, such as @code{mail},
+@code{ftp}, and @code{sh}. For such programs, the default behaviour of
+Readline is sufficient. This section describes how to use Readline in
+the simplest way possible, perhaps to replace calls in your code to
+@code{gets ()}.
+
+@findex readline ()
+@cindex readline, function
+The function @code{readline} prints a prompt and then reads and returns
+a single line of text from the user. The line which @code{readline ()}
+returns is allocated with @code{malloc ()}; you should @code{free ()}
+the line when you are done with it. The declaration in ANSI C is
+
+@example
+@code{char *readline (char *@var{prompt});}
+@end example
+or, preferably,
+@example
+@code{#include <readline/readline.h>}
+@end example
+
+So, one might say
+@example
+@code{char *line = readline ("Enter a line: ");}
+@end example
+in order to read a line of text from the user.
+
+The line which is returned has the final newline removed, so only the
+text of the line remains.
+
+If readline encounters an EOF while reading the line, and the line is
+empty at that point, then @code{(char *)NULL} is returned. Otherwise,
+the line is ended just as if a newline was typed.
+
+If you want the user to be able to get at the line later, (with
+@key{C-p} for example), you must call @code{add_history ()} to save the
+line away in a @dfn{history} list of such lines.
+
+@example
+@code{add_history (line)};
+@end example
+
+If you use @code{add_history ()}, you should also
+@code{#include <readline/history.h>}
+For full details on the GNU History Library, see the associated manual.
+
+It is polite to avoid saving empty lines on the history list, since
+no one has a burning need to reuse a blank line. Here is a function
+which usefully replaces the standard @code{gets ()} library function:
+
+@example
+#include <readline/readline.h>
+#include <readline/history.h>
+
+/* A static variable for holding the line. */
+static char *my_gets_line = (char *)NULL;
+
+/* Read a string, and return a pointer to it. Returns NULL on EOF. */
+char *
+my_gets ()
+@{
+ /* If the buffer has already been allocated, return the memory
+ to the free pool. */
+ if (my_gets_line != (char *)NULL)
+ free (my_gets_line);
+
+ /* Get a line from the user. */
+ my_gets_line = readline ("");
+
+ /* If the line has any text in it, save it on the history. */
+ if (my_get_line && *my_gets_line)
+ add_history (my_gets_line);
+
+ return (my_gets_line);
+@}
+@end example
+
+The above code gives the user the default behaviour of @key{TAB}
+completion: completion on file names. If you do not want readline to
+complete on filenames, you can change the binding of the @key{TAB} key
+with @code{rl_bind_key ()}.
+
+@findex rl_bind_key ()
+
+@example
+@code{int rl_bind_key (int @var{key}, (int (*)())@var{function});}
+@end example
+
+@code{rl_bind_key ()} takes 2 arguments; @var{key} is the character that
+you want to bind, and @var{function} is the address of the function to
+run when @var{key} is pressed. Binding @key{TAB} to @code{rl_insert ()}
+makes @key{TAB} just insert itself.
+
+@code{rl_bind_key ()} returns non-zero if @var{key} is not a valid
+ASCII character code (between 0 and 255).
+
+@example
+@code{rl_bind_key ('\t', rl_insert);}
+@end example
+
+@node Custom Functions, Custom Completers, Default Behaviour, Readline Technical
+@section Custom Functions
+
+Readline provides a great many functions for manipulating the text of
+the line. But it isn't possible to anticipate the needs of all
+programs. This section describes the various functions and variables
+defined in within the Readline library which allow a user program to add
+customized functionality to Readline.
+
+@menu
+* The Function Type:: C declarations to make code readable.
+* Function Naming:: How to give a function you write a name.
+* Keymaps:: Making keymaps.
+* Binding Keys:: Changing Keymaps.
+* Function Writing:: Variables and calling conventions.
+* Allowing Undoing:: How to make your functions undoable.
+@end menu
+
+@node The Function Type, Function Naming, Custom Functions, Custom Functions
+For the sake of readabilty, we declare a new type of object, called
+@dfn{Function}. `Function' is a C language function which returns an
+@code{int}. The type declaration for `Function' is:
+
+@code{typedef int Function ();}
+
+The reason for declaring this new type is to make it easier to discuss
+pointers to C functions. Let us say we had a variable called @var{func}
+which was a pointer to a function. Instead of the classic C declaration
+
+@code{int (*)()func;}
+
+we have
+
+@code{Function *func;}
+
+@node Function Naming, Keymaps, The Function Type, Custom Functions
+@subsection Naming a Function
+
+The user can dynamically change the bindings of keys while using
+Readline. This is done by representing the function with a descriptive
+name. The user is able to type the descriptive name when referring to
+the function. Thus, in an init file, one might find
+
+@example
+Meta-Rubout: backward-kill-word
+@end example
+
+This binds @key{Meta-Rubout} to the function @emph{descriptively} named
+@code{backward-kill-word}. You, as a programmer, should bind the
+functions you write to descriptive names as well. Here is how to do
+that.
+
+@defun rl_add_defun (char *name, Function *function, int key)
+Add @var{name} to the list of named functions. Make @var{function} be
+the function that gets called. If @var{key} is not -1, then bind it to
+@var{function} using @code{rl_bind_key ()}.
+@end defun
+
+Using this function alone is sufficient for most applications. It is
+the recommended way to add a few functions to the default functions that
+Readline has built in already. If you need to do more or different
+things than adding a function to Readline, you may need to use the
+underlying functions described below.
+
+@node Keymaps, Binding Keys, Function Naming, Custom Functions
+@subsection Selecting a Keymap
+
+Key bindings take place on a @dfn{keymap}. The keymap is the
+association between the keys that the user types and the functions that
+get run. You can make your own keymaps, copy existing keymaps, and tell
+Readline which keymap to use.
+
+@defun rl_make_bare_keymap ()
+Returns a new, empty keymap. The space for the keymap is allocated with
+@code{malloc ()}; you should @code{free ()} it when you are done.
+@end defun
+
+@defun rl_copy_keymap (Keymap map)
+Return a new keymap which is a copy of @var{map}.
+@end defun
+
+@defun rl_make_keymap ()
+Return a new keymap with the printing characters bound to rl_insert,
+the lowercase Meta characters bound to run their equivalents, and
+the Meta digits bound to produce numeric arguments.
+@end defun
+
+@node Binding Keys, Function Writing, Keymaps, Custom Functions
+@subsection Binding Keys
+
+You associate keys with functions through the keymap. Here are
+the functions for doing that.
+
+@defun rl_bind_key (int key, Function *function)
+Binds @var{key} to @var{function} in the currently selected keymap.
+Returns non-zero in the case of an invalid @var{key}.
+@end defun
+
+@defun rl_bind_key_in_map (int key, Function *function, Keymap map)
+Bind @var{key} to @var{function} in @var{map}. Returns non-zero in the case
+of an invalid @var{key}.
+@end defun
+
+@defun rl_unbind_key (int key)
+Make @var{key} do nothing in the currently selected keymap.
+Returns non-zero in case of error.
+@end defun
+
+@defun rl_unbind_key_in_map (int key, Keymap map)
+Make @var{key} be bound to the null function in @var{map}.
+Returns non-zero in case of error.
+@end defun
+
+@node Function Writing, Allowing Undoing, Binding Keys, Custom Functions
+@subsection Writing a New Function
+
+In order to write new functions for Readline, you need to know the
+calling conventions for keyboard invoked functions, and the names of the
+variables that describe the current state of the line gathered so far.
+
+@defvar char *rl_line_buffer
+This is the line gathered so far. You are welcome to modify the
+contents of this, but see Undoing, below.
+@end defvar
+
+@defvar int rl_point
+The offset of the current cursor position in @var{rl_line_buffer}.
+@end defvar
+
+@defvar int rl_end
+The number of characters present in @code{rl_line_buffer}. When
+@code{rl_point} is at the end of the line, then @code{rl_point} and
+@code{rl_end} are equal.
+@end defvar
+
+The calling sequence for a command @code{foo} looks like
+
+@example
+@code{foo (count, key)}
+@end example
+
+where @var{count} is the numeric argument (or 1 if defaulted) and
+@var{key} is the key that invoked this function.
+
+It is completely up to the function as to what should be done with the
+numeric argument; some functions use it as a repeat count, other
+functions as a flag, and some choose to ignore it. In general, if a
+function uses the numeric argument as a repeat count, it should be able
+to do something useful with a negative argument as well as a positive
+argument. At the very least, it should be aware that it can be passed a
+negative argument.
+
+@node Allowing Undoing, , Function Writing, Custom Functions
+@subsection Allowing Undoing
+
+Supporting the undo command is a painless thing to do, and makes your
+function much more useful to the end user. It is certainly easy to try
+something if you know you can undo it. I could use an undo function for
+the stock market.
+
+If your function simply inserts text once, or deletes text once, and it
+calls @code{rl_insert_text ()} or @code{rl_delete_text ()} to do it, then
+undoing is already done for you automatically, and you can safely skip
+this section.
+
+If you do multiple insertions or multiple deletions, or any combination
+of these operations, you will want to group them together into one
+operation. This can be done with @code{rl_begin_undo_group ()} and
+@code{rl_end_undo_group ()}.
+
+@defun rl_begin_undo_group ()
+Begins saving undo information in a group construct. The undo
+information usually comes from calls to @code{rl_insert_text ()} and
+@code{rl_delete_text ()}, but they could be direct calls to
+@code{rl_add_undo ()}.
+@end defun
+
+@defun rl_end_undo_group ()
+Closes the current undo group started with @code{rl_begin_undo_group
+()}. There should be exactly one call to @code{rl_end_undo_group ()}
+for every call to @code{rl_begin_undo_group ()}.
+@end defun
+
+Finally, if you neither insert nor delete text, but directly modify the
+existing text (e.g. change its case), you call @code{rl_modifying ()}
+once, just before you modify the text. You must supply the indices of
+the text range that you are going to modify.
+
+@defun rl_modifying (int start, int end)
+Tell Readline to save the text between @var{start} and @var{end} as a
+single undo unit. It is assumed that subsequent to this call you will
+modify that range of text in some way.
+@end defun
+
+@subsection An Example
+
+Let us say that we are actually going to put an example here.
+
+@node Custom Completers, Variable Index, Custom Functions, Readline Technical
+
+Typically, a program that reads commands from the user has a way of
+disambiguating between commands and data. If your program is one of
+these, then it can provide completion for either commands, or data, or
+both commands and data. The following sections describe how your
+program and Readline cooperate to provide this service to end users.
+
+@menu
+@end menu
+
+@node Variable Index, , Custom Completers, Readline Technical
+@appendix Variable Index
+@printindex vr
+@contents
+
+@bye
+