From bb7592f01006b09c846831a9fb9c306307ba34f6 Mon Sep 17 00:00:00 2001 From: "gdb-2.8.1" Date: Fri, 16 Dec 1988 00:00:00 +0000 Subject: [PATCH] gdb-2.8.1 --- gdb/Makefile | 10 +- gdb/ORIGIN | 16 - gdb/ORIGIN.ls.lag | 95 --- gdb/ORIGIN.ls.pmax | 95 --- gdb/TAGS | 948 +++++++++++---------- gdb/blockframe.c | 19 +- gdb/breakpoint.c | 181 ++-- gdb/c.h | 14 + gdb/coffread.c | 1427 ++++++++++++++++++++++++++++++- gdb/coffread.c.README | 12 - gdb/coffread.c.pmax | 1851 ----------------------------------------- gdb/command.c | 4 + gdb/config.gdb | 4 + gdb/config.status | 1 + gdb/core.c | 21 + gdb/dbxread.c | 775 ++++++++++++++++- gdb/defs.h | 5 +- gdb/eval.c | 496 ++++++++--- gdb/expread.tab.c | 1608 +++++++++++++++++++++++++++++++++++ gdb/expread.y | 223 ++++- gdb/expression.h | 25 + gdb/findvar.c | 8 + gdb/frame.h | 4 + gdb/gdb.ideas | 243 ------ gdb/infcmd.c | 17 +- gdb/inflow.c | 92 +- gdb/infrun.c | 182 +++- gdb/m-hp9k320.h | 6 +- gdb/m-hp9k320bsd.h | 6 +- gdb/m-init.h | 2 +- gdb/m-isi.h | 533 ------------ gdb/m-merlin.h | 6 +- gdb/m-news.h | 6 +- gdb/m-npl.h | 2 +- gdb/m-pn.h | 2 +- gdb/m-sun2.h | 6 +- gdb/m-sun3.h | 6 +- gdb/m-sun4.h | 493 +++++++++++ gdb/m-sun4init.h | 5 + gdb/m-suninit.h | 5 + gdb/m-umax.h | 6 +- gdb/m-vax.h | 6 +- gdb/main.c | 2 +- gdb/opcode.h | 1273 +--------------------------- gdb/param.h | 512 ++++++------ gdb/pinsn.c | 1354 +++++++++++++++--------------- gdb/printcmd.c | 63 +- gdb/source.c | 46 +- gdb/sparc-opcode.h | 1 + gdb/sparc-pinsn.c | 811 ++++++++++++++++++ gdb/stack.c | 6 +- gdb/symmisc.c | 4 + gdb/symseg.h | 84 ++ gdb/symtab.c | 548 +++++++++++- gdb/symtab.h | 74 +- gdb/test.c | 6 + gdb/test4.c | 40 + gdb/teststruct.c | 111 +++ gdb/valarith.c | 175 ++++ gdb/valops.c | 513 +++++++++++- gdb/valprint.c | 395 ++++++++- gdb/value.h | 22 +- gdb/values.c | 148 +++- gdb/version.c | 2 +- 64 files changed, 9818 insertions(+), 5838 deletions(-) delete mode 100644 gdb/ORIGIN delete mode 100644 gdb/ORIGIN.ls.lag delete mode 100644 gdb/ORIGIN.ls.pmax create mode 100644 gdb/c.h delete mode 100644 gdb/coffread.c.README delete mode 100644 gdb/coffread.c.pmax mode change 100644 => 100755 gdb/config.gdb create mode 100644 gdb/config.status create mode 100644 gdb/expread.tab.c delete mode 100644 gdb/m-isi.h create mode 100644 gdb/m-sun4.h create mode 100644 gdb/m-sun4init.h create mode 100644 gdb/m-suninit.h create mode 100644 gdb/sparc-opcode.h create mode 100644 gdb/sparc-pinsn.c create mode 100644 gdb/test.c create mode 100644 gdb/test4.c create mode 100644 gdb/teststruct.c diff --git a/gdb/Makefile b/gdb/Makefile index fefd8dadfd1..563de460996 100644 --- a/gdb/Makefile +++ b/gdb/Makefile @@ -52,11 +52,11 @@ TSSTART = /lib/crt0.o NTSSTART = kdb-start.o -gdb : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1) - $(CC) $(LDFLAGS) -o gdb $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(CLIBS) +gdb+ : $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(OBSTACK1) + $(CC) $(LDFLAGS) -o gdb+ $(STARTOBS) $(OBS) $(TSOBS) $(ENDOBS) $(CLIBS) -xgdb : $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) $(OBSTACK1) - $(CC) $(LDFLAGS) -o xgdb $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) \ +xgdb+ : $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) $(OBSTACK1) + $(CC) $(LDFLAGS) -o xgdb+ $(STARTOBS) $(OBS) $(TSOBS) xgdb.o $(ENDOBS) \ -lXaw -lXt -lX11 $(CLIBS) kdb : $(NTSSTART) $(STARTOBS) $(OBS) $(NTSOBS) $(ENDOBS) $(OBSTACK1) @@ -89,7 +89,7 @@ main.o : main.c defs.h command.h # pinsn.o depends on ALL the opcode printers # since we don't know which one is really being used. pinsn.o : pinsn.c defs.h param.h symtab.h \ - vax-opcode.h vax-pinsn.c m68k-opcode.h m68k-pinsn.c + vax-opcode.h vax-pinsn.c m68k-opcode.h m68k-pinsn.c sparc-opcode.h sparc-pinsn.c printcmd.o : printcmd.c defs.h initialize.h param.h symtab.h value.h expression.h remote.o : remote.c defs.h initialize.h param.h frame.h inferior.h source.o : source.c defs.h initialize.h symtab.h diff --git a/gdb/ORIGIN b/gdb/ORIGIN deleted file mode 100644 index f113819f4e0..00000000000 --- a/gdb/ORIGIN +++ /dev/null @@ -1,16 +0,0 @@ -Host akbar.cac.washington.edu (128.95.112.1) -Last updated 17:04 11 Nov 1990 - Location: local/emacs.pmax/info - FILE rw-rw-r-- 2515 Feb 12 1988 gdb - Location: local/emacs.pmax.old - DIRECTORY rwxr-xr-x 2048 Sep 11 01:16 gdb - Location: local/emacs.pmax.old/info - FILE rw-rw-r-- 2515 Feb 12 1988 gdb - Location: local/emacs.pmax4.0 - DIRECTORY rwxr-xr-x 2048 Aug 11 01:16 gdb - Location: local/emacs.pmax4.0/info - FILE rw-r--r-- 2515 Feb 12 1988 gdb - Location: local/emacs.sun386 - DIRECTORY rwxr-xr-x 2048 May 23 01:17 gdb - Location: local/emacs.sun386/info - FILE rw-rw-r-- 2515 Feb 12 1988 gdb diff --git a/gdb/ORIGIN.ls.lag b/gdb/ORIGIN.ls.lag deleted file mode 100644 index e46be368930..00000000000 --- a/gdb/ORIGIN.ls.lag +++ /dev/null @@ -1,95 +0,0 @@ -total 1304 -drwxr-xr-x 2 bin system 2048 May 23 1990 . -drwxr-xr-x 11 bin system 512 May 23 1990 .. --rw-rw-r-- 2 5057 staff 7517 Feb 11 1988 COPYING --rw-rw-r-- 2 5057 staff 58620 Sep 3 1988 ChangeLog --rw-rw-r-- 2 5057 staff 4698 Sep 3 1988 Makefile --rw-rw-r-- 2 5057 staff 1168 Jul 8 1988 README --rw-rw-r-- 2 5057 staff 30273 May 6 1988 TAGS --rw-rw-r-- 2 5057 staff 8285 Mar 24 1988 blockframe.c --rw-rw-r-- 2 5057 staff 28258 Jun 9 1988 breakpoint.c --rw-r--r-- 2 5057 staff 12288 Dec 20 1988 coffread.c --rw-rw-r-- 2 5057 staff 14515 Mar 25 1988 command.c --rw-rw-r-- 2 5057 staff 7397 Feb 11 1988 command.h --rwxrwxr-x 2 5057 staff 2273 Sep 1 1988 config.gdb --rw-rw-r-- 2 5057 staff 19678 May 3 1988 core.c --rw-rw-r-- 2 5057 staff 69156 Jul 6 1988 dbxread.c --rw-rw-r-- 2 5057 staff 2499 May 22 1988 defs.h --rw-rw-r-- 2 5057 staff 8436 Feb 11 1988 environ.c --rw-rw-r-- 2 5057 staff 615 Jul 15 1986 environ.h --rw-rw-r-- 2 5057 staff 16501 Feb 3 1988 eval.c --rw-rw-r-- 2 5057 staff 9484 May 30 1988 expprint.c --rw-rw-r-- 2 5057 staff 27745 Apr 30 1988 expread.y --rw-rw-r-- 2 5057 staff 6455 Nov 22 1986 expression.h --rw-rw-r-- 2 5057 staff 10805 Jun 27 1988 findvar.c --rw-rw-r-- 2 5057 staff 7052 Feb 11 1988 firstfile.c --rw-rw-r-- 2 5057 staff 2287 Sep 30 1986 frame.h --rw-rw-r-- 2 5057 staff 4006 Apr 13 1987 gdb.1 --rw-rw-r-- 2 5057 staff 41892 Sep 2 1988 gdb.ideas --rw-rw-r-- 2 5057 staff 6759 Jun 21 1988 gld-pinsn.c --rw-rw-r-- 2 5057 staff 23615 Jun 27 1988 infcmd.c --rw-rw-r-- 2 5057 staff 2820 Feb 3 1988 inferior.h --rw-rw-r-- 2 5057 staff 23111 Sep 3 1988 inflow.c --rw-rw-r-- 2 5057 staff 29393 Jun 25 1988 infrun.c --rw-rw-r-- 2 5057 staff 6545 Jun 21 1988 initialize.h --rw-rw-r-- 2 5057 staff 409 Jul 15 1986 kdb-start.c --rw-rw-r-- 2 5057 staff 172 Jul 15 1986 lastfile.c --rw-rw-r-- 2 5057 staff 20054 Apr 11 1988 m-hp9k320.h --rw-rw-r-- 2 5057 staff 19325 Sep 1 1988 m-hp9k320bsd.h --rw-rw-r-- 4 5057 staff 141 Feb 6 1988 m-init.h --rw-rw-r-- 2 5057 staff 20411 Apr 6 1988 m-isi.h --rw-rw-r-- 2 5057 staff 348 Mar 20 1988 m-isiinit.h --rw-rw-r-- 2 5057 staff 15011 Mar 24 1988 m-merlin.h --rw-rw-r-- 2 5057 staff 19335 Aug 30 1988 m-news.h --rw-rw-r-- 2 5057 staff 146 Jan 15 1988 m-newsinit.h --rw-rw-r-- 2 5057 staff 18267 Jun 17 1988 m-npl.h --rw-rw-r-- 2 5057 staff 189 Jun 16 1988 m-nplinit.h --rw-rw-r-- 2 5057 staff 17503 Jun 17 1988 m-pn.h --rw-rw-r-- 2 5057 staff 191 Jun 16 1988 m-pninit.h --rw-rw-r-- 2 5057 staff 15507 Apr 6 1988 m-sun2.h --rw-rw-r-- 2 5057 staff 130 Jul 15 1986 m-sun2init.h --rw-rw-r-- 4 5057 staff 18051 Apr 6 1988 m-sun3.h --rw-rw-r-- 4 5057 staff 141 Feb 6 1988 m-sun3init.h --rw-rw-r-- 2 5057 staff 14711 Jun 17 1988 m-umax.h --rw-rw-r-- 2 5057 staff 147 Apr 9 1988 m-umaxinit.h --rw-rw-r-- 2 5057 staff 13590 Mar 24 1988 m-vax.h --rw-rw-r-- 2 5057 staff 141 Sep 24 1986 m-vaxinit.h --rw-rw-r-- 4 5057 staff 68314 Apr 8 1988 m68k-opcode.h --rw-rw-r-- 4 5057 staff 17695 Jun 21 1988 m68k-pinsn.c --rw-rw-r-- 2 5057 staff 34227 Jul 20 1988 main.c --rw-rw-r-- 2 5057 staff 18362 Jun 16 1988 npl-opcode.h --rw-rw-r-- 2 5057 staff 10621 Nov 25 1987 ns32k-opcode.h --rw-rw-r-- 2 5057 staff 10662 Jun 21 1988 ns32k-pinsn.c --rw-rw-r-- 2 5057 staff 12230 Jun 17 1988 obstack.c --rw-rw-r-- 2 5057 staff 18478 Jul 24 1988 obstack.h --rw-rw-r-- 4 5057 staff 68314 Apr 8 1988 opcode.h --rw-rw-r-- 4 5057 staff 18051 Apr 6 1988 param.h --rw-rw-r-- 4 5057 staff 17695 Jun 21 1988 pinsn.c --rw-rw-r-- 2 5057 staff 12573 Jun 16 1988 pn-opcode.h --rw-rw-r-- 2 5057 staff 31150 Jul 22 1988 printcmd.c --rw-rw-r-- 2 5057 staff 13024 Apr 7 1988 remote.c --rw-rw-r-- 2 5057 staff 22485 May 23 1988 source.c --rw-rw-r-- 2 5057 staff 16743 May 23 1988 stack.c --rw-rw-r-- 2 5057 staff 12067 May 3 1988 standalone.c --rw-rw-r-- 2 5057 staff 5366 Sep 30 1986 stuff.c --rw-rw-r-- 2 5057 staff 15537 Jul 26 1988 symmisc.c --rw-rw-r-- 2 5057 staff 13976 Feb 17 1988 symseg.h --rw-rw-r-- 2 5057 staff 30879 Apr 8 1988 symtab.c --rw-rw-r-- 2 5057 staff 8030 Apr 8 1988 symtab.h --rw-rw-r-- 2 5057 staff 303 Jul 15 1986 test2.c --rw-rw-r-- 2 5057 staff 602 Apr 9 1988 testbpt.c --rw-rw-r-- 2 5057 staff 205 Jan 2 1988 testfun.c --rw-rw-r-- 2 5057 staff 79 Jul 15 1986 testrec.c --rw-rw-r-- 2 5057 staff 365 Jul 15 1986 testreg.c --rw-rw-r-- 2 5057 staff 387 Dec 3 1987 testregs.c --rw-rw-r-- 2 5057 staff 9872 May 30 1988 utils.c --rw-rw-r-- 2 5057 staff 8374 Dec 17 1987 valarith.c --rw-rw-r-- 2 5057 staff 16436 Jan 7 1988 valops.c --rw-rw-r-- 2 5057 staff 17003 Sep 3 1988 valprint.c --rw-rw-r-- 2 5057 staff 3799 Feb 6 1988 value.h --rw-rw-r-- 2 5057 staff 19062 May 20 1988 values.c --rw-rw-r-- 2 5057 staff 12750 Jul 15 1986 vax-opcode.h --rw-rw-r-- 2 5057 staff 5681 Jun 21 1988 vax-pinsn.c --rw-rw-r-- 2 5057 staff 73 Sep 8 1988 version.c --rw-rw-r-- 2 5057 staff 961 May 1 1988 wait.h --rw-rw-r-- 2 5057 staff 19446 Jul 20 1988 xgdb.c diff --git a/gdb/ORIGIN.ls.pmax b/gdb/ORIGIN.ls.pmax deleted file mode 100644 index b9a552f7b6b..00000000000 --- a/gdb/ORIGIN.ls.pmax +++ /dev/null @@ -1,95 +0,0 @@ -total 1338 -drwxr-xr-x 2 bin system 2048 Aug 11 01:16 . -drwxr-xr-x 11 bin system 512 Sep 5 01:14 .. --rw-r--r-- 2 5057 staff 7517 Feb 11 1988 COPYING --rw-r--r-- 2 5057 staff 58620 Sep 3 1988 ChangeLog --rw-r--r-- 2 5057 staff 4698 Sep 3 1988 Makefile --rw-r--r-- 2 5057 staff 1168 Jul 8 1988 README --rw-r--r-- 2 5057 staff 30273 May 6 1988 TAGS --rw-r--r-- 2 5057 staff 8285 Mar 24 1988 blockframe.c --rw-r--r-- 2 5057 staff 28258 Jun 9 1988 breakpoint.c --rw-r--r-- 2 5057 staff 46897 Jul 12 1988 coffread.c --rw-r--r-- 2 5057 staff 14515 Mar 25 1988 command.c --rw-r--r-- 2 5057 staff 7397 Feb 11 1988 command.h --rwxr-xr-x 2 5057 staff 2273 Sep 1 1988 config.gdb --rw-r--r-- 2 5057 staff 19678 May 3 1988 core.c --rw-r--r-- 2 5057 staff 69156 Jul 6 1988 dbxread.c --rw-r--r-- 2 5057 staff 2499 May 22 1988 defs.h --rw-r--r-- 2 5057 staff 8436 Feb 11 1988 environ.c --rw-r--r-- 2 5057 staff 615 Jul 15 1986 environ.h --rw-r--r-- 2 5057 staff 16501 Feb 3 1988 eval.c --rw-r--r-- 2 5057 staff 9484 May 30 1988 expprint.c --rw-r--r-- 2 5057 staff 27745 Apr 30 1988 expread.y --rw-r--r-- 2 5057 staff 6455 Nov 22 1986 expression.h --rw-r--r-- 2 5057 staff 10805 Jun 27 1988 findvar.c --rw-r--r-- 2 5057 staff 7052 Feb 11 1988 firstfile.c --rw-r--r-- 2 5057 staff 2287 Sep 30 1986 frame.h --rw-r--r-- 2 5057 staff 4006 Apr 13 1987 gdb.1 --rw-r--r-- 2 5057 staff 41892 Sep 2 1988 gdb.ideas --rw-r--r-- 2 5057 staff 6759 Jun 21 1988 gld-pinsn.c --rw-r--r-- 2 5057 staff 23615 Jun 27 1988 infcmd.c --rw-r--r-- 2 5057 staff 2820 Feb 3 1988 inferior.h --rw-r--r-- 2 5057 staff 23111 Sep 3 1988 inflow.c --rw-r--r-- 2 5057 staff 29393 Jun 25 1988 infrun.c --rw-r--r-- 2 5057 staff 6545 Jun 21 1988 initialize.h --rw-r--r-- 2 5057 staff 409 Jul 15 1986 kdb-start.c --rw-r--r-- 2 5057 staff 172 Jul 15 1986 lastfile.c --rw-r--r-- 2 5057 staff 20054 Apr 11 1988 m-hp9k320.h --rw-r--r-- 2 5057 staff 19325 Sep 1 1988 m-hp9k320bsd.h --rw-r--r-- 4 5057 staff 141 Feb 6 1988 m-init.h --rw-r--r-- 2 5057 staff 20411 Apr 6 1988 m-isi.h --rw-r--r-- 2 5057 staff 348 Mar 20 1988 m-isiinit.h --rw-r--r-- 2 5057 staff 15011 Mar 24 1988 m-merlin.h --rw-r--r-- 2 5057 staff 19335 Aug 30 1988 m-news.h --rw-r--r-- 2 5057 staff 146 Jan 15 1988 m-newsinit.h --rw-r--r-- 2 5057 staff 18267 Jun 17 1988 m-npl.h --rw-r--r-- 2 5057 staff 189 Jun 16 1988 m-nplinit.h --rw-r--r-- 2 5057 staff 17503 Jun 17 1988 m-pn.h --rw-r--r-- 2 5057 staff 191 Jun 16 1988 m-pninit.h --rw-r--r-- 2 5057 staff 15507 Apr 6 1988 m-sun2.h --rw-r--r-- 2 5057 staff 130 Jul 15 1986 m-sun2init.h --rw-r--r-- 4 5057 staff 18051 Apr 6 1988 m-sun3.h --rw-r--r-- 4 5057 staff 141 Feb 6 1988 m-sun3init.h --rw-r--r-- 2 5057 staff 14711 Jun 17 1988 m-umax.h --rw-r--r-- 2 5057 staff 147 Apr 9 1988 m-umaxinit.h --rw-r--r-- 2 5057 staff 13590 Mar 24 1988 m-vax.h --rw-r--r-- 2 5057 staff 141 Sep 24 1986 m-vaxinit.h --rw-r--r-- 4 5057 staff 68314 Apr 8 1988 m68k-opcode.h --rw-r--r-- 4 5057 staff 17695 Jun 21 1988 m68k-pinsn.c --rw-r--r-- 2 5057 staff 34227 Jul 20 1988 main.c --rw-r--r-- 2 5057 staff 18362 Jun 16 1988 npl-opcode.h --rw-r--r-- 2 5057 staff 10621 Nov 25 1987 ns32k-opcode.h --rw-r--r-- 2 5057 staff 10662 Jun 21 1988 ns32k-pinsn.c --rw-r--r-- 2 5057 staff 12230 Jun 17 1988 obstack.c --rw-r--r-- 2 5057 staff 18478 Jul 24 1988 obstack.h --rw-r--r-- 4 5057 staff 68314 Apr 8 1988 opcode.h --rw-r--r-- 4 5057 staff 18051 Apr 6 1988 param.h --rw-r--r-- 4 5057 staff 17695 Jun 21 1988 pinsn.c --rw-r--r-- 2 5057 staff 12573 Jun 16 1988 pn-opcode.h --rw-r--r-- 2 5057 staff 31150 Jul 22 1988 printcmd.c --rw-r--r-- 2 5057 staff 13024 Apr 7 1988 remote.c --rw-r--r-- 2 5057 staff 22485 May 23 1988 source.c --rw-r--r-- 2 5057 staff 16743 May 23 1988 stack.c --rw-r--r-- 2 5057 staff 12067 May 3 1988 standalone.c --rw-r--r-- 2 5057 staff 5366 Sep 30 1986 stuff.c --rw-r--r-- 2 5057 staff 15537 Jul 26 1988 symmisc.c --rw-r--r-- 2 5057 staff 13976 Feb 17 1988 symseg.h --rw-r--r-- 2 5057 staff 30879 Apr 8 1988 symtab.c --rw-r--r-- 2 5057 staff 8030 Apr 8 1988 symtab.h --rw-r--r-- 2 5057 staff 303 Jul 15 1986 test2.c --rw-r--r-- 2 5057 staff 602 Apr 9 1988 testbpt.c --rw-r--r-- 2 5057 staff 205 Jan 2 1988 testfun.c --rw-r--r-- 2 5057 staff 79 Jul 15 1986 testrec.c --rw-r--r-- 2 5057 staff 365 Jul 15 1986 testreg.c --rw-r--r-- 2 5057 staff 387 Dec 3 1987 testregs.c --rw-r--r-- 2 5057 staff 9872 May 30 1988 utils.c --rw-r--r-- 2 5057 staff 8374 Dec 17 1987 valarith.c --rw-r--r-- 2 5057 staff 16436 Jan 7 1988 valops.c --rw-r--r-- 2 5057 staff 17003 Sep 3 1988 valprint.c --rw-r--r-- 2 5057 staff 3799 Feb 6 1988 value.h --rw-r--r-- 2 5057 staff 19062 May 20 1988 values.c --rw-r--r-- 2 5057 staff 12750 Jul 15 1986 vax-opcode.h --rw-r--r-- 2 5057 staff 5681 Jun 21 1988 vax-pinsn.c --rw-r--r-- 2 5057 staff 73 Sep 8 1988 version.c --rw-r--r-- 2 5057 staff 961 May 1 1988 wait.h --rw-r--r-- 2 5057 staff 19446 Jul 20 1988 xgdb.c diff --git a/gdb/TAGS b/gdb/TAGS index 3c45dac02c0..1059758375c 100644 --- a/gdb/TAGS +++ b/gdb/TAGS @@ -1,20 +1,4 @@ -expread.y,349 -copy_name 952,21388 -end_arglist 516,11399 -free_funcalls 530,11701 -length_of_subexp 986,22292 -parse_c_1 1167,26460 -parse_c_expression 1208,27550 -parse_number 616,14066 -prefixify_expression 966,21724 -prefixify_subexp 1058,23629 -start_arglist 502,11040 -write_exp_elt 547,12040 -write_exp_string 564,12494 -yyerror 943,21233 -yylex 714,16109 - command.h,0 defs.h,42 @@ -151,6 +135,9 @@ m-news800.h,823 m-newsinit.h,29 #define FILEADDR_ROUND(4,99 +m-sparcinit.h,29 +#define FILEADDR_ROUND(5,94 + m-sun2.h,947 #define ABOUT_TO_RETURN(83,2582 #define EXTRACT_RETURN_VALUE(169,5390 @@ -209,6 +196,35 @@ m-sun3.h,913 #define SKIP_PROLOGUE(46,1570 #define STORE_RETURN_VALUE(191,6368 +m-sun4.h,985 +#define ABOUT_TO_RETURN(89,2910 +#define EXTRACT_RETURN_VALUE(198,6697 +#define EXTRACT_STRUCT_VALUE_ADDRESS(211,7282 +#define FIX_CALL_DUMMY(482,17052 +#define FRAME_ARGS_ADDRESS(271,9251 +#define FRAME_CHAIN(258,8815 +#define FRAME_CHAIN_COMBINE(264,9012 +#define FRAME_CHAIN_VALID(261,8890 +#define FRAME_FIND_SAVED_REGS(300,10368 +#define FRAME_LOCALS_ADDRESS(275,9344 +#define FRAME_NUM_ARGS(282,9599 +#define FRAME_SAVED_PC(268,9116 +#define FRAME_STRUCT_ARGS_ADDRESS(273,9294 +#define GET_RWINDOW_REG(238,8005 +#define INVALID_FLOAT(94,3065 +#define PC_ADJUST(59,2068 +#define REGISTER_BYTE(147,5292 +#define REGISTER_CONVERTIBLE(174,5926 +#define REGISTER_CONVERT_TO_RAW(185,6245 +#define REGISTER_CONVERT_TO_VIRTUAL(179,6062 +#define REGISTER_RAW_SIZE(154,5462 +#define REGISTER_VIRTUAL_SIZE(161,5626 +#define REGISTER_VIRTUAL_TYPE(191,6415 +#define SAVED_PC_AFTER_CALL(61,2160 +#define SKIP_PROLOGUE(47,1624 +#define STACK_ALIGN(73,2395 +#define STORE_RETURN_VALUE(204,6963 + m-suninit.h,29 #define FILEADDR_ROUND(5,94 @@ -316,55 +332,103 @@ obstack.h,1054 param.h,0 +sparc-opcode.h,0 + symseg.h,0 -symtab.h,1364 -#define BLOCKLIST(110,3965 -#define BLOCKLIST_BLOCK(121,4342 -#define BLOCKLIST_NBLOCKS(120,4284 -#define BLOCKVECTOR(111,4013 -#define BLOCKVECTOR_BLOCK(123,4461 -#define BLOCKVECTOR_NBLOCKS(122,4401 -#define BLOCK_END(129,4675 -#define BLOCK_FUNCTION(132,4785 -#define BLOCK_NSYMS(130,4711 -#define BLOCK_SHOULD_SORT(136,4945 -#define BLOCK_START(128,4635 -#define BLOCK_SUPERBLOCK(133,4827 -#define BLOCK_SYM(131,4747 -#define LINELIST(115,4113 -#define LINETABLE(116,4158 -#define SYMBOL_BLOCK_VALUE(143,5245 -#define SYMBOL_CLASS(140,5092 -#define SYMBOL_NAME(138,4996 -#define SYMBOL_NAMESPACE(139,5039 -#define SYMBOL_TYPE(144,5302 -#define SYMBOL_VALUE(141,5137 -#define SYMBOL_VALUE_BYTES(142,5188 -#define TYPEVECTOR(113,4064 -#define TYPEVECTOR_NTYPES(125,4523 -#define TYPEVECTOR_TYPE(126,4578 -#define TYPE_CODE(158,5917 -#define TYPE_FIELD(162,6063 -#define TYPE_FIELDS(160,6013 -#define TYPE_FIELD_BITPOS(166,6322 -#define TYPE_FIELD_BITSIZE(167,6390 -#define TYPE_FIELD_NAME(164,6181 -#define TYPE_FIELD_PACKED(168,6460 -#define TYPE_FIELD_TYPE(163,6117 -#define TYPE_FIELD_VALUE(165,6245 -#define TYPE_FLAGS(156,5797 -#define TYPE_FUNCTION_TYPE(154,5685 -#define TYPE_LENGTH(155,5748 -#define TYPE_NAME(151,5520 -#define TYPE_NFIELDS(159,5962 -#define TYPE_POINTER_TYPE(153,5624 -#define TYPE_TARGET_TYPE(152,5565 -#define TYPE_UNSIGNED(157,5844 - -value.h,428 -#define COERCE_ARRAY(61,2062 -#define COERCE_ENUM(71,2403 +symtab.h,3053 +#define BLOCKLIST(110,3968 +#define BLOCKLIST_BLOCK(121,4345 +#define BLOCKLIST_NBLOCKS(120,4287 +#define BLOCKVECTOR(111,4016 +#define BLOCKVECTOR_BLOCK(123,4464 +#define BLOCKVECTOR_NBLOCKS(122,4404 +#define BLOCK_END(129,4678 +#define BLOCK_FUNCTION(132,4788 +#define BLOCK_NSYMS(130,4714 +#define BLOCK_SHOULD_SORT(136,4948 +#define BLOCK_START(128,4638 +#define BLOCK_SUPERBLOCK(133,4830 +#define BLOCK_SYM(131,4750 +#define B_CLR(153,5603 +#define B_SET(152,5557 +#define B_TST(154,5650 +#define LINELIST(115,4116 +#define LINETABLE(116,4161 +#define SET_TYPE_CHAIN(181,7118 +#define SET_TYPE_FIELD_PRIVATE(193,7827 +#define SET_TYPE_FIELD_PROTECTED(194,7915 +#define SET_TYPE_FN_PRIVATE(220,9426 +#define SET_TYPE_FN_PROTECTED(221,9511 +#define SYMBOL_BLOCK_VALUE(143,5248 +#define SYMBOL_CLASS(140,5095 +#define SYMBOL_NAME(138,4999 +#define SYMBOL_NAMESPACE(139,5042 +#define SYMBOL_TYPE(144,5305 +#define SYMBOL_VALUE(141,5140 +#define SYMBOL_VALUE_BYTES(142,5191 +#define TYPEVECTOR(113,4067 +#define TYPEVECTOR_NTYPES(125,4526 +#define TYPEVECTOR_TYPE(126,4581 +#define TYPE_BASECLASS(176,6799 +#define TYPE_BASECLASSES(175,6740 +#define TYPE_CHAIN(180,7048 +#define TYPE_CODE(165,6219 +#define TYPE_DOMAIN_TYPE(170,6437 +#define TYPE_FIELD(183,7210 +#define TYPE_FIELDS(167,6315 +#define TYPE_FIELD_BITPOS(187,7469 +#define TYPE_FIELD_BITSIZE(188,7537 +#define TYPE_FIELD_NAME(185,7328 +#define TYPE_FIELD_PACKED(189,7607 +#define TYPE_FIELD_PRIVATE(195,8007 +#define TYPE_FIELD_PRIVATE_BITS(191,7677 +#define TYPE_FIELD_PROTECTED(196,8090 +#define TYPE_FIELD_PROTECTED_BITS(192,7750 +#define TYPE_FIELD_STATIC(201,8315 +#define TYPE_FIELD_STATIC_PHYSNAME(202,8391 +#define TYPE_FIELD_TYPE(184,7264 +#define TYPE_FIELD_VALUE(186,7392 +#define TYPE_FLAGS(163,6099 +#define TYPE_FN_FIELD(210,8851 +#define TYPE_FN_FIELDLIST(205,8543 +#define TYPE_FN_FIELDLIST1(206,8611 +#define TYPE_FN_FIELDLISTS(204,8480 +#define TYPE_FN_FIELDLIST_LENGTH(208,8768 +#define TYPE_FN_FIELDLIST_NAME(207,8690 +#define TYPE_FN_FIELDS(172,6559 +#define TYPE_FN_FIELD_ARGS(213,9015 +#define TYPE_FN_FIELD_NAME(211,8897 +#define TYPE_FN_FIELD_PHYSNAME(214,9074 +#define TYPE_FN_FIELD_TYPE(212,8956 +#define TYPE_FN_FIELD_VIRTUAL_P(215,9141 +#define TYPE_FN_FIELD_VOFFSET(216,9208 +#define TYPE_FN_PRIVATE(222,9600 +#define TYPE_FN_PRIVATE_BITS(218,9278 +#define TYPE_FN_PROTECTED(223,9681 +#define TYPE_FN_PROTECTED_BITS(219,9350 +#define TYPE_FUNCTION_TYPE(160,5926 +#define TYPE_HAS_CONSTRUCTOR(199,8245 +#define TYPE_HAS_DESTRUCTOR(198,8178 +#define TYPE_LENGTH(162,6050 +#define TYPE_MAIN_VARIANT(161,5989 +#define TYPE_NAME(156,5696 +#define TYPE_NFIELDS(166,6264 +#define TYPE_NFN_FIELDS(173,6614 +#define TYPE_NFN_FIELDS_TOTAL(174,6671 +#define TYPE_N_BASECLASSES(177,6869 +#define TYPE_POINTER_TYPE(158,5800 +#define TYPE_REFERENCE_TYPE(159,5861 +#define TYPE_TARGET_TYPE(157,5741 +#define TYPE_UNSIGNED(164,6146 +#define TYPE_VIA_PUBLIC(178,6932 +#define TYPE_VIA_VIRTUAL(179,6989 +#define TYPE_VPTR_BASETYPE(169,6374 +#define TYPE_VPTR_FIELDNO(171,6498 + +value.h,465 +#define COERCE_ARRAY(63,2095 +#define COERCE_ENUM(75,2527 #define VALUE_ADDRESS(48,1560 #define VALUE_BITPOS(52,1752 #define VALUE_BITSIZE(51,1710 @@ -377,6 +441,7 @@ value.h,428 #define VALUE_REPEATED(54,1828 #define VALUE_REPETITIONS(55,1872 #define VALUE_TYPE(45,1433 +typedef struct value *value;43,1403 vax-opcode.h,0 @@ -398,66 +463,66 @@ wait.h,381 #define WTERMSIG(23,771 blockframe.c,436 -block_for_pc 221,5343 -block_innermost_frame 328,7854 -find_pc_function 276,6479 -find_pc_misc_function 290,6812 -get_current_block 182,4491 +block_for_pc 226,5551 +block_innermost_frame 333,8062 +find_pc_function 281,6687 +find_pc_misc_function 295,7020 +get_current_block 187,4699 get_current_frame 47,1559 -get_frame_block 172,4342 -get_frame_function 208,5059 +get_frame_block 177,4550 +get_frame_function 213,5267 get_frame_info 90,2667 -get_frame_pc 150,3806 -get_frame_saved_regs 161,3992 -get_pc_function_start 188,4563 +get_frame_pc 155,4014 +get_frame_saved_regs 166,4200 +get_pc_function_start 193,4771 get_prev_frame 66,1899 -get_prev_frame_info 128,3461 -initialize 349,8257 +get_prev_frame_info 132,3578 +initialize 354,8465 set_current_frame 56,1711 -breakpoint.c,1268 +breakpoint.c,1272 #define ALL_BREAKPOINTS(71,2545 -break_command 685,16863 -break_command_1 628,15527 +break_command 716,17619 +break_command_1 630,15552 breakpoint_1 394,10213 -breakpoint_auto_delete 768,18842 +breakpoint_auto_delete 809,19886 breakpoint_cond_eval 326,8672 breakpoint_here_p 310,8342 breakpoint_stop_status 340,9123 breakpoints_info 443,11295 check_duplicates 508,12789 clear_breakpoint_commands 223,6282 -clear_breakpoints 838,20224 -clear_command 701,17105 +clear_breakpoints 879,21268 +clear_command 732,17867 clear_momentary_breakpoints 578,14320 commands_command 156,4505 condition_command 109,3533 -delete_breakpoint 785,19147 -delete_command 814,19667 +delete_breakpoint 826,20191 +delete_command 855,20711 describe_other_breakpoints 462,11663 -disable_breakpoint 957,22641 -disable_command 966,22774 +disable_breakpoint 999,23686 +disable_command 1008,23819 do_breakpoint_commands 205,5722 -enable_breakpoint 941,22402 -enable_command 950,22533 -enable_delete_breakpoint 994,23259 -enable_delete_command 1003,23396 -enable_once_breakpoint 978,23003 -enable_once_command 987,23141 +enable_breakpoint 983,23447 +enable_command 992,23578 +enable_delete_breakpoint 1036,24304 +enable_delete_command 1045,24441 +enable_once_breakpoint 1020,24048 +enable_once_command 1029,24186 get_breakpoint_commands 234,6567 -ignore_command 878,21116 -initialize 1017,23649 +ignore_command 919,22160 +initialize 1059,24694 insert_breakpoints 252,6958 -map_breakpoint_numbers 906,21721 +map_breakpoint_numbers 948,22766 mark_breakpoints_out 297,8031 remove_breakpoints 273,7497 set_breakpoint 594,14672 set_breakpoint_commands 240,6634 set_default_breakpoint 491,12319 -set_ignore_count 848,20449 +set_ignore_count 889,21493 set_momentary_breakpoint 566,14096 set_raw_breakpoint 529,13309 -tbreak_command 693,16983 +tbreak_command 724,17742 coffread.c,1050 add_symbol_to_list 225,6438 @@ -501,81 +566,86 @@ start_symtab 391,11203 symbol_file_command 634,17279 command.c,151 -add_alias_cmd 149,6542 -add_cmd 124,5994 -add_prefix_cmd 185,7605 -delete_cmd 206,8146 -help_cmd 238,8980 -lookup_cmd 344,12116 -savestring 454,14356 +add_alias_cmd 153,6583 +add_cmd 128,6035 +add_prefix_cmd 189,7646 +delete_cmd 210,8187 +help_cmd 242,9021 +lookup_cmd 348,12157 +savestring 458,14397 core.c,438 #define N_DATADDR(61,1786 #define N_TXTADDR(57,1716 -close_exec_file 457,12255 +close_exec_file 478,13099 core_file_command 152,3832 -exec_file_command 337,9034 -files_info 517,13575 -get_exec_file 501,13324 -have_core_file_p 511,13514 -initialize 736,18877 -myread 692,18121 -read_memory 560,14568 -register_addr 719,18606 -reopen_exec_file 464,12339 -specify_exec_file_hook 447,12026 -validate_files 480,12745 -write_memory 576,14975 -xfer_core_file 587,15240 - -dbxread.c,1312 -#define READ_FILE_HEADERS(85,2865 -#define READ_STRING_TABLE_SIZE(72,2434 -add_new_header_file 442,13085 -add_old_header_file 413,12067 -add_symbol_to_list 592,17369 -add_this_object_header_file 393,11440 -compare_misc_functions 1095,30835 -compare_symbols 1164,32278 -condense_misc_bunches 1121,31339 -dbx_alloc_type 550,16297 -dbx_lookup_type 500,14858 -define_symbol 1796,49277 -discard_misc_bunches 1108,31147 -end_symtab 919,26460 -explicit_lookup_type 571,16837 -fill_symbuf 1408,38674 -finish_block 657,18912 -free_header_files 369,10858 -get_sym_file 1384,38016 -hash_symsegs 1604,43801 -hashname 1577,43278 -init_header_files 356,10507 -init_misc_functions 1067,30229 -initialize 2474,68397 -make_blockvector 744,21323 -new_object_header_files 382,11168 -next_symbol_text 1424,39150 -obconcat 282,7896 -obsavestring 260,7389 -pop_subfile 1025,29388 -process_one_symbol 1635,44619 -push_subfile 1011,29037 -read_dbx_symtab 1439,39629 -read_enum_type 2264,62603 -read_number 2437,67832 -read_range_type 2345,64877 -read_struct_type 2177,60020 -read_type 2028,56226 -read_type_number 2001,55571 -really_free_pendings 621,18127 -record_line 783,22506 -record_misc_function 1075,30343 -sort_syms 1183,32828 -start_subfile 862,24702 -start_symtab 818,23480 -symbol_file_command 1208,33406 -xxmalloc 247,7121 +exec_file_command 358,9878 +files_info 538,14419 +get_exec_file 522,14168 +have_core_file_p 532,14358 +initialize 757,19721 +myread 713,18965 +read_memory 581,15412 +register_addr 740,19450 +reopen_exec_file 485,13183 +specify_exec_file_hook 468,12870 +validate_files 501,13589 +write_memory 597,15819 +xfer_core_file 608,16084 + +dbxread.c,1462 +#define READ_FILE_HEADERS(89,2958 +#define READ_STRING_TABLE_SIZE(76,2527 +add_file_command 1992,54601 +add_new_header_file 446,13178 +add_old_header_file 417,12160 +add_symbol_to_list 597,17499 +add_this_object_header_file 397,11533 +compare_misc_functions 1100,30965 +compare_symbols 1169,32408 +condense_addl_misc_bunches 1949,53491 +condense_misc_bunches 1126,31469 +dbx_alloc_type 554,16390 +dbx_lookup_type 504,14951 +define_symbol 2110,57727 +discard_misc_bunches 1113,31277 +end_symtab 924,26590 +explicit_lookup_type 576,16967 +fill_in_vptr_fieldno 3202,88273 +fill_symbuf 1413,38804 +finish_block 662,19042 +free_header_files 373,10951 +get_sym_file 1389,38146 +hash_symsegs 1610,43975 +hashname 1583,43452 +init_header_files 360,10600 +init_misc_functions 1072,30359 +initialize 3211,88488 +make_blockvector 749,21453 +new_object_header_files 386,11261 +next_symbol_text 1429,39280 +obconcat 286,7989 +obsavestring 264,7482 +pop_subfile 1030,29518 +process_one_symbol 1641,44793 +push_subfile 1016,29167 +read_addl_syms 1807,49601 +read_args 3166,87336 +read_dbx_symtab 1444,39759 +read_enum_type 2954,81399 +read_number 3127,86628 +read_range_type 3035,83673 +read_struct_type 2537,70010 +read_type 2363,65510 +read_type_number 2336,64855 +really_free_pendings 626,18257 +record_line 788,22636 +record_misc_function 1080,30473 +sort_syms 1188,32958 +start_subfile 867,24832 +start_symtab 823,23610 +symbol_file_command 1213,33536 +xxmalloc 251,7214 environ.c,215 environ_vector 172,6802 @@ -590,12 +660,12 @@ unset_in_environ 240,8026 eval.c,343 evaluate_expression 113,3186 -evaluate_subexp 132,3574 -evaluate_subexp_for_address 461,13617 -evaluate_subexp_for_sizeof 530,15374 -evaluate_subexp_with_coercion 498,14564 -evaluate_type 124,3431 -initialize 571,16473 +evaluate_subexp 132,3580 +evaluate_subexp_for_address 753,21631 +evaluate_subexp_for_sizeof 822,23400 +evaluate_subexp_with_coercion 790,22587 +evaluate_type 124,3434 +initialize 863,24505 parse_and_eval 64,1980 parse_and_eval_address 33,1188 parse_and_eval_address_1 50,1650 @@ -605,32 +675,34 @@ expprint.c,49 print_expression 88,3265 print_subexp 102,3660 -expread.tab.c,359 -copy_name 561,12554 -end_arglist 125,2565 -free_funcalls 139,2867 -length_of_subexp 595,13458 -parse_c_1 776,17626 -parse_c_expression 817,18716 -parse_number 225,5232 -prefixify_expression 575,12890 -prefixify_subexp 667,14795 -start_arglist 111,2206 -write_exp_elt 156,3206 -write_exp_string 173,3660 -yyerror 552,12399 -yylex 323,7275 -yyparse(1012,26510 +expread.tab.c,405 + } YYSTYPE;68,1351 +copy_name 600,13369 +end_arglist 130,2654 +free_funcalls 144,2956 +length_of_subexp 634,14273 +parse_c_1 841,18977 +parse_c_expression 882,20067 +parse_number 254,5961 +prefixify_expression 614,13705 +prefixify_subexp 720,15905 +start_arglist 116,2295 +write_exp_elt 163,3413 +write_exp_elt2 182,3891 +write_exp_string 202,4389 +yyerror 591,13214 +yylex 352,8004 +yyparse(1076,27837 findvar.c,309 find_saved_register 38,1432 -initialize 410,10938 -locate_var_value 343,9217 +initialize 418,11075 +locate_var_value 350,9332 read_register 165,4621 read_register_bytes 140,4050 read_relative_register_raw_bytes 68,2095 -read_var_value 202,5600 -supply_register 190,5277 +read_var_value 208,5693 +supply_register 196,5370 value_of_register 102,2842 write_register 175,4862 write_register_bytes 151,4328 @@ -641,77 +713,84 @@ initialize_dummy_1 148,6803 initialize_dummy_2 156,6962 infcmd.c,625 -attach_command 732,17281 +attach_command 743,17529 cont_command 193,4509 -detach_command 793,18554 -environment_info 512,12068 -finish_command 433,10153 +detach_command 804,18802 +environment_info 520,12243 +finish_command 441,10308 have_inferior_p 111,3062 -initialize 819,19055 +initialize 830,19303 jump_command 297,6565 next_command 230,5225 nexti_command 244,5427 -program_info 490,11463 -read_memory_integer 575,13485 -read_pc 608,14081 -registers_info 622,14276 +program_info 498,11638 +read_memory_integer 583,13660 +read_pc 616,14256 +registers_info 633,14521 run_command 136,3461 -run_stack_dummy 384,8700 +run_stack_dummy 392,8855 set_args_command 117,3127 -set_environment_command 532,12470 -signal_command 342,7530 +set_environment_command 540,12645 +signal_command 350,7685 step_1 250,5504 step_command 222,5073 stepi_command 238,5350 tty_command 126,3268 -unset_environment_command 564,13246 -write_pc 613,14145 +unset_environment_command 572,13421 +write_pc 621,14320 inflow.c,863 -#define FP_REGISTER_ADDR_DIFF(525,12732 -#define INFERIOR_AR0(528,12842 -attach 439,10259 +#define FP_REGISTER_ADDR_DIFF(597,15092 +#define INFERIOR_AR0(600,15202 +attach 447,10389 create_inferior 337,8134 -detach 455,10564 -fetch_inferior_register 534,12998 -fetch_inferior_registers 469,10787 -fetch_inferior_registers 619,14955 -fetch_inferior_registers 665,16181 +detach 463,10694 +fetch_inferior_register 606,15358 +fetch_inferior_registers 477,10917 +fetch_inferior_registers 691,17315 +fetch_inferior_registers 737,18541 inferior_died 405,9600 -initialize 859,21278 +initialize 931,23638 kill_command 383,9216 kill_inferior 394,9439 new_tty 301,7373 -read_inferior_memory 746,18325 +read_inferior_memory 818,20685 resume 420,9929 -store_inferior_register 587,14202 -store_inferior_register_1 565,13702 -store_inferior_registers 497,11824 -store_inferior_registers 636,15505 -store_inferior_registers 696,16999 +store_inferior_register 659,16562 +store_inferior_register_1 637,16062 +store_inferior_registers 525,12906 +store_inferior_registers 708,17865 +store_inferior_registers 768,19359 term_status_command 261,6253 terminal_inferior 140,3396 terminal_init_inferior 115,2925 terminal_ours 189,4596 terminal_ours_1 198,4690 terminal_ours_for_output 176,4359 -try_writing_regs_command 833,20768 -write_inferior_memory 779,19356 - -infrun.c,334 -attach_program 301,8446 -clear_proceed_status 130,3881 -handle_command 840,24097 -initialize 960,27506 -insert_step_breakpoint 818,23520 -normal_stop 726,20808 -proceed 158,4731 -remove_step_breakpoint 830,23822 -signals_info 922,26545 -start_inferior 243,6991 -start_remote 283,8086 -wait_for_inferior 324,9063 -writing_pc 231,6675 +try_writing_regs_command 905,23128 +write_inferior_memory 851,21716 + +infrun.c,504 +attach_program 314,8812 +typedef char binsn_quantum[1060,30158 +} branch_type;1056,30076 +clear_proceed_status 138,4165 +do_restore_insn 1152,32540 +do_save_insn 1123,31691 +handle_command 866,24714 +initialize 986,28123 +insert_step_breakpoint 844,24137 + int 1065,30266 +normal_stop 752,21425 +proceed 166,5015 +remove_step_breakpoint 856,24439 +signals_info 948,27162 +1064,30245 +start_inferior 256,7357 +start_remote 296,8452 +static 1061,30205 +wait_for_inferior 337,9429 +writing_pc 244,7041 kdb-start.c,14 start 10,140 @@ -807,35 +886,35 @@ void 296,10326 pinsn.c,0 -printcmd.c,734 +printcmd.c,735 address_info 454,10758 -clear_displays 736,17066 +clear_displays 740,17163 decode_format 79,2326 -delete_current_display 870,19696 -delete_display 751,17277 -display_command 677,16025 -display_info 882,19974 -do_displays 858,19446 +delete_current_display 877,19858 +delete_display 755,17374 +display_command 681,16122 +display_info 889,20136 +do_displays 865,19608 do_examine 299,7212 -do_one_display 817,18479 -free_display 724,16848 -initialize 1169,26896 +do_one_display 824,18641 +free_display 728,16945 +initialize 1219,28520 output_command 415,9952 print_address 276,6680 print_command 375,9121 print_formatted 124,3359 -print_frame_args 923,21059 -print_frame_nameless_args 986,22819 +print_frame_args 930,21221 +print_frame_nameless_args 1036,24443 print_scalar_formatted 167,4519 -print_variable_value 908,20615 -printf_command 1004,23196 -ptype_command 596,14000 +print_variable_value 915,20777 +printf_command 1054,24820 +ptype_command 600,14097 set_command 443,10508 set_next_address 261,6316 -undisplay_command 781,17829 +undisplay_command 788,17991 validate_format 360,8682 -whatis_command 571,13527 -x_command 523,12221 +whatis_command 575,13624 +x_command 527,12318 remote.c,549 dcache_alloc 548,11397 @@ -862,45 +941,58 @@ remote_wait 184,4062 remote_write_bytes 288,6178 tohex 156,3656 -source.c,445 -directories_info 91,2575 -directory_command 115,3092 -find_source_lines 283,7000 -forward_search_command 647,16430 -get_filename_and_charpos 362,8935 -identify_source_line 394,9804 -init_source_path 97,2666 -initialize 794,19866 -line_info 600,15220 -list_command 473,11569 -openp 219,5527 -print_source_lines 413,10296 -reverse_search_command 717,18054 +source.c,446 +directories_info 94,2657 +directory_command 118,3174 +find_source_lines 286,7082 +forward_search_command 676,17065 +get_filename_and_charpos 365,9017 +identify_source_line 397,9886 +init_source_path 100,2748 +initialize 823,20501 +line_info 621,15649 +list_command 476,11651 +openp 222,5609 +print_source_lines 416,10378 +reverse_search_command 746,18689 select_source_symtab 57,1795 -source_charpos_line 336,8295 -source_line_charpos 322,7999 +source_charpos_line 339,8377 +source_line_charpos 325,8081 + +sparc-pinsn.c,267 +} branch_type;129,2729 +fprint_addr1 414,9505 +fprint_c_ldst 514,11525 +fprint_f_ldst 487,11019 +fprint_fpop 539,12023 +fprint_ldst 460,10530 +fprint_mem 435,9924 +frame_saved_pc 773,16590 +isabranch 710,15193 +print_insn 176,4188 +CORE_ADDR skip_prologue 742,15962 stack.c,534 -args_info 363,9216 -backtrace_command 244,6624 -down_command 522,13553 -find_relative_frame 415,10615 -frame_command 468,12228 +args_info 363,9268 +backtrace_command 244,6639 +down_command 522,13605 +find_relative_frame 415,10667 +frame_command 468,12280 frame_info 161,4481 -get_selected_block 395,9911 -initialize 582,14958 -locals_info 325,8515 -print_block_frame_locals 269,7164 -print_frame_arg_vars 331,8597 +get_selected_block 395,9963 +initialize 582,15010 +locals_info 325,8530 +print_block_frame_locals 269,7179 +print_frame_arg_vars 331,8612 print_frame_info 75,2329 -print_frame_local_vars 304,7997 +print_frame_local_vars 304,8012 print_sel_frame 143,4033 print_selected_frame 152,4238 print_stack_frame 62,2126 -record_selected_frame 383,9619 -return_command 540,14053 -select_frame 372,9416 -up_command 501,12961 +record_selected_frame 383,9671 +return_command 540,14105 +select_frame 372,9468 +up_command 501,13013 standalone.c,1165 _exit 437,8550 @@ -972,12 +1064,12 @@ symmisc.c,532 #define RELOCATE(146,4235 #define TEXT_RELOCATE(160,4829 #define UNRELOCATE(150,4430 -block_depth 546,15195 +block_depth 552,15350 free_all_symtabs 38,1310 free_symtab 92,2701 free_symtab_block 70,1994 -initialize 555,15336 -print_symbol 449,12827 +initialize 561,15491 +print_symbol 451,12880 print_symtabs 383,11097 read_symsegs 347,10121 relocate_block 227,6794 @@ -989,78 +1081,47 @@ relocate_symtab 181,5623 relocate_type 293,8716 relocate_typevector 273,8107 -symtab.c,830 -block_function 411,11587 -compare_symbols 1095,28490 -decode_line_1 746,20110 -decode_line_spec 909,24191 -find_line_common 656,17799 -find_line_pc 591,16045 -find_line_pc_range 613,16574 -find_pc_line 453,12634 -find_pc_line_pc_range 707,18691 -find_pc_symtab 423,11820 -functions_info 1079,28240 -init_type 1118,29098 -initialize 1138,29548 -list_symbols 988,25907 -lookup_block_symbol 330,9558 +symtab.c,1103 +block_function 650,18342 +compare_symbols 1583,42494 +decode_line_1 985,26867 +decode_line_2 1296,35899 +decode_line_spec 1281,35508 +find_line_common 895,24554 +find_line_pc 830,22800 +find_line_pc_range 852,23329 +find_pc_line 692,19389 +find_pc_line_pc_range 946,25446 +find_pc_symtab 662,18575 +functions_info 1560,42158 +init_type 1606,43102 +initialize 1631,43703 +list_symbols 1455,39402 +lookup_basetype_type 292,8824 +lookup_block_symbol 569,16313 lookup_enum 166,4764 -lookup_function_type 211,6266 -lookup_misc_func 926,24619 -lookup_pointer_type 182,5275 +lookup_function_type 351,10506 +lookup_member_type 244,7428 +lookup_misc_func 1393,38114 +lookup_pointer_type 185,5371 +lookup_reference_type 212,6279 lookup_struct 134,3830 -lookup_symbol 285,8464 +lookup_symbol 524,15219 +lookup_symbol_1 468,13881 +lookup_symbol_2 490,14356 lookup_symtab 58,1935 lookup_typename 85,2565 lookup_union 150,4299 lookup_unsigned_typename 116,3352 -smash_to_function_type 262,7822 -smash_to_pointer_type 241,7212 -sort_block_syms 1107,28881 -sources_info 938,24850 -types_info 1086,28328 -variables_info 1072,28152 - -test2.c,11 -main 6,86 - -test3.c,25 -bar 12,123 -newfun 5,51 - -testbit.c,11 -main 7,58 - -testbpt.c,48 -after_dump 31,584 -int dump 15,351 -main 8,233 - -testfun.c,55 -do_add 12,86 -do_float_add 18,128 -foo 7,51 -main 1,0 - -testkill.c,11 - main(2,1 - -testrec.c,20 -foo 6,24 -main 1,0 - -testreg.c,22 -foo 19,341 -main 1,0 - -testregs.c,23 -foo 4,47 -main 17,357 - -testxx.c,20 -a(10,77 -main(3,20 +methods_info 1574,42330 +smash_to_function_type 445,13239 +smash_to_member_type 403,12047 +smash_to_pointer_type 382,11491 +smash_to_reference_type 422,12587 +sort_block_syms 1595,42885 +sources_info 1405,38345 +types_info 1567,42246 +variables_info 1553,42070 utils.c,382 concat 267,6227 @@ -1082,78 +1143,91 @@ savestring 256,6060 xmalloc 120,3191 xrealloc 132,3411 -valarith.c,215 -initialize 361,8346 -value_add 31,1128 -value_binop 116,3276 -value_equal 260,5580 -value_less 304,6791 -value_lognot 349,8075 -value_neg 331,7664 -value_sub 70,2102 -value_subscript 105,2971 -value_zerop 236,5229 - -valops.c,396 -call_function 394,10974 -initialize 597,16408 -push_bytes 316,9287 -push_word 296,8921 +valarith.c,333 +binop_user_defined_p 120,3330 +initialize 536,13968 +int unop_user_defined_p 140,4066 +value_add 33,1153 +value_binop 283,8790 +value_equal 435,11202 +value_less 479,12413 +value_lognot 524,13697 +value_neg 506,13286 +value_sub 72,2127 +value_subscript 107,2996 +value_x_binop 157,4648 +value_x_unop 237,7399 +value_zerop 411,10851 + +valops.c,538 +call_function 406,11494 +check_field 799,21547 +destructor_name_p 772,20847 +initialize 1036,27337 +push_bytes 328,9807 +push_word 308,9441 +int typecmp(968,25919 value_addr 249,7552 -value_arg_coerce 356,10080 -value_arg_push 379,10527 +value_arg_coerce 368,10600 +value_arg_push 391,11047 value_assign 88,2873 value_at 71,2465 value_cast 34,1302 value_coerce_array 221,6762 value_ind 276,8307 +value_of_this 997,26533 value_of_variable 211,6556 -value_push 335,9628 +value_push 347,10148 value_repeat 188,5971 -value_string 488,13694 -value_struct_elt 558,15616 - -valprint.c,256 -initialize 634,15818 -is_nan 312,7921 -set_maximum_command 626,15672 -type_print 341,8823 -type_print_1 352,9049 -type_print_base 474,12317 -type_print_varspec_prefix 385,10075 -type_print_varspec_suffix 420,10858 -val_print 115,3427 -value_print 47,1622 - -values.c,762 +value_string 534,14856 +value_struct_elt 609,16972 +value_struct_elt_for_address 872,23241 + +valprint.c,293 +initialize 922,23635 +is_nan 475,12348 +set_maximum_command 914,23489 +type_print 504,13250 +type_print_1 515,13476 +type_print_base 691,18041 +type_print_method_args 543,14320 +type_print_varspec_prefix 581,15207 +type_print_varspec_suffix 630,16398 +val_print 125,3755 +value_print 48,1661 + +values.c,852 access_value_history 212,5551 allocate_repeat_value 83,2505 allocate_value 59,1948 -clear_internalvars 371,9242 +clear_internalvars 372,9256 clear_value_history 251,6511 -convenience_info 386,9478 +convenience_info 387,9492 free_all_values 108,3143 history_info 270,6920 -initialize 741,18461 -internalvar_name 361,9051 +initialize 884,23003 +internalvar_name 362,9065 lookup_internalvar 308,7855 -modify_field 608,14951 +modify_field 751,19493 record_latest_value 178,4634 release_value 125,3410 -set_internalvar 351,8882 -set_internalvar_component 336,8488 -set_return_value 715,17910 -unpack_double 486,11857 -unpack_field_as_long 584,14377 -unpack_long 430,10621 -value_as_double 418,10258 -value_as_long 411,10138 -value_being_returned 694,17332 +set_internalvar 352,8896 +set_internalvar_component 337,8502 +set_return_value 858,22452 +unpack_double 495,12241 +unpack_field_as_long 727,18919 +unpack_long 436,10879 +value_as_double 419,10272 +value_as_long 412,10152 +value_being_returned 837,21874 value_copy 151,3834 -value_field 548,13336 -value_from_double 660,16290 -value_from_long 632,15530 +value_field 559,13788 +value_fn_field 595,14830 +value_from_double 803,20832 +value_from_long 775,20072 value_of_internalvar 327,8301 +value_static_field 665,17504 +value_virtual_fn_field 623,15815 vax-pinsn.c,44 print_insn 42,1456 @@ -1161,31 +1235,31 @@ print_insn_arg 86,2396 version.c,0 -xgdb.c,690 -addbutton 447,11022 -breakpoint_button 308,8599 -breakpoint_button_1 285,8127 -cont_button 385,10023 -create_buttons 461,11342 -create_label 486,12096 -create_text_widget 501,12496 -deiconify_button 402,10249 -down_button 430,10785 -explicit_breakpoint_button 334,9027 -finish_button 393,10131 -garbage 321,8760 -iconify_button 409,10382 -initialize 688,17526 -next_button 369,9807 -print_1 242,7251 -print_button 269,7835 -print_star_button 275,7884 -refresh_button 438,10893 -step_button 377,9915 -until_button 314,8664 -up_button 422,10681 -xgdb_create_window 523,13113 -xgdb_dispatch 646,16620 -xgdb_display_exec_file 224,6748 -xgdb_display_source 102,2745 -xgdb_window_hook 678,17364 +xgdb.c,679 +addbutton 420,9859 +breakpoint_button 288,7520 +breakpoint_button_1 265,7032 +cont_button 365,8944 +create_buttons 436,10258 +create_label 460,10963 +create_text_widget 475,11357 +deiconify_button 382,9170 +down_button 410,9706 +explicit_breakpoint_button 314,7948 +finish_button 373,9052 +garbage 301,7681 +iconify_button 389,9303 +initialize 660,16261 +next_button 349,8728 +print_1 222,6172 +print_button 249,6740 +print_prompt 209,5879 +print_star_button 255,6789 +step_button 357,8836 +until_button 294,7585 +up_button 402,9602 +xgdb_create_window 489,11713 +xgdb_dispatch 618,15369 +xgdb_display_exec_file 195,5595 +xgdb_display_source 93,2553 +xgdb_window_hook 650,16099 diff --git a/gdb/blockframe.c b/gdb/blockframe.c index 4acac1e6f82..86ff033e985 100644 --- a/gdb/blockframe.c +++ b/gdb/blockframe.c @@ -92,7 +92,7 @@ get_frame_info (frame) { struct frame_info val; FRAME current = get_current_frame (); - register FRAME frame1; + register FRAME frame1, frame2; val.frame = frame; @@ -100,17 +100,21 @@ get_frame_info (frame) { val.pc = read_pc (); val.next_frame = 0; + val.next_next_frame = 0; } else { - for (frame1 = current; frame1; frame1 = get_prev_frame (frame1)) + for (frame1 = current, frame2 = 0; + frame1; + frame2 = frame1, frame1 = get_prev_frame (frame1)) { QUIT; if (frame1 == frame) break; - val.pc = FRAME_SAVED_PC (frame1); + val.pc = FRAME_SAVED_PC (frame1, frame2); val.next_frame = frame1; + val.next_next_frame = frame2; } } @@ -125,22 +129,23 @@ get_frame_info (frame) to find the frame called by the one being described -- that is FRAME. */ struct frame_info -get_prev_frame_info (next_frame) - FRAME next_frame; +get_prev_frame_info (next_frame, next_next_frame) + FRAME next_frame, next_next_frame; { struct frame_info val; register FRAME frame = get_prev_frame (next_frame); val.frame = frame; val.next_frame = next_frame; + val.next_next_frame = next_next_frame; if (next_frame == 0) { val.pc = read_pc (); } - else + else { - val.pc = FRAME_SAVED_PC (next_frame); + val.pc = FRAME_SAVED_PC (next_frame, next_next_frame); } return val; diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 635cc495ce2..c5acf964c67 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -622,63 +622,96 @@ set_breakpoint (s, line, tempflag) } /* Set a breakpoint according to ARG (function, linenum or *address) - and make it temporary if TEMPFLAG is nonzero. */ + and make it temporary if TEMPFLAG is nonzero. + + LINE_NUM is for C++. */ static void -break_command_1 (arg, tempflag, from_tty) +break_command_1 (arg, tempflag, from_tty, line_num) char *arg; - int tempflag, from_tty; + int tempflag, from_tty, line_num; { + struct symtabs_and_lines sals; struct symtab_and_line sal; register struct expression *cond = 0; register struct breakpoint *b; + char *save_arg; + int i; + + sals.sals = NULL; + sals.nelts = 0; - sal.pc = 0; + sal.line = sal.pc = sal.end = 0; + sal.symtab = 0; if (arg) { - sal = decode_line_1 (&arg, 1, 0, 0); + CORE_ADDR pc; + sals = decode_line_1 (&arg, 1, 0, 0); - if (sal.pc == 0 && sal.symtab != 0) + if (! sals.nelts) return; + save_arg = arg; + for (i = 0; i < sals.nelts; i++) { - sal.pc = find_line_pc (sal.symtab, sal.line); - if (sal.pc == 0) - error ("No line %d in file \"%s\".", - sal.line, sal.symtab->filename); - } + sal = sals.sals[i]; + if (sal.pc == 0 && sal.symtab != 0) + { + pc = find_line_pc (sal.symtab, sal.line); + if (pc == 0) + error ("No line %d in file \"%s\".", + sal.line, sal.symtab->filename); + } + else pc = sal.pc; - while (*arg) - { - if (arg[0] == 'i' && arg[1] == 'f' - && (arg[2] == ' ' || arg[2] == '\t')) - cond = (struct expression *) parse_c_1 ((arg += 2, &arg), - block_for_pc (sal.pc), 0); - else - error ("Junk at end of arguments."); + while (*arg) + { + if (arg[0] == 'i' && arg[1] == 'f' + && (arg[2] == ' ' || arg[2] == '\t')) + cond = (struct expression *) parse_c_1 ((arg += 2, &arg), + block_for_pc (pc), 0); + else + error ("Junk at end of arguments."); + } + arg = save_arg; + sals.sals[i].pc = pc; } } else if (default_breakpoint_valid) { + sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line)); sal.pc = default_breakpoint_address; sal.line = default_breakpoint_line; sal.symtab = default_breakpoint_symtab; + sals.sals[0] = sal; + sals.nelts = 1; } else error ("No default breakpoint address now."); - if (from_tty) - describe_other_breakpoints (sal.pc); + for (i = 0; i < sals.nelts; i++) + { + sal = sals.sals[i]; + sal.line += line_num; /** C++ **/ + if (line_num != 0) + { /* get the pc for a particular line */ + sal.pc = find_line_pc (sal.symtab, sal.line); + } + + if (from_tty) + describe_other_breakpoints (sal.pc); - b = set_raw_breakpoint (sal); - b->number = ++breakpoint_count; - b->cond = cond; - if (tempflag) - b->enable = temporary; - - printf ("Breakpoint %d at 0x%x", b->number, b->address); - if (b->symtab) - printf (": file %s, line %d.", b->symtab->filename, b->line_number); - printf ("\n"); + b = set_raw_breakpoint (sal); + b->number = ++breakpoint_count; + b->cond = cond; + if (tempflag) + b->enable = temporary; + + printf ("Breakpoint %d at 0x%x", b->number, b->address); + if (b->symtab) + printf (": file %s, line %d.", b->symtab->filename, b->line_number); + printf ("\n"); + } + free (sals.sals); } static void @@ -686,7 +719,7 @@ break_command (arg, from_tty) char *arg; int from_tty; { - break_command_1 (arg, 0, from_tty); + break_command_1 (arg, 0, from_tty, 0); } static void @@ -694,7 +727,7 @@ tbreak_command (arg, from_tty) char *arg; int from_tty; { - break_command_1 (arg, 1, from_tty); + break_command_1 (arg, 1, from_tty, 0); } static void @@ -703,60 +736,70 @@ clear_command (arg, from_tty) int from_tty; { register struct breakpoint *b, *b1; + struct symtabs_and_lines sals; struct symtab_and_line sal; register struct breakpoint *found; + int i; if (arg) - sal = decode_line_spec (arg, 1); + sals = decode_line_spec (arg, 1); else { + sals.sals = (struct symtab_and_line *) malloc (sizeof (struct symtab_and_line)); sal.line = default_breakpoint_line; sal.symtab = default_breakpoint_symtab; sal.pc = 0; if (sal.symtab == 0) error ("No source file specified."); - } - /* If exact pc given, clear bpts at that pc. - But if sal.pc is zero, clear all bpts on specified line. */ + sals.sals[0] = sal; + sals.nelts = 1; + } - found = (struct breakpoint *) 0; - while (breakpoint_chain - && (sal.pc ? breakpoint_chain->address == sal.pc - : (breakpoint_chain->symtab == sal.symtab - && breakpoint_chain->line_number == sal.line))) + for (i = 0; i < sals.nelts; i++) { - b1 = breakpoint_chain; - breakpoint_chain = b1->next; - b1->next = found; - found = b1; - } + /* If exact pc given, clear bpts at that pc. + But if sal.pc is zero, clear all bpts on specified line. */ + sal = sals.sals[i]; + found = (struct breakpoint *) 0; + while (breakpoint_chain + && (sal.pc ? breakpoint_chain->address == sal.pc + : (breakpoint_chain->symtab == sal.symtab + && breakpoint_chain->line_number == sal.line))) + { + b1 = breakpoint_chain; + breakpoint_chain = b1->next; + b1->next = found; + found = b1; + } - ALL_BREAKPOINTS (b) - while (b->next - && (sal.pc ? b->next->address == sal.pc - : (b->next->symtab == sal.symtab - && b->next->line_number == sal.line))) - { - b1 = b->next; - b->next = b1->next; - b1->next = found; - found = b1; - } + ALL_BREAKPOINTS (b) + while (b->next + && (sal.pc ? b->next->address == sal.pc + : (b->next->symtab == sal.symtab + && b->next->line_number == sal.line))) + { + b1 = b->next; + b->next = b1->next; + b1->next = found; + found = b1; + } - if (found == 0) - error ("No breakpoint at %s.", arg); + if (found == 0) + error ("No breakpoint at %s.", arg); - if (found->next) from_tty = 1; /* Alwats report if deleted more than one */ - if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : ""); - while (found) - { - if (from_tty) printf ("%d ", found->number); - b1 = found->next; - delete_breakpoint (found); - found = b1; + if (found->next) from_tty = 1; /* Always report if deleted more than one */ + if (from_tty) printf ("Deleted breakpoint%s ", found->next ? "s" : ""); + while (found) + { + if (from_tty) printf ("%d ", found->number); + b1 = found->next; + delete_breakpoint (found); + found = b1; + } + if (from_tty) putchar ('\n'); } - if (from_tty) putchar ('\n'); + free (sals.sals); } /* Delete breakpoint number BNUM if it is a `delete' breakpoint. diff --git a/gdb/c.h b/gdb/c.h new file mode 100644 index 00000000000..1c60a3429e9 --- /dev/null +++ b/gdb/c.h @@ -0,0 +1,14 @@ +#include "b.h" + +inline c () +{ + Foo x = 1; + { + Foo y = 2; + { + b (); + } + Foo z = 3; + } + Foo w = 4; +} diff --git a/gdb/coffread.c b/gdb/coffread.c index 16edc000a2e..17b53bd6d01 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -423,4 +423,1429 @@ complete_symtab (name, start_addr, size) /* Finish the symbol definitions for one main source file, close off all the lexical contexts for that file (creating struct block's for them), then make the - struct sym \ No newline at end of file + struct symtab for that file and put it in the list of all such. */ + +static void +end_symtab () +{ + register struct symtab *symtab; + register struct context_stack *cstk; + register struct blockvector *blockvector; + register struct linetable *lv; + + /* Finish the lexical context of the last function in the file. */ + + if (context_stack) + { + cstk = context_stack; + /* Make a block for the local symbols within. */ + finish_block (cstk->name, &local_symbols, cstk->old_blocks, + cstk->start_addr, cur_src_end_addr); + free (cstk); + } + + finish_block (0, &file_symbols, 0, cur_src_start_addr, cur_src_end_addr); + finish_block (0, &global_symbols, 0, cur_src_start_addr, cur_src_end_addr); + blockvector = make_blockvector (); + + /* Now create the symtab object this source file. */ + + symtab = (struct symtab *) xmalloc (sizeof (struct symtab)); + symtab->free_ptr = 0; + + /* Fill in its components. */ + symtab->blockvector = blockvector; + symtab->free_code = free_linetable; + symtab->filename = last_source_file; + lv = line_vector; + lv->nitems = line_vector_index; + symtab->linetable = (struct linetable *) + xrealloc (lv, sizeof (struct linetable) + lv->nitems * sizeof (int)); + symtab->nlines = 0; + symtab->line_charpos = 0; + + /* Link the new symtab into the list of such. */ + symtab->next = symtab_list; + symtab_list = symtab; + + line_vector = 0; + line_vector_length = -1; + last_source_file = 0; +} + +/* Accumulate the misc functions in bunches of 127. + At the end, copy them all into one newly allocated structure. */ + +#define MISC_BUNCH_SIZE 127 + +struct misc_bunch +{ + struct misc_bunch *next; + struct misc_function contents[MISC_BUNCH_SIZE]; +}; + +/* Bunch currently being filled up. + The next field points to chain of filled bunches. */ + +static struct misc_bunch *misc_bunch; + +/* Number of slots filled in current bunch. */ + +static int misc_bunch_index; + +/* Total number of misc functions recorded so far. */ + +static int misc_count; + +static void +init_misc_functions () +{ + misc_count = 0; + misc_bunch = 0; + misc_bunch_index = MISC_BUNCH_SIZE; +} + +static void +record_misc_function (name, address) + char *name; + CORE_ADDR address; +{ + register struct misc_bunch *new; + + if (misc_bunch_index == MISC_BUNCH_SIZE) + { + new = (struct misc_bunch *) xmalloc (sizeof (struct misc_bunch)); + misc_bunch_index = 0; + new->next = misc_bunch; + misc_bunch = new; + } + misc_bunch->contents[misc_bunch_index].name = savestring (name, strlen (name)); + misc_bunch->contents[misc_bunch_index].address = address; + misc_bunch_index++; + misc_count++; +} + +static int +compare_misc_functions (fn1, fn2) + struct misc_function *fn1, *fn2; +{ + /* Return a signed result based on unsigned comparisons + so that we sort into unsigned numeric order. */ + if (fn1->address < fn2->address) + return -1; + if (fn1->address > fn2->address) + return 1; + return 0; +} + +static void +discard_misc_bunches () +{ + register struct misc_bunch *next; + + while (misc_bunch) + { + next = misc_bunch->next; + free (misc_bunch); + misc_bunch = next; + } +} + +static void +condense_misc_bunches () +{ + register int i, j; + register struct misc_bunch *bunch; +#ifdef NAMES_HAVE_UNDERSCORE + int offset = 1; +#else + int offset = 0; +#endif + + misc_function_vector + = (struct misc_function *) + xmalloc (misc_count * sizeof (struct misc_function)); + + j = 0; + bunch = misc_bunch; + while (bunch) + { + for (i = 0; i < misc_bunch_index; i++) + { + register char *tmp; + + misc_function_vector[j] = bunch->contents[i]; + tmp = misc_function_vector[j].name; + misc_function_vector[j].name = (tmp[0] == '_' ? tmp + offset : tmp); + j++; + } + bunch = bunch->next; + misc_bunch_index = MISC_BUNCH_SIZE; + } + + misc_function_count = j; + + /* Sort the misc functions by address. */ + + qsort (misc_function_vector, j, sizeof (struct misc_function), + compare_misc_functions); +} + +/* Call sort_syms to sort alphabetically + the symbols of each block of each symtab. */ + +static int +compare_symbols (s1, s2) + struct symbol **s1, **s2; +{ + /* Names that are less should come first. */ + register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)); + if (namediff != 0) return namediff; + /* For symbols of the same name, registers should come first. */ + return ((SYMBOL_CLASS (*s2) == LOC_REGISTER) + - (SYMBOL_CLASS (*s1) == LOC_REGISTER)); +} + +static void +sort_syms () +{ + register struct symtab *s; + register int i, nbl; + register struct blockvector *bv; + register struct block *b; + + for (s = symtab_list; s; s = s->next) + { + bv = BLOCKVECTOR (s); + nbl = BLOCKVECTOR_NBLOCKS (bv); + for (i = 0; i < nbl; i++) + { + b = BLOCKVECTOR_BLOCK (bv, i); + qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), + sizeof (struct symbol *), compare_symbols); + } + } +} + +/* This is the symbol-file command. Read the file, analyze its symbols, + and add a struct symtab to symtab_list. */ + +void +symbol_file_command (name) + char *name; +{ + int desc; + int num_symbols; + int num_sections; + int symtab_offset; + extern void close (); + register int val; + struct cleanup *old_chain; + + dont_repeat (); + + if (name == 0) + { + if (symtab_list && !query ("Discard symbol table? ", 0)) + error ("Not confirmed."); + free_all_symtabs (); + return; + } + + if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name)) + error ("Not confirmed."); + + if (symfile) + free (symfile); + symfile = 0; + + { + char *absolute_name; + + desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name); + if (desc < 0) + perror_with_name (name); + else + name = absolute_name; + } + + old_chain = make_cleanup (close, desc); + make_cleanup (free_current_contents, &name); + + if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0) + error ("File \"%s\" not in executable format.", name); + + if (num_symbols == 0) + { + free_all_symtabs (); + printf ("%s does not have a symbol-table.\n", name); + fflush (stdout); + return; + } + + printf ("Reading symbol data from %s...", name); + fflush (stdout); + + /* Throw away the old symbol table. */ + + free_all_symtabs (); + + num_sections = file_hdr.f_nscns; + symtab_offset = file_hdr.f_symptr; + + if (read_section_hdr (desc, _TEXT, &text_hdr, num_sections) < 0) + error ("\"%s\": can't read text section header", name); + + /* Read the line number table, all at once. */ + + val = init_lineno (desc, text_hdr.s_lnnoptr, text_hdr.s_nlnno); + if (val < 0) + error ("\"%s\": error reading line numbers\n", name); + + /* Now read the string table, all at once. */ + + val = init_stringtab (desc, symtab_offset + num_symbols * SYMESZ); + if (val < 0) + { + free_all_symtabs (); + printf ("\"%s\": can't get string table", name); + fflush (stdout); + return; + } + make_cleanup (free_stringtab, 0); + + /* Position to read the symbol table. Do not read it all at once. */ + val = lseek (desc, (long)symtab_offset, 0); + if (val < 0) + perror_with_name (name); + + init_misc_functions (); + make_cleanup (discard_misc_bunches, 0); + + /* Now that the executable file is positioned at symbol table, + process it and define symbols accordingly. */ + + read_coff_symtab (desc, num_symbols); + + patch_opaque_types (); + + /* Sort symbols alphabetically within each block. */ + + sort_syms (); + + /* Go over the misc functions and install them in vector. */ + + condense_misc_bunches (); + + /* Don't allow char * to have a typename (else would get caddr_t.) */ + + TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; + + /* Make a default for file to list. */ + + select_source_symtab (symtab_list); + + symfile = savestring (name, strlen (name)); + + do_cleanups (old_chain); + + printf ("done.\n"); + fflush (stdout); +} + +/* Return name of file symbols were loaded from, or 0 if none.. */ + +char * +get_sym_file () +{ + return symfile; +} + +/* Simplified internal version of coff symbol table information */ + +struct coff_symbol { + char *c_name; + int c_symnum; /* symbol number of this entry */ + int c_nsyms; /* 1 if syment only, 2 if syment + auxent */ + long c_value; + int c_sclass; + int c_secnum; + unsigned int c_type; +}; + +/* Given pointers to a symbol table in coff style exec file, + analyze them and create struct symtab's describing the symbols. + NSYMS is the number of symbols in the symbol table. + We read them one at a time using read_one_sym (). */ + +static void +read_coff_symtab (desc, nsyms) + int desc; + int nsyms; +{ + FILE *stream = fdopen (desc, "r"); + register struct context_stack *new; + struct coff_symbol coff_symbol; + register struct coff_symbol *cs = &coff_symbol; + static SYMENT main_sym; + static AUXENT main_aux; + + int num_object_files = 0; + int next_file_symnum; + char *filestring; + int depth; + int fcn_first_line; + int fcn_last_line; + long fcn_line_ptr; + struct cleanup *old_chain; + + old_chain = make_cleanup (free_all_symtabs, 0); + nlist_stream_global = stream; + nlist_nsyms_global = nsyms; + last_source_file = 0; + bzero (opaque_type_chain, sizeof opaque_type_chain); + + type_vector_length = 160; + type_vector = (struct typevector *) + xmalloc (sizeof (struct typevector) + + type_vector_length * sizeof (struct type *)); + bzero (type_vector->type, type_vector_length * sizeof (struct type *)); + + start_symtab (); + + symnum = 0; + while (symnum < nsyms) + { + QUIT; /* Make this command interruptable. */ + read_one_sym (cs, &main_sym, &main_aux); + + if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) + { + CORE_ADDR last_file_end = cur_src_end_addr; + + if (last_source_file) + end_symtab (); + + start_symtab (); + complete_symtab ("_globals_", 0, first_object_file_end); + /* done with all files, everything from here on out is globals */ + } + + /* Special case for file with type declarations only, no text. */ + if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG) + complete_symtab (filestring, 0, 0); + + if (ISFCN (cs->c_type)) + { + /* + * gdb expects all functions to also be in misc_function + * list -- why not... + */ + record_misc_function (cs->c_name, cs->c_value); + + fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; + within_function = 1; + + new = (struct context_stack *) + xmalloc (sizeof (struct context_stack)); + new->depth = depth = 0; + new->next = 0; + context_stack = new; + new->locals = 0; + new->old_blocks = pending_blocks; + new->start_addr = cs->c_value; + new->name = process_coff_symbol (cs, &main_aux); + continue; + } + + switch (cs->c_sclass) + { + case C_EFCN: + case C_EXTDEF: + case C_ULABEL: + case C_USTATIC: + case C_LINE: + case C_ALIAS: + case C_HIDDEN: + printf ("Bad n_sclass = %d\n", cs->c_sclass); + break; + + case C_FILE: + /* + * c_value field contains symnum of next .file entry in table + * or symnum of first global after last .file. + */ + next_file_symnum = cs->c_value; + filestring = getfilename (&main_aux); + /* + * Complete symbol table for last object file + * containing debugging information. + */ + if (last_source_file) + { + end_symtab (); + start_symtab (); + } + num_object_files++; + break; + + case C_EXT: + if (cs->c_secnum == N_ABS && strcmp (cs->c_name, _ETEXT) == 0) + { + end_of_text_addr = cs->c_value; + } + if (cs->c_type == T_NULL) + { + if (cs->c_secnum <= 1) /* text or abs */ + { + record_misc_function (cs->c_name, cs->c_value); + break; + } + else + cs->c_type = T_INT; + } + (void) process_coff_symbol (cs, &main_aux); + break; + + case C_STAT: + if (cs->c_type == T_NULL && cs->c_secnum > N_UNDEF) + { + if (strcmp (cs->c_name, _TEXT) == 0) + { + if (num_object_files == 1) + { + /* Record end address of first file, crt0.s */ + first_object_file_end = + cs->c_value + main_aux.x_scn.x_scnlen; + } + /* + * Fill in missing information for debugged + * object file only if we have line number info. + */ + if (main_aux.x_scn.x_nlinno > 0) + { + complete_symtab (filestring, cs->c_value, + main_aux.x_scn.x_scnlen); + } + break; + } + else if (strcmp (cs->c_name, _DATA) == 0) + break; + else if (strcmp (cs->c_name, _BSS) == 0) + break; + + /* get rid of assembly labels here */ + /* record_misc_function (cs->c_name, cs->c_value); */ + break; + } + (void) process_coff_symbol (cs, &main_aux); + break; + + case C_FCN: + if (strcmp (cs->c_name, ".bf") == 0) + { + /* value contains address of first non-init type code */ + /* main_aux.x_sym.x_misc.x_lnsz.x_lnno + contains line number of '{' } */ + fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; + } + else if (strcmp (cs->c_name, ".ef") == 0) + { + /* value contains address of exit/return from function */ + /* round it up to next multiple of 16 */ + cs->c_value = (cs->c_value + 15) & -16; + /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno + contains number of lines to '}' */ + fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; + enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line); + + new = context_stack; + finish_block (new->name, &local_symbols, new->old_blocks, + new->start_addr, cs->c_value); + context_stack = 0; + within_function = 0; + free (new); + } + break; + + case C_BLOCK: + if (strcmp (cs->c_name, ".bb") == 0) + { + new = (struct context_stack *) + xmalloc (sizeof (struct context_stack)); + depth++; + new->depth = depth; + new->next = context_stack; + context_stack = new; + new->locals = local_symbols; + new->old_blocks = pending_blocks; + new->start_addr = cs->c_value; + new->name = 0; + local_symbols = 0; + } + else if (strcmp (cs->c_name, ".eb") == 0) + { + new = context_stack; + if (new == 0 || depth != new->depth) + error ("Invalid symbol data: .bb/.eb symbol mismatch."); + if (local_symbols && context_stack->next) + { + /* Make a block for the local symbols within. */ + finish_block (0, &local_symbols, new->old_blocks, + new->start_addr, cs->c_value); + } + depth--; + local_symbols = new->locals; + context_stack = new->next; + free (new); + } + break; + + default: + (void) process_coff_symbol (cs, &main_aux); + break; + } + } + + if (last_source_file) + end_symtab (); + fclose (stream); + discard_cleanups (old_chain); +} + +/* Routines for reading headers and symbols from executable. */ + +/* Read COFF file header, check magic number, + and return number of symbols. */ +read_file_hdr (chan, file_hdr) + int chan; + FILHDR *file_hdr; +{ + lseek (chan, 0L, 0); + if (myread (chan, (char *)file_hdr, FILHSZ) < 0) + return -1; + + switch (file_hdr->f_magic) + { + case NS32GMAGIC: + case NS32SMAGIC: + return file_hdr->f_nsyms; + + default: + return -1; + } +} + +read_aout_hdr (chan, aout_hdr, size) + int chan; + AOUTHDR *aout_hdr; + int size; +{ + lseek (chan, (long)FILHSZ, 0); + if (size != sizeof (AOUTHDR)) + return -1; + if (myread (chan, (char *)aout_hdr, size) != size) + return -1; + return 0; +} + +read_section_hdr (chan, section_name, section_hdr, nsects) + register int chan; + register char *section_name; + SCNHDR *section_hdr; + register int nsects; +{ + register int i; + + if (lseek (chan, FILHSZ + sizeof (AOUTHDR), 0) < 0) + return -1; + + for (i = 0; i < nsects; i++) + { + if (myread (chan, (char *)section_hdr, SCNHSZ) < 0) + return -1; + if (strncmp (section_hdr->s_name, section_name, 8) == 0) + return 0; + } + return -1; +} + +read_one_sym (cs, sym, aux) + register struct coff_symbol *cs; + register SYMENT *sym; + register AUXENT *aux; +{ + cs->c_symnum = symnum; + fread ((char *)sym, SYMESZ, 1, nlist_stream_global); + cs->c_nsyms = (sym->n_numaux & 0xff) + 1; + if (cs->c_nsyms == 2) + { + /* doc for coff says there is either no aux entry or just one */ + fread ((char *)aux, AUXESZ, 1, nlist_stream_global); + } + else if (cs->c_nsyms > 2) + error ("more than one aux symbol table entry at symnum=%d\n", symnum); + + cs->c_name = getsymname (sym); + cs->c_value = sym->n_value; + cs->c_sclass = (sym->n_sclass & 0xff); + cs->c_secnum = sym->n_scnum; + cs->c_type = (unsigned) sym->n_type; + + symnum += cs->c_nsyms; +} + +/* Support for string table handling */ + +static char *stringtab = NULL; + +static int +init_stringtab (chan, offset) + int chan; + long offset; +{ + long buffer; + int val; + + if (lseek (chan, offset, 0) < 0) + return -1; + + val = myread (chan, (char *)&buffer, sizeof buffer); + if (val != sizeof buffer) + return -1; + + if (stringtab) + free (stringtab); + stringtab = (char *) xmalloc (buffer); + if (stringtab == NULL) + return -1; + + bcopy (&buffer, stringtab, sizeof buffer); + + val = myread (chan, stringtab + sizeof buffer, buffer - sizeof buffer); + if (val != buffer - sizeof buffer || stringtab[buffer - 1] != '\0') + return -1; + + return 0; +} + +static void +free_stringtab () +{ + if (stringtab) + free (stringtab); + stringtab = NULL; +} + +static char * +getsymname (symbol_entry) + SYMENT *symbol_entry; +{ + static char buffer[SYMNMLEN+1]; + char *result; + + if (symbol_entry->n_zeroes == 0) + { + result = stringtab + symbol_entry->n_offset; + } + else + { + strncpy (buffer, symbol_entry->n_name, SYMNMLEN); + buffer[SYMNMLEN] = '\0'; + result = buffer; + } + return result; +} + +static char * +getfilename (aux_entry) + AUXENT *aux_entry; +{ + static char buffer[BUFSIZ]; + register char *temp; + char *result; + extern char *rindex (); + + if (aux_entry->x_file.x_foff != 0) + strcpy (buffer, stringtab + aux_entry->x_file.x_foff); + else + { + strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); + buffer[FILNMLEN] = '\0'; + } + result = buffer; + if ((temp = rindex (result, '/')) != NULL) + result = temp + 1; + return (result); +} + +/* Support for line number handling */ +static char *linetab = NULL; +static long linetab_offset; +static int linetab_count; + +static int +init_lineno (chan, offset, count) + int chan; + long offset; + int count; +{ + int val; + + if (lseek (chan, offset, 0) < 0) + return -1; + + if (linetab) + free (linetab); + linetab = (char *) xmalloc (count * LINESZ); + + val = myread (chan, linetab, count * LINESZ); + if (val != count * LINESZ) + return -1; + + linetab_offset = offset; + linetab_count = count; + return 0; +} + +static void +enter_linenos (file_offset, first_line, last_line) + long file_offset; + register int first_line; + register int last_line; +{ + register char *rawptr = &linetab[file_offset - linetab_offset]; + register struct lineno *lptr; + + /* skip first line entry for each function */ + rawptr += LINESZ; + /* line numbers start at one for the first line of the function */ + first_line--; + + for (lptr = (struct lineno *)rawptr; + lptr->l_lnno && lptr->l_lnno <= last_line; + rawptr += LINESZ, lptr = (struct lineno *)rawptr) + { + record_line (first_line + lptr->l_lnno, lptr->l_addr.l_paddr); + } +} + +static int +hashname (name) + char *name; +{ + register char *p = name; + register int total = p[0]; + register int c; + + c = p[1]; + total += c << 2; + if (c) + { + c = p[2]; + total += c << 4; + if (c) + total += p[3] << 6; + } + + return total % HASHSIZE; +} + +static void +patch_type (type, real_type) + struct type *type; + struct type *real_type; +{ + register struct type *target = TYPE_TARGET_TYPE (type); + register struct type *real_target = TYPE_TARGET_TYPE (real_type); + int field_size = TYPE_NFIELDS (real_target) * sizeof (struct field); + + TYPE_LENGTH (target) = TYPE_LENGTH (real_target); + TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target); + TYPE_FIELDS (target) = (struct field *) + obstack_alloc (symbol_obstack, field_size); + + bcopy (TYPE_FIELDS (real_target), TYPE_FIELDS (target), field_size); + + if (TYPE_NAME (real_target)) + { + if (TYPE_NAME (target)) + free (TYPE_NAME (target)); + TYPE_NAME (target) = concat (TYPE_NAME (real_target), "", ""); + } +} + +/* Patch up all appropriate typdef symbols in the opaque_type_chains + so that they can be used to print out opaque data structures properly */ + +static void +patch_opaque_types () +{ + struct symtab *s; + + /* Look at each symbol in the per-file block of each symtab. */ + for (s = symtab_list; s; s = s->next) + { + register struct block *b; + register int i; + + /* Go through the per-file symbols only */ + b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1); + for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--) + { + register struct symbol *real_sym; + + /* Find completed typedefs to use to fix opaque ones. + Remove syms from the chain when their types are stored, + but search the whole chain, as there may be several syms + from different files with the same name. */ + real_sym = BLOCK_SYM (b, i); + if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF && + SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE && + TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR && + TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0) + { + register char *name = SYMBOL_NAME (real_sym); + register int hash = hashname (name); + register struct symbol *sym, *prev; + + prev = 0; + for (sym = opaque_type_chain[hash]; sym;) + { + if (name[0] == SYMBOL_NAME (sym)[0] && + !strcmp (name + 1, SYMBOL_NAME (sym) + 1)) + { + if (prev) + SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); + else + opaque_type_chain[hash] + = (struct symbol *) SYMBOL_VALUE (sym); + + patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym)); + + if (prev) + sym = (struct symbol *) SYMBOL_VALUE (prev); + else + sym = opaque_type_chain[hash]; + } + else + { + prev = sym; + sym = (struct symbol *) SYMBOL_VALUE (sym); + } + } + } + } + } +} + +static struct symbol * +process_coff_symbol (cs, aux) + register struct coff_symbol *cs; + register AUXENT *aux; +{ + register struct symbol *sym + = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); + char *name; + char *dot; +#ifdef NAMES_HAVE_UNDERSCORE + int offset = 1; +#else + int offset = 0; +#endif + + bzero (sym, sizeof (struct symbol)); + name = cs->c_name; + name = (name[0] == '_' ? name + offset : name); + SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, name, strlen (name)); + + /* default assumptions */ + SYMBOL_VALUE (sym) = cs->c_value; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + + if (ISFCN (cs->c_type)) + { + SYMBOL_TYPE (sym) + = lookup_function_type (decode_function_type (cs, cs->c_type, aux)); + SYMBOL_CLASS (sym) = LOC_BLOCK; + if (cs->c_sclass == C_STAT) + add_symbol_to_list (sym, &file_symbols); + else if (cs->c_sclass == C_EXT) + add_symbol_to_list (sym, &global_symbols); + } + else + { + SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux); + switch (cs->c_sclass) + { + case C_NULL: + break; + + case C_AUTO: + SYMBOL_CLASS (sym) = LOC_LOCAL; + add_symbol_to_list (sym, &local_symbols); + break; + + case C_EXT: + SYMBOL_CLASS (sym) = LOC_STATIC; + add_symbol_to_list (sym, &global_symbols); + break; + + case C_STAT: + SYMBOL_CLASS (sym) = LOC_STATIC; + if (within_function) { + /* Static symbol of local scope */ + add_symbol_to_list (sym, &local_symbols); + } + else { + /* Static symbol at top level of file */ + add_symbol_to_list (sym, &file_symbols); + } + break; + + case C_REG: + case C_REGPARM: + SYMBOL_CLASS (sym) = LOC_REGISTER; + add_symbol_to_list (sym, &local_symbols); + break; + + case C_LABEL: + break; + + case C_ARG: + SYMBOL_CLASS (sym) = LOC_ARG; + add_symbol_to_list (sym, &local_symbols); + /* If PCC says a parameter is a short or a char, + it is really an int. */ + if (SYMBOL_TYPE (sym) == builtin_type_char + || SYMBOL_TYPE (sym) == builtin_type_short) + SYMBOL_TYPE (sym) = builtin_type_int; + else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char + || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) + SYMBOL_TYPE (sym) = builtin_type_unsigned_int; + break; + + case C_TPDEF: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + + /* If type has no name, give it one */ + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 + && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) + TYPE_NAME (SYMBOL_TYPE (sym)) + = concat (SYMBOL_NAME (sym), "", ""); + + /* Keep track of any type which points to empty structured type, + so it can be filled from a definition from another file */ + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR && + TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0) + { + register int i = hashname (SYMBOL_NAME (sym)); + + SYMBOL_VALUE (sym) = (int) opaque_type_chain[i]; + opaque_type_chain[i] = sym; + } + add_symbol_to_list (sym, &file_symbols); + break; + + case C_STRTAG: + case C_UNTAG: + case C_ENTAG: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 + && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) + TYPE_NAME (SYMBOL_TYPE (sym)) + = concat ("", + (cs->c_sclass == C_ENTAG + ? "enum " + : (cs->c_sclass == C_STRTAG + ? "struct " : "union ")), + SYMBOL_NAME (sym)); + add_symbol_to_list (sym, &file_symbols); + break; + + default: + break; + } + } + return sym; +} + +/* Decode a coff type specifier; + return the type that is meant. */ + +static +struct type * +decode_type (cs, c_type, aux) + register struct coff_symbol *cs; + unsigned int c_type; + register AUXENT *aux; +{ + register struct type *type = 0; + register int n; + unsigned int new_c_type; + + if (c_type & ~N_BTMASK) + { + new_c_type = DECREF (c_type); + if (ISPTR (c_type)) + { + type = decode_type (cs, new_c_type, aux); + type = lookup_pointer_type (type); + } + else if (ISFCN (c_type)) + { + type = decode_type (cs, new_c_type, aux); + type = lookup_function_type (type); + } + else if (ISARY (c_type)) + { + int i, n; + register unsigned short *dim; + struct type *base_type; + + /* Define an array type. */ + /* auxent refers to array, not base type */ + if (aux->x_sym.x_tagndx == 0) + cs->c_nsyms = 1; + + /* shift the indices down */ + dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0]; + i = 1; + n = dim[0]; + for (i = 0; *dim && i < DIMNUM - 1; i++, dim++) + *dim = *(dim + 1); + *dim = 0; + + type = (struct type *) + obstack_alloc (symbol_obstack, sizeof (struct type)); + bzero (type, sizeof (struct type)); + + base_type = decode_type (cs, new_c_type, aux); + + TYPE_CODE (type) = TYPE_CODE_ARRAY; + TYPE_TARGET_TYPE (type) = base_type; + TYPE_LENGTH (type) = n * TYPE_LENGTH (base_type); + } + return type; + } + + /* Reference to existing type */ + if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx != 0) + { + type = coff_alloc_type (aux->x_sym.x_tagndx); + return type; + } + + return decode_base_type (cs, BTYPE (c_type), aux); +} + +/* Decode a coff type specifier for function definition; + return the type that the function returns. */ + +static +struct type * +decode_function_type (cs, c_type, aux) + register struct coff_symbol *cs; + unsigned int c_type; + register AUXENT *aux; +{ + if (aux->x_sym.x_tagndx == 0) + cs->c_nsyms = 1; /* auxent refers to function, not base type */ + + return decode_type (cs, DECREF (cs->c_type), aux); +} + +/* basic C types */ + +static +struct type * +decode_base_type (cs, c_type, aux) + register struct coff_symbol *cs; + unsigned int c_type; + register AUXENT *aux; +{ + struct type *type; + + switch (c_type) + { + case T_NULL: + /* shouldn't show up here */ + break; + + case T_ARG: + /* shouldn't show up here */ + break; + + case T_CHAR: + return builtin_type_char; + + case T_SHORT: + return builtin_type_short; + + case T_INT: + return builtin_type_int; + + case T_LONG: + return builtin_type_long; + + case T_FLOAT: + return builtin_type_float; + + case T_DOUBLE: + return builtin_type_double; + + case T_STRUCT: + if (cs->c_nsyms != 2) + { + /* anonymous structure type */ + type = coff_alloc_type (cs->c_symnum); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_NAME (type) = concat ("struct ", "", ""); + TYPE_LENGTH (type) = 0; + TYPE_FIELDS (type) = 0; + TYPE_NFIELDS (type) = 0; + } + else + { + type = read_struct_type (cs->c_symnum, + aux->x_sym.x_misc.x_lnsz.x_size, + aux->x_sym.x_fcnary.x_fcn.x_endndx); + } + return type; + + case T_UNION: + if (cs->c_nsyms != 2) + { + /* anonymous union type */ + type = coff_alloc_type (cs->c_symnum); + TYPE_NAME (type) = concat ("union ", "", ""); + TYPE_LENGTH (type) = 0; + TYPE_FIELDS (type) = 0; + TYPE_NFIELDS (type) = 0; + } + else + { + type = read_struct_type (cs->c_symnum, + aux->x_sym.x_misc.x_lnsz.x_size, + aux->x_sym.x_fcnary.x_fcn.x_endndx); + } + TYPE_CODE (type) = TYPE_CODE_UNION; + return type; + + case T_ENUM: + return read_enum_type (cs->c_symnum, + aux->x_sym.x_misc.x_lnsz.x_size, + aux->x_sym.x_fcnary.x_fcn.x_endndx); + + case T_MOE: + /* shouldn't show up here */ + break; + + case T_UCHAR: + return builtin_type_unsigned_char; + + case T_USHORT: + return builtin_type_unsigned_short; + + case T_UINT: + return builtin_type_unsigned_int; + + case T_ULONG: + return builtin_type_unsigned_long; + } + printf ("unexpected type %d at symnum %d\n", c_type, cs->c_symnum); + return builtin_type_void; +} + +/* This page contains subroutines of read_type. */ + +/* Read the description of a structure (or union type) + and return an object describing the type. */ + +static struct type * +read_struct_type (index, length, lastsym) + int index; + int length; + int lastsym; +{ + struct nextfield + { + struct nextfield *next; + struct field field; + }; + + register struct type *type; + register struct nextfield *list = 0; + struct nextfield *new; + int nfields = 0; + register int n; + char *name; +#ifdef NAMES_HAVE_UNDERSCORE + int offset = 1; +#else + int offset = 0; +#endif + struct coff_symbol member_sym; + register struct coff_symbol *ms = &member_sym; + SYMENT sub_sym; + AUXENT sub_aux; + + type = coff_alloc_type (index); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_LENGTH (type) = length; + + while (symnum < lastsym && symnum < nlist_nsyms_global) + { + read_one_sym (ms, &sub_sym, &sub_aux); + name = ms->c_name; + name = (name[0] == '_' ? name + offset : name); + + switch (ms->c_sclass) + { + case C_MOS: + case C_MOU: + + /* Get space to record the next field's data. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + /* Save the data. */ + list->field.name = savestring (name, strlen (name)); + list->field.type = decode_type (ms, ms->c_type, &sub_aux); + list->field.bitpos = 8 * ms->c_value; + list->field.bitsize = 0; + nfields++; + break; + + case C_FIELD: + + /* Get space to record the next field's data. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + /* Save the data. */ + list->field.name = savestring (name, strlen (name)); + list->field.type = decode_type (ms, ms->c_type, &sub_aux); + list->field.bitpos = ms->c_value; + list->field.bitsize = sub_aux.x_sym.x_misc.x_lnsz.x_size; + nfields++; + break; + + case C_EOS: + break; + } + } + /* Now create the vector of fields, and record how big it is. */ + + TYPE_NFIELDS (type) = nfields; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (symbol_obstack, sizeof (struct field) * nfields); + + /* Copy the saved-up fields into the field vector. */ + + for (n = nfields; list; list = list->next) + TYPE_FIELD (type, --n) = list->field; + + return type; +} + +/* Read a definition of an enumeration type, + and create and return a suitable type object. + Also defines the symbols that represent the values of the type. */ + +static struct type * +read_enum_type (index, length, lastsym) + int index; + int length; + int lastsym; +{ + register struct symbol *sym; + register struct type *type; + int nsyms = 0; + struct pending **symlist; + struct coff_symbol member_sym; + register struct coff_symbol *ms = &member_sym; + SYMENT sub_sym; + AUXENT sub_aux; + struct pending *osyms, *syms; + register int n; + char *name; +#ifdef NAMES_HAVE_UNDERSCORE + int offset = 1; +#else + int offset = 0; +#endif + + type = coff_alloc_type (index); + if (within_function) + symlist = &local_symbols; + else + symlist = &file_symbols; + osyms = *symlist; + + while (symnum < lastsym && symnum < nlist_nsyms_global) + { + read_one_sym (ms, &sub_sym, &sub_aux); + name = ms->c_name; + name = (name[0] == '_' ? name + offset : name); + + switch (ms->c_sclass) + { + case C_MOE: + sym = (struct symbol *) xmalloc (sizeof (struct symbol)); + bzero (sym, sizeof (struct symbol)); + + SYMBOL_NAME (sym) = savestring (name, strlen (name)); + SYMBOL_CLASS (sym) = LOC_CONST; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + SYMBOL_VALUE (sym) = ms->c_value; + add_symbol_to_list (sym, symlist); + nsyms++; + break; + + case C_EOS: + break; + } + } + + /* Now fill in the fields of the type-structure. */ + + TYPE_LENGTH (type) = sizeof (int); + TYPE_CODE (type) = TYPE_CODE_ENUM; + TYPE_NFIELDS (type) = nsyms; + TYPE_FIELDS (type) = (struct field *) + obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms); + + /* Find the symbols for the values and put them into the type. + The symbols can be found in the symlist that we put them on + to cause them to be defined. osyms contains the old value + of that symlist; everything up to there was defined by us. */ + + for (syms = *symlist, n = nsyms; syms != osyms; syms = syms->next) + { + SYMBOL_TYPE (syms->symbol) = type; + TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol); + TYPE_FIELD_VALUE (type, n) = SYMBOL_VALUE (syms->symbol); + TYPE_FIELD_BITPOS (type, n) = 0; + TYPE_FIELD_BITSIZE (type, n) = 0; + } + return type; +} + +static +initialize () +{ + symfile = 0; + + add_com ("symbol-file", class_files, symbol_file_command, + "Load symbol table (in coff format) from executable file FILE."); +} + +END_FILE + +#endif /* COFF_FORMAT */ + diff --git a/gdb/coffread.c.README b/gdb/coffread.c.README deleted file mode 100644 index 922e50c7c38..00000000000 --- a/gdb/coffread.c.README +++ /dev/null @@ -1,12 +0,0 @@ -coffread.c is truncated. - -It ends on a 4096-byte boundary, which makes me think it got chopped -in a disk operation, so the modification date probably doesn't reflect -the date of the damage. - -We checked the backups of Sep 8, 1992 and June 3, 1991, and in both -cases it was truncated. So we would appear to be out of luck. - -Someone found gdb-assorted on a dump of /s3 from cygint on November -19, 1990, but no gdb-2.8. The guess is that gdb-2.8 moved there after -/s3 moved to /work (which was apparently a new 1gig disk at the time). diff --git a/gdb/coffread.c.pmax b/gdb/coffread.c.pmax deleted file mode 100644 index 17b53bd6d01..00000000000 --- a/gdb/coffread.c.pmax +++ /dev/null @@ -1,1851 +0,0 @@ -/* Read coff symbol tables and convert to internal format, for GDB. - Design and support routines derived from dbxread.c, and UMAX COFF - specific routines written 9/1/87 by David D. Johnson, Brown University. - Revised 11/27/87 ddj@cs.brown.edu - Copyright (C) 1987, 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 "defs.h" -#include "param.h" -#ifdef COFF_FORMAT -#include "initialize.h" -#include "symtab.h" - -#include -#include -#include -#include -#include - -static void add_symbol_to_list (); -static void read_coff_symtab (); -static void patch_opaque_types (); -static struct type *decode_function_type (); -static struct type *decode_type (); -static struct type *decode_base_type (); -static struct type *read_enum_type (); -static struct type *read_struct_type (); -static void finish_block (); -static struct blockvector *make_blockvector (); -static struct symbol *process_coff_symbol (); -static int init_stringtab (); -static void free_stringtab (); -static char *getfilename (); -static char *getsymname (); -static int init_lineno (); -static void enter_linenos (); - -extern void free_all_symtabs (); - -START_FILE - -/* Name of source file whose symbol data we are now processing. - This comes from a symbol named ".file". */ - -static char *last_source_file; - -/* Core address of start and end of text of current source file. - This comes from a ".text" symbol where x_nlinno > 0. */ - -static CORE_ADDR cur_src_start_addr; -static CORE_ADDR cur_src_end_addr; - -/* End of the text segment of the executable file, - as found in the symbol _etext. */ - -static CORE_ADDR end_of_text_addr; - -/* The addresses of the symbol table stream and number of symbols - of the object file we are reading (as copied into core). */ - -static FILE *nlist_stream_global; -static int nlist_nsyms_global; - -/* The file and text section headers of the symbol file */ - -static FILHDR file_hdr; -static SCNHDR text_hdr; - -/* The index in the symbol table of the last coff symbol that was processed. */ - -static int symnum; - -/* Vector of types defined so far, indexed by their coff symnum. */ - -static struct typevector *type_vector; - -/* Number of elements allocated for type_vector currently. */ - -static int type_vector_length; - -/* Vector of line number information. */ - -static struct linetable *line_vector; - -/* Index of next entry to go in line_vector_index. */ - -static int line_vector_index; - -/* Last line number recorded in the line vector. */ - -static int prev_line_number; - -/* Number of elements allocated for line_vector currently. */ - -static int line_vector_length; - -/* Chain of typedefs of pointers to empty struct/union types. - They are chained thru the SYMBOL_VALUE. */ - -#define HASHSIZE 127 -static struct symbol *opaque_type_chain[HASHSIZE]; - -/* Record the symbols defined for each context in a list. - We don't create a struct block for the context until we - know how long to make it. */ - -struct pending -{ - struct pending *next; - struct symbol *symbol; -}; - -/* Here are the three lists that symbols are put on. */ - -struct pending *file_symbols; /* static at top level, and types */ - -struct pending *global_symbols; /* global functions and variables */ - -struct pending *local_symbols; /* everything local to lexical context */ - -/* List of unclosed lexical contexts - (that will become blocks, eventually). */ - -struct context_stack -{ - struct context_stack *next; - struct pending *locals; - struct pending_block *old_blocks; - struct symbol *name; - CORE_ADDR start_addr; - int depth; -}; - -struct context_stack *context_stack; - -/* Nonzero if within a function (so symbols should be local, - if nothing says specifically). */ - -int within_function; - -/* List of blocks already made (lexical contexts already closed). - This is used at the end to make the blockvector. */ - -struct pending_block -{ - struct pending_block *next; - struct block *block; -}; - -struct pending_block *pending_blocks; - -extern CORE_ADDR first_object_file_end; /* From blockframe.c */ - -/* File name symbols were loaded from. */ - -static char *symfile; - -/* Look up a coff type-number index. Return the address of the slot - where the type for that index is stored. - The type-number is in INDEX. - - This can be used for finding the type associated with that index - or for associating a new type with the index. */ - -static struct type ** -coff_lookup_type (index) - register int index; -{ - if (index >= type_vector_length) - { - type_vector_length *= 2; - type_vector = (struct typevector *) - xrealloc (type_vector, sizeof (struct typevector) - + type_vector_length * sizeof (struct type *)); - bzero (&type_vector->type[type_vector_length / 2], - type_vector_length * sizeof (struct type *) / 2); - } - return &type_vector->type[index]; -} - -/* Make sure there is a type allocated for type number index - and return the type object. - This can create an empty (zeroed) type object. */ - -static struct type * -coff_alloc_type (index) - int index; -{ - register struct type **type_addr = coff_lookup_type (index); - register struct type *type = *type_addr; - - /* If we are referring to a type not known at all yet, - allocate an empty type for it. - We will fill it in later if we find out how. */ - if (type == 0) - { - type = (struct type *) obstack_alloc (symbol_obstack, - sizeof (struct type)); - bzero (type, sizeof (struct type)); - *type_addr = type; - } - return type; -} - -/* maintain the lists of symbols and blocks */ - -/* Add a symbol to one of the lists of symbols. */ -static void -add_symbol_to_list (symbol, listhead) - struct symbol *symbol; - struct pending **listhead; -{ - register struct pending *link - = (struct pending *) xmalloc (sizeof (struct pending)); - - link->next = *listhead; - link->symbol = symbol; - *listhead = link; -} - -/* Take one of the lists of symbols and make a block from it. - Put the block on the list of pending blocks. */ - -static void -finish_block (symbol, listhead, old_blocks, start, end) - struct symbol *symbol; - struct pending **listhead; - struct pending_block *old_blocks; - CORE_ADDR start, end; -{ - register struct pending *next, *next1; - register struct block *block; - register struct pending_block *pblock; - struct pending_block *opblock; - register int i; - - /* Count the length of the list of symbols. */ - - for (next = *listhead, i = 0; next; next = next->next, i++); - - block = (struct block *) - obstack_alloc (symbol_obstack, sizeof (struct block) + (i - 1) * sizeof (struct symbol *)); - - /* Copy the symbols into the block. */ - - BLOCK_NSYMS (block) = i; - for (next = *listhead; next; next = next->next) - BLOCK_SYM (block, --i) = next->symbol; - - BLOCK_START (block) = start; - BLOCK_END (block) = end; - BLOCK_SUPERBLOCK (block) = 0; /* Filled in when containing block is made */ - - /* Put the block in as the value of the symbol that names it. */ - - if (symbol) - { - SYMBOL_BLOCK_VALUE (symbol) = block; - BLOCK_FUNCTION (block) = symbol; - } - else - BLOCK_FUNCTION (block) = 0; - - /* Now free the links of the list, and empty the list. */ - - for (next = *listhead; next; next = next1) - { - next1 = next->next; - free (next); - } - *listhead = 0; - - /* Install this block as the superblock - of all blocks made since the start of this scope - that don't have superblocks yet. */ - - opblock = 0; - for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next) - { - if (BLOCK_SUPERBLOCK (pblock->block) == 0) - BLOCK_SUPERBLOCK (pblock->block) = block; - opblock = pblock; - } - - /* Record this block on the list of all blocks in the file. - Put it after opblock, or at the beginning if opblock is 0. - This puts the block in the list after all its subblocks. */ - - pblock = (struct pending_block *) xmalloc (sizeof (struct pending_block)); - pblock->block = block; - if (opblock) - { - pblock->next = opblock->next; - opblock->next = pblock; - } - else - { - pblock->next = pending_blocks; - pending_blocks = pblock; - } -} - -static struct blockvector * -make_blockvector () -{ - register struct pending_block *next, *next1; - register struct blockvector *blockvector; - register int i; - - /* Count the length of the list of blocks. */ - - for (next = pending_blocks, i = 0; next; next = next->next, i++); - - blockvector = (struct blockvector *) - obstack_alloc (symbol_obstack, sizeof (struct blockvector) + (i - 1) * sizeof (struct block *)); - - /* Copy the blocks into the blockvector. - This is done in reverse order, which happens to put - the blocks into the proper order (ascending starting address). - finish_block has hair to insert each block into the list - after its subblocks in order to make sure this is true. */ - - BLOCKVECTOR_NBLOCKS (blockvector) = i; - for (next = pending_blocks; next; next = next->next) - BLOCKVECTOR_BLOCK (blockvector, --i) = next->block; - - /* Now free the links of the list, and empty the list. */ - - for (next = pending_blocks; next; next = next1) - { - next1 = next->next; - free (next); - } - pending_blocks = 0; - - return blockvector; -} - -/* Manage the vector of line numbers. */ - -static -record_line (line, pc) - int line; - CORE_ADDR pc; -{ - /* Make sure line vector is big enough. */ - - if (line_vector_index + 2 >= line_vector_length) - { - line_vector_length *= 2; - line_vector = (struct linetable *) - xrealloc (line_vector, sizeof (struct linetable) - + line_vector_length * sizeof (int)); - } - - /* If this line is not continguous with previous one recorded, - all lines between subsequent line and current one are same pc. - Add one item to line vector, and if more than one line skipped, - record a line-number entry for it. */ - if (prev_line_number > 0 && line != prev_line_number + 1) - line_vector->item[line_vector_index++] = pc; - if (prev_line_number < 0 || line > prev_line_number + 2) - line_vector->item[line_vector_index++] = - line; - prev_line_number = line; - - /* Record the core address of the line. */ - line_vector->item[line_vector_index++] = pc; -} - -/* Start a new symtab for a new source file. - This is called when a COFF ".file" symbol is seen; - it indicates the start of data for one original source file. */ - -static void -start_symtab () -{ - file_symbols = 0; - global_symbols = 0; - context_stack = 0; - within_function = 0; - last_source_file = 0; - - /* Initialize the source file information for this file. */ - - line_vector_index = 0; - line_vector_length = 1000; - prev_line_number = -2; /* Force first line number to be explicit */ - line_vector = (struct linetable *) - xmalloc (sizeof (struct linetable) + line_vector_length * sizeof (int)); -} - -/* Save the vital information for use when closing off the current file. - NAME is the file name the symbols came from, START_ADDR is the first - text address for the file, and SIZE is the number of bytes of text. */ - -static void -complete_symtab (name, start_addr, size) - char *name; - CORE_ADDR start_addr; - unsigned int size; -{ - last_source_file = savestring (name, strlen (name)); - cur_src_start_addr = start_addr; - cur_src_end_addr = start_addr + size; -} - -/* Finish the symbol definitions for one main source file, - close off all the lexical contexts for that file - (creating struct block's for them), then make the - struct symtab for that file and put it in the list of all such. */ - -static void -end_symtab () -{ - register struct symtab *symtab; - register struct context_stack *cstk; - register struct blockvector *blockvector; - register struct linetable *lv; - - /* Finish the lexical context of the last function in the file. */ - - if (context_stack) - { - cstk = context_stack; - /* Make a block for the local symbols within. */ - finish_block (cstk->name, &local_symbols, cstk->old_blocks, - cstk->start_addr, cur_src_end_addr); - free (cstk); - } - - finish_block (0, &file_symbols, 0, cur_src_start_addr, cur_src_end_addr); - finish_block (0, &global_symbols, 0, cur_src_start_addr, cur_src_end_addr); - blockvector = make_blockvector (); - - /* Now create the symtab object this source file. */ - - symtab = (struct symtab *) xmalloc (sizeof (struct symtab)); - symtab->free_ptr = 0; - - /* Fill in its components. */ - symtab->blockvector = blockvector; - symtab->free_code = free_linetable; - symtab->filename = last_source_file; - lv = line_vector; - lv->nitems = line_vector_index; - symtab->linetable = (struct linetable *) - xrealloc (lv, sizeof (struct linetable) + lv->nitems * sizeof (int)); - symtab->nlines = 0; - symtab->line_charpos = 0; - - /* Link the new symtab into the list of such. */ - symtab->next = symtab_list; - symtab_list = symtab; - - line_vector = 0; - line_vector_length = -1; - last_source_file = 0; -} - -/* Accumulate the misc functions in bunches of 127. - At the end, copy them all into one newly allocated structure. */ - -#define MISC_BUNCH_SIZE 127 - -struct misc_bunch -{ - struct misc_bunch *next; - struct misc_function contents[MISC_BUNCH_SIZE]; -}; - -/* Bunch currently being filled up. - The next field points to chain of filled bunches. */ - -static struct misc_bunch *misc_bunch; - -/* Number of slots filled in current bunch. */ - -static int misc_bunch_index; - -/* Total number of misc functions recorded so far. */ - -static int misc_count; - -static void -init_misc_functions () -{ - misc_count = 0; - misc_bunch = 0; - misc_bunch_index = MISC_BUNCH_SIZE; -} - -static void -record_misc_function (name, address) - char *name; - CORE_ADDR address; -{ - register struct misc_bunch *new; - - if (misc_bunch_index == MISC_BUNCH_SIZE) - { - new = (struct misc_bunch *) xmalloc (sizeof (struct misc_bunch)); - misc_bunch_index = 0; - new->next = misc_bunch; - misc_bunch = new; - } - misc_bunch->contents[misc_bunch_index].name = savestring (name, strlen (name)); - misc_bunch->contents[misc_bunch_index].address = address; - misc_bunch_index++; - misc_count++; -} - -static int -compare_misc_functions (fn1, fn2) - struct misc_function *fn1, *fn2; -{ - /* Return a signed result based on unsigned comparisons - so that we sort into unsigned numeric order. */ - if (fn1->address < fn2->address) - return -1; - if (fn1->address > fn2->address) - return 1; - return 0; -} - -static void -discard_misc_bunches () -{ - register struct misc_bunch *next; - - while (misc_bunch) - { - next = misc_bunch->next; - free (misc_bunch); - misc_bunch = next; - } -} - -static void -condense_misc_bunches () -{ - register int i, j; - register struct misc_bunch *bunch; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - misc_function_vector - = (struct misc_function *) - xmalloc (misc_count * sizeof (struct misc_function)); - - j = 0; - bunch = misc_bunch; - while (bunch) - { - for (i = 0; i < misc_bunch_index; i++) - { - register char *tmp; - - misc_function_vector[j] = bunch->contents[i]; - tmp = misc_function_vector[j].name; - misc_function_vector[j].name = (tmp[0] == '_' ? tmp + offset : tmp); - j++; - } - bunch = bunch->next; - misc_bunch_index = MISC_BUNCH_SIZE; - } - - misc_function_count = j; - - /* Sort the misc functions by address. */ - - qsort (misc_function_vector, j, sizeof (struct misc_function), - compare_misc_functions); -} - -/* Call sort_syms to sort alphabetically - the symbols of each block of each symtab. */ - -static int -compare_symbols (s1, s2) - struct symbol **s1, **s2; -{ - /* Names that are less should come first. */ - register int namediff = strcmp (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)); - if (namediff != 0) return namediff; - /* For symbols of the same name, registers should come first. */ - return ((SYMBOL_CLASS (*s2) == LOC_REGISTER) - - (SYMBOL_CLASS (*s1) == LOC_REGISTER)); -} - -static void -sort_syms () -{ - register struct symtab *s; - register int i, nbl; - register struct blockvector *bv; - register struct block *b; - - for (s = symtab_list; s; s = s->next) - { - bv = BLOCKVECTOR (s); - nbl = BLOCKVECTOR_NBLOCKS (bv); - for (i = 0; i < nbl; i++) - { - b = BLOCKVECTOR_BLOCK (bv, i); - qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), - sizeof (struct symbol *), compare_symbols); - } - } -} - -/* This is the symbol-file command. Read the file, analyze its symbols, - and add a struct symtab to symtab_list. */ - -void -symbol_file_command (name) - char *name; -{ - int desc; - int num_symbols; - int num_sections; - int symtab_offset; - extern void close (); - register int val; - struct cleanup *old_chain; - - dont_repeat (); - - if (name == 0) - { - if (symtab_list && !query ("Discard symbol table? ", 0)) - error ("Not confirmed."); - free_all_symtabs (); - return; - } - - if (symtab_list && !query ("Load new symbol table from \"%s\"? ", name)) - error ("Not confirmed."); - - if (symfile) - free (symfile); - symfile = 0; - - { - char *absolute_name; - - desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name); - if (desc < 0) - perror_with_name (name); - else - name = absolute_name; - } - - old_chain = make_cleanup (close, desc); - make_cleanup (free_current_contents, &name); - - if ((num_symbols = read_file_hdr (desc, &file_hdr)) < 0) - error ("File \"%s\" not in executable format.", name); - - if (num_symbols == 0) - { - free_all_symtabs (); - printf ("%s does not have a symbol-table.\n", name); - fflush (stdout); - return; - } - - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Throw away the old symbol table. */ - - free_all_symtabs (); - - num_sections = file_hdr.f_nscns; - symtab_offset = file_hdr.f_symptr; - - if (read_section_hdr (desc, _TEXT, &text_hdr, num_sections) < 0) - error ("\"%s\": can't read text section header", name); - - /* Read the line number table, all at once. */ - - val = init_lineno (desc, text_hdr.s_lnnoptr, text_hdr.s_nlnno); - if (val < 0) - error ("\"%s\": error reading line numbers\n", name); - - /* Now read the string table, all at once. */ - - val = init_stringtab (desc, symtab_offset + num_symbols * SYMESZ); - if (val < 0) - { - free_all_symtabs (); - printf ("\"%s\": can't get string table", name); - fflush (stdout); - return; - } - make_cleanup (free_stringtab, 0); - - /* Position to read the symbol table. Do not read it all at once. */ - val = lseek (desc, (long)symtab_offset, 0); - if (val < 0) - perror_with_name (name); - - init_misc_functions (); - make_cleanup (discard_misc_bunches, 0); - - /* Now that the executable file is positioned at symbol table, - process it and define symbols accordingly. */ - - read_coff_symtab (desc, num_symbols); - - patch_opaque_types (); - - /* Sort symbols alphabetically within each block. */ - - sort_syms (); - - /* Go over the misc functions and install them in vector. */ - - condense_misc_bunches (); - - /* Don't allow char * to have a typename (else would get caddr_t.) */ - - TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; - - /* Make a default for file to list. */ - - select_source_symtab (symtab_list); - - symfile = savestring (name, strlen (name)); - - do_cleanups (old_chain); - - printf ("done.\n"); - fflush (stdout); -} - -/* Return name of file symbols were loaded from, or 0 if none.. */ - -char * -get_sym_file () -{ - return symfile; -} - -/* Simplified internal version of coff symbol table information */ - -struct coff_symbol { - char *c_name; - int c_symnum; /* symbol number of this entry */ - int c_nsyms; /* 1 if syment only, 2 if syment + auxent */ - long c_value; - int c_sclass; - int c_secnum; - unsigned int c_type; -}; - -/* Given pointers to a symbol table in coff style exec file, - analyze them and create struct symtab's describing the symbols. - NSYMS is the number of symbols in the symbol table. - We read them one at a time using read_one_sym (). */ - -static void -read_coff_symtab (desc, nsyms) - int desc; - int nsyms; -{ - FILE *stream = fdopen (desc, "r"); - register struct context_stack *new; - struct coff_symbol coff_symbol; - register struct coff_symbol *cs = &coff_symbol; - static SYMENT main_sym; - static AUXENT main_aux; - - int num_object_files = 0; - int next_file_symnum; - char *filestring; - int depth; - int fcn_first_line; - int fcn_last_line; - long fcn_line_ptr; - struct cleanup *old_chain; - - old_chain = make_cleanup (free_all_symtabs, 0); - nlist_stream_global = stream; - nlist_nsyms_global = nsyms; - last_source_file = 0; - bzero (opaque_type_chain, sizeof opaque_type_chain); - - type_vector_length = 160; - type_vector = (struct typevector *) - xmalloc (sizeof (struct typevector) - + type_vector_length * sizeof (struct type *)); - bzero (type_vector->type, type_vector_length * sizeof (struct type *)); - - start_symtab (); - - symnum = 0; - while (symnum < nsyms) - { - QUIT; /* Make this command interruptable. */ - read_one_sym (cs, &main_sym, &main_aux); - - if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE) - { - CORE_ADDR last_file_end = cur_src_end_addr; - - if (last_source_file) - end_symtab (); - - start_symtab (); - complete_symtab ("_globals_", 0, first_object_file_end); - /* done with all files, everything from here on out is globals */ - } - - /* Special case for file with type declarations only, no text. */ - if (!last_source_file && cs->c_type != T_NULL && cs->c_secnum == N_DEBUG) - complete_symtab (filestring, 0, 0); - - if (ISFCN (cs->c_type)) - { - /* - * gdb expects all functions to also be in misc_function - * list -- why not... - */ - record_misc_function (cs->c_name, cs->c_value); - - fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr; - within_function = 1; - - new = (struct context_stack *) - xmalloc (sizeof (struct context_stack)); - new->depth = depth = 0; - new->next = 0; - context_stack = new; - new->locals = 0; - new->old_blocks = pending_blocks; - new->start_addr = cs->c_value; - new->name = process_coff_symbol (cs, &main_aux); - continue; - } - - switch (cs->c_sclass) - { - case C_EFCN: - case C_EXTDEF: - case C_ULABEL: - case C_USTATIC: - case C_LINE: - case C_ALIAS: - case C_HIDDEN: - printf ("Bad n_sclass = %d\n", cs->c_sclass); - break; - - case C_FILE: - /* - * c_value field contains symnum of next .file entry in table - * or symnum of first global after last .file. - */ - next_file_symnum = cs->c_value; - filestring = getfilename (&main_aux); - /* - * Complete symbol table for last object file - * containing debugging information. - */ - if (last_source_file) - { - end_symtab (); - start_symtab (); - } - num_object_files++; - break; - - case C_EXT: - if (cs->c_secnum == N_ABS && strcmp (cs->c_name, _ETEXT) == 0) - { - end_of_text_addr = cs->c_value; - } - if (cs->c_type == T_NULL) - { - if (cs->c_secnum <= 1) /* text or abs */ - { - record_misc_function (cs->c_name, cs->c_value); - break; - } - else - cs->c_type = T_INT; - } - (void) process_coff_symbol (cs, &main_aux); - break; - - case C_STAT: - if (cs->c_type == T_NULL && cs->c_secnum > N_UNDEF) - { - if (strcmp (cs->c_name, _TEXT) == 0) - { - if (num_object_files == 1) - { - /* Record end address of first file, crt0.s */ - first_object_file_end = - cs->c_value + main_aux.x_scn.x_scnlen; - } - /* - * Fill in missing information for debugged - * object file only if we have line number info. - */ - if (main_aux.x_scn.x_nlinno > 0) - { - complete_symtab (filestring, cs->c_value, - main_aux.x_scn.x_scnlen); - } - break; - } - else if (strcmp (cs->c_name, _DATA) == 0) - break; - else if (strcmp (cs->c_name, _BSS) == 0) - break; - - /* get rid of assembly labels here */ - /* record_misc_function (cs->c_name, cs->c_value); */ - break; - } - (void) process_coff_symbol (cs, &main_aux); - break; - - case C_FCN: - if (strcmp (cs->c_name, ".bf") == 0) - { - /* value contains address of first non-init type code */ - /* main_aux.x_sym.x_misc.x_lnsz.x_lnno - contains line number of '{' } */ - fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; - } - else if (strcmp (cs->c_name, ".ef") == 0) - { - /* value contains address of exit/return from function */ - /* round it up to next multiple of 16 */ - cs->c_value = (cs->c_value + 15) & -16; - /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno - contains number of lines to '}' */ - fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno; - enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line); - - new = context_stack; - finish_block (new->name, &local_symbols, new->old_blocks, - new->start_addr, cs->c_value); - context_stack = 0; - within_function = 0; - free (new); - } - break; - - case C_BLOCK: - if (strcmp (cs->c_name, ".bb") == 0) - { - new = (struct context_stack *) - xmalloc (sizeof (struct context_stack)); - depth++; - new->depth = depth; - new->next = context_stack; - context_stack = new; - new->locals = local_symbols; - new->old_blocks = pending_blocks; - new->start_addr = cs->c_value; - new->name = 0; - local_symbols = 0; - } - else if (strcmp (cs->c_name, ".eb") == 0) - { - new = context_stack; - if (new == 0 || depth != new->depth) - error ("Invalid symbol data: .bb/.eb symbol mismatch."); - if (local_symbols && context_stack->next) - { - /* Make a block for the local symbols within. */ - finish_block (0, &local_symbols, new->old_blocks, - new->start_addr, cs->c_value); - } - depth--; - local_symbols = new->locals; - context_stack = new->next; - free (new); - } - break; - - default: - (void) process_coff_symbol (cs, &main_aux); - break; - } - } - - if (last_source_file) - end_symtab (); - fclose (stream); - discard_cleanups (old_chain); -} - -/* Routines for reading headers and symbols from executable. */ - -/* Read COFF file header, check magic number, - and return number of symbols. */ -read_file_hdr (chan, file_hdr) - int chan; - FILHDR *file_hdr; -{ - lseek (chan, 0L, 0); - if (myread (chan, (char *)file_hdr, FILHSZ) < 0) - return -1; - - switch (file_hdr->f_magic) - { - case NS32GMAGIC: - case NS32SMAGIC: - return file_hdr->f_nsyms; - - default: - return -1; - } -} - -read_aout_hdr (chan, aout_hdr, size) - int chan; - AOUTHDR *aout_hdr; - int size; -{ - lseek (chan, (long)FILHSZ, 0); - if (size != sizeof (AOUTHDR)) - return -1; - if (myread (chan, (char *)aout_hdr, size) != size) - return -1; - return 0; -} - -read_section_hdr (chan, section_name, section_hdr, nsects) - register int chan; - register char *section_name; - SCNHDR *section_hdr; - register int nsects; -{ - register int i; - - if (lseek (chan, FILHSZ + sizeof (AOUTHDR), 0) < 0) - return -1; - - for (i = 0; i < nsects; i++) - { - if (myread (chan, (char *)section_hdr, SCNHSZ) < 0) - return -1; - if (strncmp (section_hdr->s_name, section_name, 8) == 0) - return 0; - } - return -1; -} - -read_one_sym (cs, sym, aux) - register struct coff_symbol *cs; - register SYMENT *sym; - register AUXENT *aux; -{ - cs->c_symnum = symnum; - fread ((char *)sym, SYMESZ, 1, nlist_stream_global); - cs->c_nsyms = (sym->n_numaux & 0xff) + 1; - if (cs->c_nsyms == 2) - { - /* doc for coff says there is either no aux entry or just one */ - fread ((char *)aux, AUXESZ, 1, nlist_stream_global); - } - else if (cs->c_nsyms > 2) - error ("more than one aux symbol table entry at symnum=%d\n", symnum); - - cs->c_name = getsymname (sym); - cs->c_value = sym->n_value; - cs->c_sclass = (sym->n_sclass & 0xff); - cs->c_secnum = sym->n_scnum; - cs->c_type = (unsigned) sym->n_type; - - symnum += cs->c_nsyms; -} - -/* Support for string table handling */ - -static char *stringtab = NULL; - -static int -init_stringtab (chan, offset) - int chan; - long offset; -{ - long buffer; - int val; - - if (lseek (chan, offset, 0) < 0) - return -1; - - val = myread (chan, (char *)&buffer, sizeof buffer); - if (val != sizeof buffer) - return -1; - - if (stringtab) - free (stringtab); - stringtab = (char *) xmalloc (buffer); - if (stringtab == NULL) - return -1; - - bcopy (&buffer, stringtab, sizeof buffer); - - val = myread (chan, stringtab + sizeof buffer, buffer - sizeof buffer); - if (val != buffer - sizeof buffer || stringtab[buffer - 1] != '\0') - return -1; - - return 0; -} - -static void -free_stringtab () -{ - if (stringtab) - free (stringtab); - stringtab = NULL; -} - -static char * -getsymname (symbol_entry) - SYMENT *symbol_entry; -{ - static char buffer[SYMNMLEN+1]; - char *result; - - if (symbol_entry->n_zeroes == 0) - { - result = stringtab + symbol_entry->n_offset; - } - else - { - strncpy (buffer, symbol_entry->n_name, SYMNMLEN); - buffer[SYMNMLEN] = '\0'; - result = buffer; - } - return result; -} - -static char * -getfilename (aux_entry) - AUXENT *aux_entry; -{ - static char buffer[BUFSIZ]; - register char *temp; - char *result; - extern char *rindex (); - - if (aux_entry->x_file.x_foff != 0) - strcpy (buffer, stringtab + aux_entry->x_file.x_foff); - else - { - strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN); - buffer[FILNMLEN] = '\0'; - } - result = buffer; - if ((temp = rindex (result, '/')) != NULL) - result = temp + 1; - return (result); -} - -/* Support for line number handling */ -static char *linetab = NULL; -static long linetab_offset; -static int linetab_count; - -static int -init_lineno (chan, offset, count) - int chan; - long offset; - int count; -{ - int val; - - if (lseek (chan, offset, 0) < 0) - return -1; - - if (linetab) - free (linetab); - linetab = (char *) xmalloc (count * LINESZ); - - val = myread (chan, linetab, count * LINESZ); - if (val != count * LINESZ) - return -1; - - linetab_offset = offset; - linetab_count = count; - return 0; -} - -static void -enter_linenos (file_offset, first_line, last_line) - long file_offset; - register int first_line; - register int last_line; -{ - register char *rawptr = &linetab[file_offset - linetab_offset]; - register struct lineno *lptr; - - /* skip first line entry for each function */ - rawptr += LINESZ; - /* line numbers start at one for the first line of the function */ - first_line--; - - for (lptr = (struct lineno *)rawptr; - lptr->l_lnno && lptr->l_lnno <= last_line; - rawptr += LINESZ, lptr = (struct lineno *)rawptr) - { - record_line (first_line + lptr->l_lnno, lptr->l_addr.l_paddr); - } -} - -static int -hashname (name) - char *name; -{ - register char *p = name; - register int total = p[0]; - register int c; - - c = p[1]; - total += c << 2; - if (c) - { - c = p[2]; - total += c << 4; - if (c) - total += p[3] << 6; - } - - return total % HASHSIZE; -} - -static void -patch_type (type, real_type) - struct type *type; - struct type *real_type; -{ - register struct type *target = TYPE_TARGET_TYPE (type); - register struct type *real_target = TYPE_TARGET_TYPE (real_type); - int field_size = TYPE_NFIELDS (real_target) * sizeof (struct field); - - TYPE_LENGTH (target) = TYPE_LENGTH (real_target); - TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target); - TYPE_FIELDS (target) = (struct field *) - obstack_alloc (symbol_obstack, field_size); - - bcopy (TYPE_FIELDS (real_target), TYPE_FIELDS (target), field_size); - - if (TYPE_NAME (real_target)) - { - if (TYPE_NAME (target)) - free (TYPE_NAME (target)); - TYPE_NAME (target) = concat (TYPE_NAME (real_target), "", ""); - } -} - -/* Patch up all appropriate typdef symbols in the opaque_type_chains - so that they can be used to print out opaque data structures properly */ - -static void -patch_opaque_types () -{ - struct symtab *s; - - /* Look at each symbol in the per-file block of each symtab. */ - for (s = symtab_list; s; s = s->next) - { - register struct block *b; - register int i; - - /* Go through the per-file symbols only */ - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1); - for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--) - { - register struct symbol *real_sym; - - /* Find completed typedefs to use to fix opaque ones. - Remove syms from the chain when their types are stored, - but search the whole chain, as there may be several syms - from different files with the same name. */ - real_sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF && - SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE && - TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR && - TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0) - { - register char *name = SYMBOL_NAME (real_sym); - register int hash = hashname (name); - register struct symbol *sym, *prev; - - prev = 0; - for (sym = opaque_type_chain[hash]; sym;) - { - if (name[0] == SYMBOL_NAME (sym)[0] && - !strcmp (name + 1, SYMBOL_NAME (sym) + 1)) - { - if (prev) - SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); - else - opaque_type_chain[hash] - = (struct symbol *) SYMBOL_VALUE (sym); - - patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym)); - - if (prev) - sym = (struct symbol *) SYMBOL_VALUE (prev); - else - sym = opaque_type_chain[hash]; - } - else - { - prev = sym; - sym = (struct symbol *) SYMBOL_VALUE (sym); - } - } - } - } - } -} - -static struct symbol * -process_coff_symbol (cs, aux) - register struct coff_symbol *cs; - register AUXENT *aux; -{ - register struct symbol *sym - = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol)); - char *name; - char *dot; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - bzero (sym, sizeof (struct symbol)); - name = cs->c_name; - name = (name[0] == '_' ? name + offset : name); - SYMBOL_NAME (sym) = obstack_copy0 (symbol_obstack, name, strlen (name)); - - /* default assumptions */ - SYMBOL_VALUE (sym) = cs->c_value; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - - if (ISFCN (cs->c_type)) - { - SYMBOL_TYPE (sym) - = lookup_function_type (decode_function_type (cs, cs->c_type, aux)); - SYMBOL_CLASS (sym) = LOC_BLOCK; - if (cs->c_sclass == C_STAT) - add_symbol_to_list (sym, &file_symbols); - else if (cs->c_sclass == C_EXT) - add_symbol_to_list (sym, &global_symbols); - } - else - { - SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux); - switch (cs->c_sclass) - { - case C_NULL: - break; - - case C_AUTO: - SYMBOL_CLASS (sym) = LOC_LOCAL; - add_symbol_to_list (sym, &local_symbols); - break; - - case C_EXT: - SYMBOL_CLASS (sym) = LOC_STATIC; - add_symbol_to_list (sym, &global_symbols); - break; - - case C_STAT: - SYMBOL_CLASS (sym) = LOC_STATIC; - if (within_function) { - /* Static symbol of local scope */ - add_symbol_to_list (sym, &local_symbols); - } - else { - /* Static symbol at top level of file */ - add_symbol_to_list (sym, &file_symbols); - } - break; - - case C_REG: - case C_REGPARM: - SYMBOL_CLASS (sym) = LOC_REGISTER; - add_symbol_to_list (sym, &local_symbols); - break; - - case C_LABEL: - break; - - case C_ARG: - SYMBOL_CLASS (sym) = LOC_ARG; - add_symbol_to_list (sym, &local_symbols); - /* If PCC says a parameter is a short or a char, - it is really an int. */ - if (SYMBOL_TYPE (sym) == builtin_type_char - || SYMBOL_TYPE (sym) == builtin_type_short) - SYMBOL_TYPE (sym) = builtin_type_int; - else if (SYMBOL_TYPE (sym) == builtin_type_unsigned_char - || SYMBOL_TYPE (sym) == builtin_type_unsigned_short) - SYMBOL_TYPE (sym) = builtin_type_unsigned_int; - break; - - case C_TPDEF: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - - /* If type has no name, give it one */ - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = concat (SYMBOL_NAME (sym), "", ""); - - /* Keep track of any type which points to empty structured type, - so it can be filled from a definition from another file */ - if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR && - TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0) - { - register int i = hashname (SYMBOL_NAME (sym)); - - SYMBOL_VALUE (sym) = (int) opaque_type_chain[i]; - opaque_type_chain[i] = sym; - } - add_symbol_to_list (sym, &file_symbols); - break; - - case C_STRTAG: - case C_UNTAG: - case C_ENTAG: - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 - && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) - = concat ("", - (cs->c_sclass == C_ENTAG - ? "enum " - : (cs->c_sclass == C_STRTAG - ? "struct " : "union ")), - SYMBOL_NAME (sym)); - add_symbol_to_list (sym, &file_symbols); - break; - - default: - break; - } - } - return sym; -} - -/* Decode a coff type specifier; - return the type that is meant. */ - -static -struct type * -decode_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - register struct type *type = 0; - register int n; - unsigned int new_c_type; - - if (c_type & ~N_BTMASK) - { - new_c_type = DECREF (c_type); - if (ISPTR (c_type)) - { - type = decode_type (cs, new_c_type, aux); - type = lookup_pointer_type (type); - } - else if (ISFCN (c_type)) - { - type = decode_type (cs, new_c_type, aux); - type = lookup_function_type (type); - } - else if (ISARY (c_type)) - { - int i, n; - register unsigned short *dim; - struct type *base_type; - - /* Define an array type. */ - /* auxent refers to array, not base type */ - if (aux->x_sym.x_tagndx == 0) - cs->c_nsyms = 1; - - /* shift the indices down */ - dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0]; - i = 1; - n = dim[0]; - for (i = 0; *dim && i < DIMNUM - 1; i++, dim++) - *dim = *(dim + 1); - *dim = 0; - - type = (struct type *) - obstack_alloc (symbol_obstack, sizeof (struct type)); - bzero (type, sizeof (struct type)); - - base_type = decode_type (cs, new_c_type, aux); - - TYPE_CODE (type) = TYPE_CODE_ARRAY; - TYPE_TARGET_TYPE (type) = base_type; - TYPE_LENGTH (type) = n * TYPE_LENGTH (base_type); - } - return type; - } - - /* Reference to existing type */ - if (cs->c_nsyms > 1 && aux->x_sym.x_tagndx != 0) - { - type = coff_alloc_type (aux->x_sym.x_tagndx); - return type; - } - - return decode_base_type (cs, BTYPE (c_type), aux); -} - -/* Decode a coff type specifier for function definition; - return the type that the function returns. */ - -static -struct type * -decode_function_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - if (aux->x_sym.x_tagndx == 0) - cs->c_nsyms = 1; /* auxent refers to function, not base type */ - - return decode_type (cs, DECREF (cs->c_type), aux); -} - -/* basic C types */ - -static -struct type * -decode_base_type (cs, c_type, aux) - register struct coff_symbol *cs; - unsigned int c_type; - register AUXENT *aux; -{ - struct type *type; - - switch (c_type) - { - case T_NULL: - /* shouldn't show up here */ - break; - - case T_ARG: - /* shouldn't show up here */ - break; - - case T_CHAR: - return builtin_type_char; - - case T_SHORT: - return builtin_type_short; - - case T_INT: - return builtin_type_int; - - case T_LONG: - return builtin_type_long; - - case T_FLOAT: - return builtin_type_float; - - case T_DOUBLE: - return builtin_type_double; - - case T_STRUCT: - if (cs->c_nsyms != 2) - { - /* anonymous structure type */ - type = coff_alloc_type (cs->c_symnum); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - TYPE_NAME (type) = concat ("struct ", "", ""); - TYPE_LENGTH (type) = 0; - TYPE_FIELDS (type) = 0; - TYPE_NFIELDS (type) = 0; - } - else - { - type = read_struct_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - } - return type; - - case T_UNION: - if (cs->c_nsyms != 2) - { - /* anonymous union type */ - type = coff_alloc_type (cs->c_symnum); - TYPE_NAME (type) = concat ("union ", "", ""); - TYPE_LENGTH (type) = 0; - TYPE_FIELDS (type) = 0; - TYPE_NFIELDS (type) = 0; - } - else - { - type = read_struct_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - } - TYPE_CODE (type) = TYPE_CODE_UNION; - return type; - - case T_ENUM: - return read_enum_type (cs->c_symnum, - aux->x_sym.x_misc.x_lnsz.x_size, - aux->x_sym.x_fcnary.x_fcn.x_endndx); - - case T_MOE: - /* shouldn't show up here */ - break; - - case T_UCHAR: - return builtin_type_unsigned_char; - - case T_USHORT: - return builtin_type_unsigned_short; - - case T_UINT: - return builtin_type_unsigned_int; - - case T_ULONG: - return builtin_type_unsigned_long; - } - printf ("unexpected type %d at symnum %d\n", c_type, cs->c_symnum); - return builtin_type_void; -} - -/* This page contains subroutines of read_type. */ - -/* Read the description of a structure (or union type) - and return an object describing the type. */ - -static struct type * -read_struct_type (index, length, lastsym) - int index; - int length; - int lastsym; -{ - struct nextfield - { - struct nextfield *next; - struct field field; - }; - - register struct type *type; - register struct nextfield *list = 0; - struct nextfield *new; - int nfields = 0; - register int n; - char *name; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - struct coff_symbol member_sym; - register struct coff_symbol *ms = &member_sym; - SYMENT sub_sym; - AUXENT sub_aux; - - type = coff_alloc_type (index); - TYPE_CODE (type) = TYPE_CODE_STRUCT; - TYPE_LENGTH (type) = length; - - while (symnum < lastsym && symnum < nlist_nsyms_global) - { - read_one_sym (ms, &sub_sym, &sub_aux); - name = ms->c_name; - name = (name[0] == '_' ? name + offset : name); - - switch (ms->c_sclass) - { - case C_MOS: - case C_MOU: - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Save the data. */ - list->field.name = savestring (name, strlen (name)); - list->field.type = decode_type (ms, ms->c_type, &sub_aux); - list->field.bitpos = 8 * ms->c_value; - list->field.bitsize = 0; - nfields++; - break; - - case C_FIELD: - - /* Get space to record the next field's data. */ - new = (struct nextfield *) alloca (sizeof (struct nextfield)); - new->next = list; - list = new; - - /* Save the data. */ - list->field.name = savestring (name, strlen (name)); - list->field.type = decode_type (ms, ms->c_type, &sub_aux); - list->field.bitpos = ms->c_value; - list->field.bitsize = sub_aux.x_sym.x_misc.x_lnsz.x_size; - nfields++; - break; - - case C_EOS: - break; - } - } - /* Now create the vector of fields, and record how big it is. */ - - TYPE_NFIELDS (type) = nfields; - TYPE_FIELDS (type) = (struct field *) - obstack_alloc (symbol_obstack, sizeof (struct field) * nfields); - - /* Copy the saved-up fields into the field vector. */ - - for (n = nfields; list; list = list->next) - TYPE_FIELD (type, --n) = list->field; - - return type; -} - -/* Read a definition of an enumeration type, - and create and return a suitable type object. - Also defines the symbols that represent the values of the type. */ - -static struct type * -read_enum_type (index, length, lastsym) - int index; - int length; - int lastsym; -{ - register struct symbol *sym; - register struct type *type; - int nsyms = 0; - struct pending **symlist; - struct coff_symbol member_sym; - register struct coff_symbol *ms = &member_sym; - SYMENT sub_sym; - AUXENT sub_aux; - struct pending *osyms, *syms; - register int n; - char *name; -#ifdef NAMES_HAVE_UNDERSCORE - int offset = 1; -#else - int offset = 0; -#endif - - type = coff_alloc_type (index); - if (within_function) - symlist = &local_symbols; - else - symlist = &file_symbols; - osyms = *symlist; - - while (symnum < lastsym && symnum < nlist_nsyms_global) - { - read_one_sym (ms, &sub_sym, &sub_aux); - name = ms->c_name; - name = (name[0] == '_' ? name + offset : name); - - switch (ms->c_sclass) - { - case C_MOE: - sym = (struct symbol *) xmalloc (sizeof (struct symbol)); - bzero (sym, sizeof (struct symbol)); - - SYMBOL_NAME (sym) = savestring (name, strlen (name)); - SYMBOL_CLASS (sym) = LOC_CONST; - SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; - SYMBOL_VALUE (sym) = ms->c_value; - add_symbol_to_list (sym, symlist); - nsyms++; - break; - - case C_EOS: - break; - } - } - - /* Now fill in the fields of the type-structure. */ - - TYPE_LENGTH (type) = sizeof (int); - TYPE_CODE (type) = TYPE_CODE_ENUM; - TYPE_NFIELDS (type) = nsyms; - TYPE_FIELDS (type) = (struct field *) - obstack_alloc (symbol_obstack, sizeof (struct field) * nsyms); - - /* Find the symbols for the values and put them into the type. - The symbols can be found in the symlist that we put them on - to cause them to be defined. osyms contains the old value - of that symlist; everything up to there was defined by us. */ - - for (syms = *symlist, n = nsyms; syms != osyms; syms = syms->next) - { - SYMBOL_TYPE (syms->symbol) = type; - TYPE_FIELD_NAME (type, --n) = SYMBOL_NAME (syms->symbol); - TYPE_FIELD_VALUE (type, n) = SYMBOL_VALUE (syms->symbol); - TYPE_FIELD_BITPOS (type, n) = 0; - TYPE_FIELD_BITSIZE (type, n) = 0; - } - return type; -} - -static -initialize () -{ - symfile = 0; - - add_com ("symbol-file", class_files, symbol_file_command, - "Load symbol table (in coff format) from executable file FILE."); -} - -END_FILE - -#endif /* COFF_FORMAT */ - diff --git a/gdb/command.c b/gdb/command.c index 6643ad8d446..acde0e3b216 100644 --- a/gdb/command.c +++ b/gdb/command.c @@ -106,6 +106,10 @@ what you give them. Help stamp out software-hoarding! */ #include "command.h" #include +#ifdef sparc +#include +#endif + extern char *xmalloc (); static char *savestring (); diff --git a/gdb/config.gdb b/gdb/config.gdb old mode 100644 new mode 100755 index 6a8cbff8542..62848f83c89 --- a/gdb/config.gdb +++ b/gdb/config.gdb @@ -61,6 +61,10 @@ case $# in pinsnfile=m68k-pinsn.c opcodefile=m68k-opcode.h ;; + sun4) + pinsnfile=sparc-pinsn.c + opcodefile=sparc-opcode.h + ;; umax) pinsnfile=ns32k-pinsn.c opcodefile=ns32k-opcode.h diff --git a/gdb/config.status b/gdb/config.status new file mode 100644 index 00000000000..dfeb43284be --- /dev/null +++ b/gdb/config.status @@ -0,0 +1 @@ +Links are now set up for use with a sun4. diff --git a/gdb/core.c b/gdb/core.c index e98f6004e0d..85a8d24599f 100644 --- a/gdb/core.c +++ b/gdb/core.c @@ -201,6 +201,7 @@ core_file_command (filename, from_tty) data_offset = sizeof corestr; stack_offset = sizeof corestr + corestr.c_dsize; +#if defined(sun2) || defined(sun3) bcopy (&corestr.c_regs, registers, 16 * 4); *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps; *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc; @@ -210,6 +211,26 @@ core_file_command (filename, from_tty) bcopy (&corestr.c_fpstatus.fps_control, ®isters[REGISTER_BYTE (FPC_REGNUM)], sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs); +#endif +#if defined(sun4) + /* G0 *always* holds 0. */ + *(int *)®isters[REGISTER_BYTE (0)] = 0; + /* The globals and output registers. I don't know where + to get the locals and input registers from the core file. */ + bcopy (&corestr.c_regs.r_g1, registers, 15 * 4); + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps; + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc; + *(int *)®isters[REGISTER_BYTE (NPC_REGNUM)] = corestr.c_regs.r_npc; + *(int *)®isters[REGISTER_BYTE (Y_REGNUM)] = corestr.c_regs.r_y; + bcopy (corestr.c_fpu.fpu_regs, + ®isters[REGISTER_BYTE (FP0_REGNUM)], + sizeof corestr.c_fpu.fpu_regs); +#ifdef FPU + bcopy (&corestr.c_fpu.fpu_fsr, + ®isters[REGISTER_BYTE (FPS_REGNUM)], + sizeof (FPU_FSR_TYPE)); +#endif +#endif bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec)); diff --git a/gdb/dbxread.c b/gdb/dbxread.c index 0ac4ff84552..27ffcc1f347 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -1,5 +1,6 @@ /* Read dbx symbol tables and convert to internal format, for GDB. Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Hacked by Michael Tiemann (tiemann@mcc.com) GDB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone @@ -51,6 +52,9 @@ static void hash_symsegs (); extern struct symtab *read_symsegs (); extern void free_all_symtabs (); +/* C++ */ +static struct type **read_args (); + /* Macro for number of symbol table entries (in usual a.out format). Some machines override this definition. */ #ifndef NUMBER_OF_SYMBOLS @@ -561,6 +565,8 @@ dbx_alloc_type (typenums) type = (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type)); bzero (type, sizeof (struct type)); + TYPE_VPTR_FIELDNO (type) = -1; + TYPE_MAIN_VARIANT (type) = type; *type_addr = type; } return type; @@ -1197,6 +1203,7 @@ sort_syms () if (BLOCK_SHOULD_SORT (b)) qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b), sizeof (struct symbol *), compare_symbols); +#if 0 else { int lastindex = BLOCK_NSYMS (b) - 1; @@ -1209,6 +1216,7 @@ sort_syms () BLOCK_SYM (b, lastindex - j) = sym; } } +#endif } } } @@ -1667,7 +1675,14 @@ process_one_symbol (type, desc, value, name) if (type == N_ENTRY) /* This code appears in libraries on Gould machines. */ return; - error ("Invalid symbol data: does not start by identifying a source file."); + + if (type == N_SLINE && desc == -1) + /* This code is used by the Sun4 coimpiler; ignore it. */ + return; + + /* This should give an aborting error. */ + printf ("Invalid symbol data: does not start by identifying a source file.\ntype == %d\n\n", type); + return; } switch (type) @@ -1678,7 +1693,7 @@ process_one_symbol (type, desc, value, name) a new function. We must process its "name" normally for dbx, but also record the start of a new lexical context, and possibly also the end of the lexical context for the previous function. */ - + within_function = 1; if (context_stack_depth > 0) { @@ -1806,6 +1821,316 @@ process_one_symbol (type, desc, value, name) } } +/************************ READ_ADDL_SYM() ***********************************/ + +static void +read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) + int desc; + register char *stringtab; + register int nlistlen; + unsigned text_addr; + int text_size; +{ + FILE *stream = fdopen (desc, "r"); + register char *namestring; + register struct symbol *sym, *prev; + int hash; + int num_object_files = 0; + +#ifdef N_BINCL + subfile_stack = 0; +#endif + + last_source_file = 0; + bzero (global_sym_chain, sizeof global_sym_chain); + symtab_input_desc = desc; + stringtab_global = stringtab; + fill_symbuf (); + + for (symnum = 0; symnum < nlistlen; symnum++) + { + struct nlist *bufp; + int type; + + QUIT; /* allow this to be interruptable */ + if (symbuf_idx == symbuf_end) + fill_symbuf (); + bufp = &symbuf[symbuf_idx++]; + type = bufp->n_type & N_TYPE; + namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : ""; + + if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) ) + { + /* Relocate this file's symbol table information + to the address it has been loaded into. */ + bufp->n_value += text_addr; + } + + type = bufp->n_type; + + if (type & N_STAB) + process_one_symbol (type, bufp->n_desc, + bufp->n_value, namestring); + /* A static text symbol whose name ends in ".o" + can only mean the start of another object file. + So end the symtab of the source file we have been processing. + This is how we avoid counting the libraries as part + or the last source file. + Also this way we find end of first object file (crt0). */ + else if ((type == N_TEXT +#ifdef N_NBTEXT + || type == N_NBTEXT +#endif + ) + && (!strcmp (namestring + strlen (namestring) - 2, ".o")) + || ! strcmp (namestring, "-l", 2)) + { + if (num_object_files++ == 1) + first_object_file_end = bufp->n_value; + if (last_source_file) + end_symtab (bufp->n_value); + } + else if (type & N_EXT || type == N_TEXT +#ifdef N_NBTEXT + || type == N_NBTEXT +#endif + ) + { + int used_up = 0; + + /* Record the location of _etext. */ + if (type == (N_TEXT | N_EXT) + && !strcmp (namestring, "_etext")) + end_of_text_addr = bufp->n_value; + + /* Global symbol: see if we came across a dbx definition + for a corresponding symbol. If so, store the value. + Remove syms from the chain when their values are stored, + but search the whole chain, as there may be several syms + from different files with the same name. */ + if (type & N_EXT) + { + prev = 0; +#ifdef NAMES_HAVE_UNDERSCORE + hash = hashname (namestring + 1); +#else /* not NAMES_HAVE_UNDERSCORE */ + hash = hashname (namestring); +#endif /* not NAMES_HAVE_UNDERSCORE */ + for (sym = global_sym_chain[hash]; + sym;) + { + if ( +#ifdef NAMES_HAVE_UNDERSCORE + *namestring == '_' + && namestring[1] == SYMBOL_NAME (sym)[0] + && + !strcmp (namestring + 2, SYMBOL_NAME (sym) + 1) +#else /* NAMES_HAVE_UNDERSCORE */ + namestring[0] == SYMBOL_NAME (sym)[0] + && + !strcmp (namestring + 1, SYMBOL_NAME (sym) + 1) +#endif /* NAMES_HAVE_UNDERSCORE */ + ) + { + if (prev) + SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); + else + global_sym_chain[hash] + = (struct symbol *) SYMBOL_VALUE (sym); + SYMBOL_VALUE (sym) = bufp->n_value; + if (prev) + sym = (struct symbol *) SYMBOL_VALUE (prev); + else + sym = global_sym_chain[hash]; + + used_up = 1; + } + else + { + prev = sym; + sym = (struct symbol *) SYMBOL_VALUE (sym); + } + } + } + + /* Defined global or text symbol: record as a misc function + if it didn't give its address to a debugger symbol above. */ + if (type <= (N_TYPE | N_EXT) + && type != N_EXT + && ! used_up) + record_misc_function (namestring, bufp->n_value); + } + } + + if (last_source_file) + end_symtab (text_addr + text_size); + + fclose (stream); +} + +/***************************** CONDENSE_ADDL_MISC_BUNCHES *******************/ + +static void +condense_addl_misc_bunches () +{ + register int i, j; + register struct misc_bunch *bunch; +#ifdef NAMES_HAVE_UNDERSCORE + int offset = 1; +#else + int offset = 0; +#endif + + misc_function_vector + = (struct misc_function *) xrealloc (misc_function_vector, + (misc_count + misc_function_count) * sizeof (struct misc_function)); + + j = misc_function_count; + bunch = misc_bunch; + while (bunch) + { + for (i = 0; i < misc_bunch_index; i++) + { + misc_function_vector[j] = bunch->contents[i]; + misc_function_vector[j].name + = concat (misc_function_vector[j].name + + (misc_function_vector[j].name[0] == '_' ? offset : 0), + "", ""); + j++; + } + bunch = bunch->next; + misc_bunch_index = MISC_BUNCH_SIZE; + } + + misc_function_count += misc_count; + + /* Sort the misc functions by address. */ + + qsort (misc_function_vector, misc_function_count, + sizeof (struct misc_function), compare_misc_functions); +} + +/**************************** ADD_FILE_COMMAND() ****************************/ +/* This function allows the addition of incrementally linked object files. */ + +void +add_file_command (arg_string) + char* arg_string; +{ + register int desc; + struct exec hdr; + struct nlist *nlist; + char *stringtab; + long buffer; + register int val; + extern void close (); + struct cleanup *old_chain; + char* name; + unsigned text_addr; + + if (arg_string == 0) + error ("add-file takes a file name and an address"); + + for( ; *arg_string == ' '; arg_string++ ); + name = arg_string; + for( ; *arg_string && *arg_string != ' ' ; arg_string++ ); + *arg_string++ = (char) 0; + + if (name[0] == 0) + error ("add-file takes a file name and an address"); + + text_addr = parse_and_eval_address (arg_string); + + dont_repeat (); + + if (query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", name, text_addr)) + { + desc = open (name, O_RDONLY); + if (desc < 0) + perror_with_name (name); + + old_chain = make_cleanup (close, desc); + make_cleanup (free_current_contents, &name); + + val = myread (desc, &hdr, sizeof hdr); + if (val < 0) + perror_with_name (name); + + if (N_BADMAG (hdr)) + error ("File \"%s\" has a bad header.", name); + + if (hdr.a_syms == 0) + { + printf ("%s does not have a symbol-table.\n", name); + fflush (stdout); + return; + } + + /* Now read the string table, all at once. */ + val = lseek (desc, N_SYMOFF (hdr) + hdr.a_syms, 0); + if (val < 0) + perror_with_name (name); + val = myread (desc, &buffer, sizeof buffer); + if (val < 0) + perror_with_name (name); + stringtab = (char *) alloca (buffer); + bcopy (&buffer, stringtab, sizeof buffer); + val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); + if (val < 0) + perror_with_name (name); + + /* That puts us at the symsegs. Read them. ########## Also need other + changes if they exist. */ + + /* Position to read the symbol table. Do not read it all at once. */ + val = lseek (desc, N_SYMOFF (hdr), 0); + if (val < 0) + perror_with_name (name); + + printf ("Reading symbol data from %s...", name); + fflush (stdout); + + init_misc_functions (); + make_cleanup (discard_misc_bunches, 0); + init_header_files (); + make_cleanup (free_header_files, 0); + + read_addl_syms (desc, stringtab, hdr.a_syms / sizeof(struct nlist), + text_addr, hdr.a_text) ; + + /* Sort symbols alphabetically within each block. */ + + sort_syms (); + + /* Go over the all misc functions and install them in vector. */ + + condense_addl_misc_bunches (); + + /* Don't allow char * to have a typename (else would get caddr_t.) */ + + TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; + + /* Make a default for file to list. */ + + select_source_symtab (symtab_list); + + do_cleanups (old_chain); + + /* Free the symtabs made by read_symsegs, but not their contents, + which have been copied into symtabs on symtab_list. */ + while (symseg_chain) + { + register struct symtab *s = symseg_chain->next; + free (symseg_chain); + symseg_chain = s; + } + + printf ("done.\n"); + fflush (stdout); + } + else error ("Not confirmed."); +} + static struct symbol * define_symbol (value, string, desc) int value; @@ -1955,6 +2280,13 @@ define_symbol (value, string, desc) SYMBOL_TYPE (sym) = builtin_type_unsigned_int; break; + case 'P': + SYMBOL_CLASS (sym) = LOC_REGPARM; + SYMBOL_VALUE (sym) = value; + SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; + add_symbol_to_list (sym, &local_symbols); + break; + case 'r': SYMBOL_CLASS (sym) = LOC_REGISTER; SYMBOL_VALUE (sym) = value; @@ -1979,6 +2311,20 @@ define_symbol (value, string, desc) TYPE_NAME (SYMBOL_TYPE (sym)) = obsavestring (SYMBOL_NAME (sym), strlen (SYMBOL_NAME (sym))); + /* C++ vagaries: we may have a type which is derived from + a base type which did not have its name defined when the + derived class was output. We fill in the derived class's + base part member's name here in that case. */ + else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT + || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION) + && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym))) + { + int i; + for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--) + if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) == 0) + TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) = TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i)); + } + add_symbol_to_list (sym, &file_symbols); break; @@ -2082,7 +2428,11 @@ read_type (pp) break; } /* Skip the name the cross-ref points to. */ - *pp = (char *) index (*pp, ','); + /* Note: for C++, the cross reference may be to a base type which + has not yet been seen. In this case, we skip to the comma, + which will mark the end of the base class name. (The ':' + at the end of the base class name will be skipped as well.) */ + *pp = (char *) index (*pp, ':') + 1; /* Just allocate the type and leave it zero if nothing known */ return dbx_alloc_type (typenums); @@ -2110,6 +2460,27 @@ read_type (pp) smash_to_pointer_type (type, read_type (pp)); break; + case '@': + { + struct type *domain = read_type (pp); + char c; + struct type *memtype; + + if (*(*pp)++ != ',') + error ("invalid member type data format, at symtab pos %d.", + symnum); + + memtype = read_type (pp); + type = dbx_alloc_type (typenums); + smash_to_member_type (type, domain, memtype); + } + break; + + case '&': + type = dbx_alloc_type (typenums); + smash_to_reference_type (type, read_type (pp)); + break; + case 'f': type = dbx_alloc_type (typenums); smash_to_function_type (type, read_type (pp)); @@ -2203,9 +2574,23 @@ read_struct_type (pp, type) struct nextfield { struct nextfield *next; + int visibility; struct field field; }; + struct next_fnfield + { + struct next_fnfield *next; + int visibility; + struct fn_field fn_field; + }; + + struct next_fnfieldlist + { + struct next_fnfieldlist *next; + struct fn_fieldlist fn_fieldlist; + }; + register struct nextfield *list = 0; struct nextfield *new; int totalsize; @@ -2214,20 +2599,95 @@ read_struct_type (pp, type) int nfields = 0; register int n; + register struct next_fnfieldlist *mainlist = 0; + int nfn_fields = 0; + struct type *baseclass = NULL; + int read_possible_virtual_info = 0; + TYPE_CODE (type) = TYPE_CODE_STRUCT; /* First comes the total size in bytes. */ TYPE_LENGTH (type) = read_number (pp, 0); - /* Now come the fields, as NAME:TYPENUM,BITPOS,BITSIZE; for each one. - At the end, we see a semicolon instead of a field. */ + /* C++: Now, if the class is a derived class, then the next character + will be a '!', followed by the number of base classes derived from. + Each element in the list contains visibility information, + the offset of this base class in the derived structure, + and then the base type. */ + if (**pp == '!') + { + int i, n_baseclasses, offset; + struct type **baseclass_vec; + struct type *baseclass; + int via_public, via_virtual; + *pp += 1; + + n_baseclasses = read_number (pp, ','); + baseclass_vec = (struct type **) + obstack_alloc (symbol_obstack, + (n_baseclasses) * sizeof (struct type **)) - 1; + for (i = 1; i <= n_baseclasses; i++) + { + if (**pp == '\\') *pp = next_symbol_text (); + switch (*(*pp)++) + { + case '0': + via_virtual = 0; + break; + case '1': + via_virtual = 1; + break; + default: + error ("Invalid symbol data: bad visibility format at symtab pos %d.", + symnum); + } + switch (*(*pp)++) + { + case '0': + via_public = 0; + break; + case '2': + via_public = 1; + break; + default: + error ("Invalid symbol data: bad visibility format at symtab pos %d.", + symnum); + } + offset = read_number (pp, ','); + baseclass = read_type (pp); + *pp += 1; /* skip trailing ';' */ + baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public); + + /* Make this baseclass visible for structure-printing purposes. */ + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + list->field.type = baseclass_vec[i]; + list->field.name = TYPE_NAME (baseclass_vec[i]); + list->field.bitpos = offset; + list->field.bitsize = 0; /* this should be an unpacked field! */ + nfields++; + } + TYPE_N_BASECLASSES (type) = n_baseclasses; + TYPE_BASECLASSES (type) = baseclass_vec; + } + + /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one. + At the end, we see a semicolon instead of a field. + + In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for + a static field. + + The `?' is a placeholder for one of '+' (public visibility), + '0' (protected visibility), and '-' (private visibility). */ while (**pp != ';') { + int visibility; + /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') - *pp = next_symbol_text (); + if (**pp == '\\') *pp = next_symbol_text (); /* Get space to record the next field's data. */ new = (struct nextfield *) alloca (sizeof (struct nextfield)); @@ -2238,9 +2698,49 @@ read_struct_type (pp, type) p = *pp; while (*p != ':') p++; list->field.name = obsavestring (*pp, p - *pp); + + /* C++: Check to see if we have hit the methods yet. */ + if (p[1] == ':') + break; + *pp = p + 1; + + /* This means we have a visibility for a field coming. */ + if (**pp == '/') + { + switch (*++*pp) + { + case '0': + visibility = 0; + *pp += 1; + break; + + case '1': + visibility = 1; + *pp += 1; + break; + + case '2': + visibility = 2; + *pp += 1; + break; + } + } + /* else normal dbx-style format. */ + list->field.type = read_type (pp); - if (**pp != ',') + if (**pp == ':') + { + /* read a static member. */ + list->field.bitpos = (long)-1; + p = ++(*pp); + while (*p != ';') p++; + list->field.bitsize = (long) savestring (*pp, p - *pp); + *pp = p + 1; + nfields++; + continue; + } + else if (**pp != ',') error ("Invalid symbol data: bad structure-type format at symtab pos %d.", symnum); (*pp)++; /* Skip the comma. */ @@ -2262,18 +2762,216 @@ read_struct_type (pp, type) nfields++; } - (*pp)++; /* Skip the terminating ';'. */ + /* Now come the method fields, as NAME::methods + where each method is of the form TYPENUM,ARGS,...:PHYSNAME; + At the end, we see a semicolon instead of a field. + + For the case of overloaded operators, the format is + OPERATOR::*.methods, where OPERATOR is the string "operator", + `*' holds the place for an operator name (such as `+=') + and `.' marks the end of the operator name. */ + if (p[1] == ':') + { + /* Now, read in the methods. To simplify matters, we + "unread" the name that has been read, so that we can + start from the top. */ + + p = *pp; + + /* chill the list of fields: the last entry (at the head) + is a partially constructed entry which we now scrub. */ + list = list->next; + + /* For each list of method lists... */ + do + { + int i; + struct next_fnfield *sublist = 0; + struct fn_field *fn_fields = 0; + int length = 0; + struct next_fnfieldlist *new_mainlist = + (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist)); + + /* read in the name. */ + while (*p != ':') p++; + if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$') + { + static char opname[32] = "operator "; + char *o = opname + 9; + + /* Skip past '::'. */ + p += 2; + while (*p != '.') + *o++ = *p++; + new_mainlist->fn_fieldlist.name = savestring (opname, o - opname); + /* Skip past '.' */ + *pp = p + 1; + } + else + { + i = 0; + new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp); + /* Skip past '::'. */ + *pp = p + 2; + } + + do + { + struct next_fnfield *new_sublist = + (struct next_fnfield *)alloca (sizeof (struct next_fnfield)); + + /* Check for and handle cretinous dbx symbol name continuation! */ + if (**pp == '\\') *pp = next_symbol_text (); + + new_sublist->fn_field.type = read_type (pp); + new_sublist->fn_field.args = read_args (pp, ':'); + p = *pp; + while (*p != ';') p++; + new_sublist->fn_field.physname = savestring (*pp, p - *pp); + *pp = p + 1; + new_sublist->visibility = *(*pp)++ - '0'; + if (**pp == '\\') *pp = next_symbol_text (); + + if (*(*pp)++ == '*') + new_sublist->fn_field.voffset = read_number (pp, ';') + 1; + else + new_sublist->fn_field.voffset = 0; + + new_sublist->next = sublist; + sublist = new_sublist; + length++; + } + while (**pp != ';'); + + *pp += 1; + + new_mainlist->fn_fieldlist.fn_fields = + (struct fn_field *) obstack_alloc (symbol_obstack, + sizeof (struct fn_field) * length); + TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (length >> 5))); + + TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (length >> 5))); + + for (i = length; sublist; sublist = sublist->next) + { + new_mainlist->fn_fieldlist.fn_fields[--i] = sublist->fn_field; + if (sublist->visibility == 0) + B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i); + else if (sublist->visibility == 1) + B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i); + } + + new_mainlist->fn_fieldlist.length = length; + new_mainlist->next = mainlist; + mainlist = new_mainlist; + nfn_fields++; + } + while (**pp != ';'); + } + *pp += 1; /* Now create the vector of fields, and record how big it is. */ TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nfields); + TYPE_FIELD_PRIVATE_BITS (type) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (nfields >> 5))); + TYPE_FIELD_PROTECTED_BITS (type) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (nfields >> 5))); + + TYPE_NFN_FIELDS (type) = nfn_fields; + TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields; + if (baseclass) + TYPE_NFN_FIELDS_TOTAL (type) += TYPE_NFN_FIELDS_TOTAL (baseclass); + + TYPE_FN_FIELDLISTS (type) = + (struct fn_fieldlist *) obstack_alloc (symbol_obstack, + sizeof (struct fn_fieldlist) * nfn_fields); /* Copy the saved-up fields into the field vector. */ for (n = nfields; list; list = list->next) - TYPE_FIELD (type, --n) = list->field; + { + TYPE_FIELD (type, --n) = list->field; + if (list->visibility == 0) + SET_TYPE_FIELD_PRIVATE (type, n); + else if (list->visibility == 1) + SET_TYPE_FIELD_PROTECTED (type, n); + } + + for (n = nfn_fields; mainlist; mainlist = mainlist->next) + TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist; + + if (**pp == '~') + { + *pp += 1; + + if (**pp == '=') + { + TYPE_FLAGS (type) + |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR; + *pp += 1; + } + else if (**pp == '+') + { + TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR; + *pp += 1; + } + else if (**pp == '-') + { + TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR; + *pp += 1; + } + + /* Read either a '%' or the final ';'. */ + if (*(*pp)++ == '%') + { + /* Now we must record the virtual function table pointer's + field information. */ + + struct type *t; + int i; + + t = read_type (pp); + p = (*pp)++; + while (*p != ';') p++; + TYPE_VPTR_BASETYPE (type) = t; + if (type == t) + { + if (TYPE_FIELD_NAME (t, 0) == 0) + TYPE_VPTR_FIELDNO (type) = i = 0; + else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i) + if (! strncmp (TYPE_FIELD_NAME (t, i), *pp, + strlen (TYPE_FIELD_NAME (t, i)))) + { + TYPE_VPTR_FIELDNO (type) = i; + break; + } + if (i < 0) + error ("virtual function table field not found"); + } + else + TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, 1)); + *pp = p + 1; + } + else + { + TYPE_VPTR_BASETYPE (type) = 0; + TYPE_VPTR_FIELDNO (type) = -1; + } + } + else + { + TYPE_VPTR_BASETYPE (type) = 0; + TYPE_VPTR_FIELDNO (type) = -1; + } return type; } @@ -2309,8 +3007,7 @@ read_enum_type (pp, type) while (**pp && **pp != ';') { /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') - *pp = next_symbol_text (); + if (**pp == '\\') *pp = next_symbol_text (); p = *pp; while (*p != ':') p++; @@ -2492,6 +3189,57 @@ read_number (pp, end) return n * sign; } +/* Read in an argument list. This is a list of types. It is terminated with + a ':', FYI. Return the list of types read in. */ +static struct type ** +read_args (pp, end) + char **pp; + int end; +{ + struct type *types[1024], **rval; /* allow for fns of 1023 parameters */ + int n = 0; + + while (**pp != end) + { + if (**pp != ',') + error ("Invalid argument list: no ',', at symtab pos %d", symnum); + *pp += 1; + /* Check for and handle cretinous dbx symbol name continuation! */ + if (**pp == '\\') + *pp = next_symbol_text (); + + types[n++] = read_type (pp); + } + *pp += 1; /* get past `end' (the ':' character) */ + + if (n == 1) + { + rval = (struct type **) xmalloc (2 * sizeof (struct type *)); + } + else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID) + { + rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *)); + bzero (rval + n, sizeof (struct type *)); + } + else + { + rval = (struct type **) xmalloc (n * sizeof (struct type *)); + } + bcopy (types, rval, n * sizeof (struct type *)); + return rval; +} + +/* This function is really horrible, but to avoid it, there would need + to be more filling in of forward references. */ +int +fill_in_vptr_fieldno (type) + struct type *type; +{ + if (TYPE_VPTR_FIELDNO (type) < 0) + TYPE_VPTR_FIELDNO (type) = fill_in_vptr_fieldno (TYPE_BASECLASS (type, 1)); + return TYPE_VPTR_FIELDNO (type); +} + static initialize () { @@ -2499,6 +3247,9 @@ initialize () add_com ("symbol-file", class_files, symbol_file_command, "Load symbol table (in dbx format) from executable file FILE."); + + add_com ("add-file", class_files, add_file_command, + "Load the symbols from FILE, assuming its codes is at TEXT_START.") ; } END_FILE diff --git a/gdb/defs.h b/gdb/defs.h index 555f440ee18..d5653ec3249 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -26,7 +26,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! extern char *savestring (); extern char *concat (); extern char *xmalloc (), *xrealloc (); -extern char *alloca (); extern int parse_escape (); extern char *reg_names[]; @@ -78,3 +77,7 @@ struct command_line *read_command_lines (); /* String containing the current directory (what getwd would return). */ char *current_directory; + +#ifdef sparc +#include +#endif diff --git a/gdb/eval.c b/gdb/eval.c index d174c18420a..5dcd9936c4e 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -114,7 +114,7 @@ evaluate_expression (exp) struct expression *exp; { int pc = 0; - return evaluate_subexp (exp, &pc, EVAL_NORMAL); + return evaluate_subexp (0, exp, &pc, EVAL_NORMAL); } /* Evaluate an expression, avoiding all memory references @@ -125,19 +125,20 @@ evaluate_type (exp) struct expression *exp; { int pc = 0; - return evaluate_subexp (exp, &pc, EVAL_AVOID_SIDE_EFFECTS); + return evaluate_subexp (0, exp, &pc, EVAL_AVOID_SIDE_EFFECTS); } static value -evaluate_subexp (exp, pos, noside) +evaluate_subexp (expect_type, exp, pos, noside) + struct type *expect_type; register struct expression *exp; register int *pos; enum noside noside; { enum exp_opcode op; int tem; - register int pc; - register value arg1, arg2; + register int pc, pc2, *oldpos; + register value arg1, arg2, arg3; int nargs; value *argvec; @@ -146,6 +147,12 @@ evaluate_subexp (exp, pos, noside) switch (op) { + case OP_SCOPE: + tem = strlen (&exp->elts[pc + 2].string); + (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + return value_static_field (exp->elts[pc + 1].type, + &exp->elts[pc + 2].string, -1); + case OP_LONG: (*pos) += 3; return value_from_long (exp->elts[pc + 1].type, @@ -176,13 +183,131 @@ evaluate_subexp (exp, pos, noside) case OP_FUNCALL: (*pos) += 2; - nargs = exp->elts[pc + 1].longconst; - argvec = (value *) alloca (sizeof (value) * (nargs + 1)); - for (tem = 0; tem <= nargs; tem++) - + op = exp->elts[*pos].opcode; + if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) + { + int fnptr; + int tem2; + + nargs = exp->elts[pc + 1].longconst + 1; + /* First, evaluate the structure into arg2 */ + pc2 = (*pos)++; + + if (noside == EVAL_SKIP) + goto nosideret; + + if (op == STRUCTOP_MEMBER) + { + arg2 = evaluate_subexp_for_address (exp, pos, noside); + } + else + { + arg2 = evaluate_subexp (0, exp, pos, noside); + } + + /* If the function is a virtual function, then the + aggregate value (providing the structure) plays + its part by providing the vtable. Otherwise, + it is just along for the ride: call the function + directly. */ + + arg1 = evaluate_subexp (0, exp, pos, noside); + + fnptr = value_as_long (arg1); + if (fnptr < 128) + { + struct type *basetype; + int i, j; + basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2)); + basetype = TYPE_VPTR_BASETYPE (basetype); + for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--) + { + struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i); + /* If one is virtual, then all are virtual. */ + if (TYPE_FN_FIELD_VIRTUAL_P (f, 0)) + for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j) + if (TYPE_FN_FIELD_VOFFSET (f, j) == fnptr) + { + value vtbl; + value base = value_ind (arg2); + struct type *fntype = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j)); + + if (TYPE_VPTR_FIELDNO (basetype) < 0) + TYPE_VPTR_FIELDNO (basetype) + = fill_in_vptr_fieldno (basetype); + + VALUE_TYPE (base) = basetype; + vtbl = value_field (base, TYPE_VPTR_FIELDNO (basetype)); + VALUE_TYPE (vtbl) = lookup_pointer_type (fntype); + VALUE_TYPE (arg1) = builtin_type_int; + arg1 = value_subscript (vtbl, arg1); + VALUE_TYPE (arg1) = fntype; + goto got_it; + } + } + if (i < 0) + error ("virtual function at index %d not found", fnptr); + } + else + { + VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))); + } + got_it: + + /* Now, say which argument to start evaluating from */ + tem = 2; + } + else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) + { + /* Hair for method invocations */ + int tem2; + + nargs = exp->elts[pc + 1].longconst + 1; + /* First, evaluate the structure into arg2 */ + pc2 = (*pos)++; + tem2 = strlen (&exp->elts[pc2 + 1].string); + *pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element); + if (noside == EVAL_SKIP) + goto nosideret; + + if (op == STRUCTOP_STRUCT) + { + arg2 = evaluate_subexp_for_address (exp, pos, noside); + } + else + { + arg2 = evaluate_subexp (0, exp, pos, noside); + } + /* Now, say which argument to start evaluating from */ + tem = 2; + } + else + { + nargs = exp->elts[pc + 1].longconst; + tem = 0; + } + argvec = (value *) alloca (sizeof (value) * (nargs + 2)); + for (; tem <= nargs; tem++) /* Ensure that array expressions are coerced into pointer objects. */ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside); + /* signal end of arglist */ + argvec[tem] = 0; + + if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR) + { + argvec[1] = arg2; + argvec[0] = + value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string, + op == STRUCTOP_STRUCT + ? "structure" : "structure pointer"); + } + else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) + { + argvec[1] = arg2; + argvec[0] = arg1; + } + if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) @@ -198,52 +323,79 @@ evaluate_subexp (exp, pos, noside) case TERNOP_COND: /* Skip third and second args to evaluate the first one. */ - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); if (value_zerop (arg1)) { - evaluate_subexp (exp, pos, EVAL_SKIP); - return evaluate_subexp (exp, pos, noside); + evaluate_subexp (0, exp, pos, EVAL_SKIP); + return evaluate_subexp (0, exp, pos, noside); } else { - arg2 = evaluate_subexp (exp, pos, noside); - evaluate_subexp (exp, pos, EVAL_SKIP); + arg2 = evaluate_subexp (0, exp, pos, noside); + evaluate_subexp (0, exp, pos, EVAL_SKIP); return arg2; } case STRUCTOP_STRUCT: tem = strlen (&exp->elts[pc + 1].string); (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_struct_elt (arg1, &exp->elts[pc + 1].string, + return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, "structure"); case STRUCTOP_PTR: tem = strlen (&exp->elts[pc + 1].string); (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_struct_elt (arg1, &exp->elts[pc + 1].string, + return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, "structure pointer"); + case STRUCTOP_MEMBER: + arg1 = evaluate_subexp_for_address (exp, pos, noside); + arg2 = evaluate_subexp (0, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + /* Now, convert these values to an address. */ + arg3 = value_from_long (builtin_type_long, + value_as_long (arg1) + value_as_long (arg2)); + VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))); + return value_ind (arg3); + + case STRUCTOP_MPTR: + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (0, exp, pos, noside); + if (noside == EVAL_SKIP) + goto nosideret; + /* Now, convert these values to an address. */ + arg3 = value_from_long (builtin_type_long, + value_as_long (arg1) + value_as_long (arg2)); + VALUE_TYPE (arg3) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))); + return value_ind (arg3); + case BINOP_ASSIGN: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; - return value_assign (arg1, arg2); + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, 0); + else + return value_assign (arg1, arg2); case BINOP_ASSIGN_MODIFY: (*pos) += 2; - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; op = exp->elts[pc + 1].opcode; - if (op == BINOP_ADD) + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op); + else if (op == BINOP_ADD) arg2 = value_add (arg1, arg2); else if (op == BINOP_SUB) arg2 = value_sub (arg1, arg2); @@ -256,14 +408,20 @@ evaluate_subexp (exp, pos, noside) arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_add (arg1, arg2); + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, 0); + else + return value_add (arg1, arg2); case BINOP_SUB: arg1 = evaluate_subexp_with_coercion (exp, pos, noside); arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_sub (arg1, arg2); + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, 0); + else + return value_sub (arg1, arg2); case BINOP_MUL: case BINOP_DIV: @@ -273,177 +431,311 @@ evaluate_subexp (exp, pos, noside) case BINOP_LOGAND: case BINOP_LOGIOR: case BINOP_LOGXOR: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_binop (arg1, arg2, op); + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, 0); + else + return value_binop (arg1, arg2, op); case BINOP_SUBSCRIPT: arg1 = evaluate_subexp_with_coercion (exp, pos, noside); arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_subscript (arg1, arg2, op); + if (binop_user_defined_p (op, arg1, arg2)) + return value_x_binop (arg1, arg2, op, 0); + else + return value_subscript (arg1, arg2, op); case BINOP_AND: - arg1 = evaluate_subexp (exp, pos, noside); - tem = value_zerop (arg1); - arg2 = evaluate_subexp (exp, pos, - (tem ? EVAL_SKIP : noside)); - return value_from_long (builtin_type_int, - !tem && !value_zerop (arg2)); + arg1 = evaluate_subexp (0, exp, pos, noside); + if (binop_user_defined_p (op, arg1, arg2)) + { + arg2 = evaluate_subexp (0, exp, pos, noside); + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_zerop (arg1); + arg2 = evaluate_subexp (0, exp, pos, + (tem ? EVAL_SKIP : noside)); + return value_from_long (builtin_type_int, + !tem && !value_zerop (arg2)); + } case BINOP_OR: - arg1 = evaluate_subexp (exp, pos, noside); - tem = value_zerop (arg1); - arg2 = evaluate_subexp (exp, pos, - (!tem ? EVAL_SKIP : noside)); - return value_from_long (builtin_type_int, - !tem || !value_zerop (arg2)); + arg1 = evaluate_subexp (0, exp, pos, noside); + if (binop_user_defined_p (op, arg1, arg2)) + { + arg2 = evaluate_subexp (0, exp, pos, noside); + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_zerop (arg1); + arg2 = evaluate_subexp (0, exp, pos, + (!tem ? EVAL_SKIP : noside)); + return value_from_long (builtin_type_int, + !tem || !value_zerop (arg2)); + } case BINOP_EQUAL: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - tem = value_equal (arg1, arg2); - return value_from_long (builtin_type_int, tem); + if (binop_user_defined_p (op, arg1, arg2)) + { + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_equal (arg1, arg2); + return value_from_long (builtin_type_int, tem); + } case BINOP_NOTEQUAL: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - tem = value_equal (arg1, arg2); - return value_from_long (builtin_type_int, ! tem); + if (binop_user_defined_p (op, arg1, arg2)) + { + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_equal (arg1, arg2); + return value_from_long (builtin_type_int, ! tem); + } case BINOP_LESS: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - tem = value_less (arg1, arg2); - return value_from_long (builtin_type_int, tem); + if (binop_user_defined_p (op, arg1, arg2)) + { + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_less (arg1, arg2); + return value_from_long (builtin_type_int, tem); + } case BINOP_GTR: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - tem = value_less (arg2, arg1); - return value_from_long (builtin_type_int, tem); + if (binop_user_defined_p (op, arg1, arg2)) + { + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_less (arg2, arg1); + return value_from_long (builtin_type_int, tem); + } case BINOP_GEQ: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - tem = value_less (arg1, arg2); - return value_from_long (builtin_type_int, ! tem); + if (binop_user_defined_p (op, arg1, arg2)) + { + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_less (arg1, arg2); + return value_from_long (builtin_type_int, ! tem); + } case BINOP_LEQ: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - tem = value_less (arg2, arg1); - return value_from_long (builtin_type_int, ! tem); + if (binop_user_defined_p (op, arg1, arg2)) + { + return value_x_binop (arg1, arg2, op, 0); + } + else + { + tem = value_less (arg2, arg1); + return value_from_long (builtin_type_int, ! tem); + } case BINOP_REPEAT: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); + arg2 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; return value_repeat (arg1, value_as_long (arg2)); case BINOP_COMMA: - evaluate_subexp (exp, pos, noside); - return evaluate_subexp (exp, pos, noside); + evaluate_subexp (0, exp, pos, noside); + return evaluate_subexp (0, exp, pos, noside); case UNOP_NEG: - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_neg (arg1); + if (unop_user_defined_p (op, arg1)) + return value_x_unop (arg1, op, 0); + else + return value_neg (arg1); case UNOP_LOGNOT: - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_lognot (arg1); + if (unop_user_defined_p (op, arg1)) + return value_x_unop (arg1, op, 0); + else + return value_lognot (arg1); case UNOP_ZEROP: - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (0, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; - return value_from_long (builtin_type_int, value_zerop (arg1)); + if (unop_user_defined_p (op, arg1)) + return value_x_unop (arg1, op, 0); + else + return value_from_long (builtin_type_int, value_zerop (arg1)); case UNOP_IND: - arg1 = evaluate_subexp (exp, pos, noside); + if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR) + expect_type = TYPE_TARGET_TYPE (expect_type); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; return value_ind (arg1); case UNOP_ADDR: + /* C++: check for and handle pointer to members. */ + + op = exp->elts[*pos].opcode; + if (noside == EVAL_SKIP) { - evaluate_subexp (exp, pos, EVAL_SKIP); + if (op == OP_SCOPE) + { + char *name = &exp->elts[pc+3].string; + int tem = strlen (name); + (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + } + else + evaluate_subexp (expect_type, exp, pos, EVAL_SKIP); goto nosideret; } - return evaluate_subexp_for_address (exp, pos, noside); + + if (op == OP_SCOPE) + { + char *name = &exp->elts[pc+3].string; + int tem = strlen (name); + struct type *domain = exp->elts[pc+2].type; + (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + arg1 = value_struct_elt_for_address (domain, expect_type, name); + if (arg1) + return arg1; + error ("no field `%s' in structure", name); + } + else + return evaluate_subexp_for_address (exp, pos, noside); case UNOP_SIZEOF: if (noside == EVAL_SKIP) { - evaluate_subexp (exp, pos, EVAL_SKIP); + evaluate_subexp (0, exp, pos, EVAL_SKIP); goto nosideret; } return evaluate_subexp_for_sizeof (exp, pos); case UNOP_CAST: (*pos) += 2; - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; return value_cast (exp->elts[pc + 1].type, arg1); case UNOP_MEMVAL: (*pos) += 2; - arg1 = evaluate_subexp (exp, pos, noside); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; return value_at (exp->elts[pc + 1].type, value_as_long (arg1)); case UNOP_PREINCREMENT: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = value_add (arg1, value_from_long (builtin_type_char, 1)); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; - return value_assign (arg1, arg2); + else if (unop_user_defined_p (op, arg1)) + { + return value_x_unop (arg1, op, 0); + } + else + { + arg2 = value_add (arg1, value_from_long (builtin_type_char, 1)); + return value_assign (arg1, arg2); + } case UNOP_PREDECREMENT: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1)); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; - return value_assign (arg1, arg2); + else if (unop_user_defined_p (op, arg1)) + { + return value_x_unop (arg1, op, 0); + } + else + { + arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1)); + return value_assign (arg1, arg2); + } case UNOP_POSTINCREMENT: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = value_add (arg1, value_from_long (builtin_type_char, 1)); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; - value_assign (arg1, arg2); - return arg1; + else if (unop_user_defined_p (op, arg1)) + { + return value_x_unop (arg1, op, 0); + } + else + { + arg2 = value_add (arg1, value_from_long (builtin_type_char, 1)); + value_assign (arg1, arg2); + return arg1; + } case UNOP_POSTDECREMENT: - arg1 = evaluate_subexp (exp, pos, noside); - arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1)); + arg1 = evaluate_subexp (expect_type, exp, pos, noside); if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS) return arg1; - value_assign (arg1, arg2); - return arg1; + else if (unop_user_defined_p (op, arg1)) + { + return value_x_unop (arg1, op, 0); + } + else + { + arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1)); + value_assign (arg1, arg2); + return arg1; + } + + case OP_THIS: + (*pos) += 1; + return value_of_this (1); + + default: + error ("internal error: I dont know how to evaluation what you gave me"); } nosideret: @@ -473,19 +765,19 @@ evaluate_subexp_for_address (exp, pos, noside) { case UNOP_IND: (*pos)++; - return evaluate_subexp (exp, pos, noside); + return evaluate_subexp (0, exp, pos, noside); case UNOP_MEMVAL: (*pos) += 3; return value_cast (lookup_pointer_type (exp->elts[pc + 1].type), - evaluate_subexp (exp, pos, noside)); + evaluate_subexp (0, exp, pos, noside)); case OP_VAR_VALUE: (*pos) += 3; return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0); default: - return value_addr (evaluate_subexp (exp, pos, noside)); + return value_addr (evaluate_subexp (0, exp, pos, noside)); } } @@ -519,7 +811,7 @@ evaluate_subexp_with_coercion (exp, pos, noside) } } - return evaluate_subexp (exp, pos, noside); + return evaluate_subexp (0, exp, pos, noside); } /* Evaluate a subexpression of EXP, at index *POS, @@ -546,7 +838,7 @@ evaluate_subexp_for_sizeof (exp, pos) create a value unnecessarily. */ case UNOP_IND: (*pos)++; - val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS); + val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS); return value_from_long (builtin_type_int, TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val)))); @@ -561,7 +853,7 @@ evaluate_subexp_for_sizeof (exp, pos) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol))); default: - val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS); + val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS); return value_from_long (builtin_type_int, TYPE_LENGTH (VALUE_TYPE (val))); } diff --git a/gdb/expread.tab.c b/gdb/expread.tab.c new file mode 100644 index 00000000000..5d6ff11db78 --- /dev/null +++ b/gdb/expread.tab.c @@ -0,0 +1,1608 @@ + +# line 31 "expread.y" +#include "defs.h" +#include "param.h" +#include "symtab.h" +#include "frame.h" +#include "expression.h" + +#include + +static struct expression *expout; +static int expout_size; +static int expout_ptr; + +static int yylex (); +static yyerror (); +static void write_exp_elt (); +static void write_exp_elt2 (); +static void write_exp_string (); +static void start_arglist (); +static int end_arglist (); +static void free_funcalls (); +static char *copy_name (); + +/* If this is nonzero, this block is used as the lexical context + for symbol names. */ + +static struct block *expression_context_block; + +/* 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; + }; + +# line 86 "expread.y" +typedef union + { + long lval; + double dval; + struct symbol *sym; + struct type *tval; + struct stoken sval; + int voidval; + struct block *bval; + enum exp_opcode opcode; + struct internalvar *ivar; + + struct type **tvec; + int *ivec; + } YYSTYPE; +# define INT 257 +# define CHAR 258 +# define FLOAT 259 +# define NAME 260 +# define TYPENAME 261 +# define STRING 262 +# define STRUCT 263 +# define UNION 264 +# define ENUM 265 +# define SIZEOF 266 +# define UNSIGNED 267 +# define COLONCOLON 268 +# define LAST 269 +# define REGNAME 270 +# define VARIABLE 271 +# define ASSIGN_MODIFY 272 +# define THIS 273 +# define ABOVE_COMMA 274 +# define OR 275 +# define AND 276 +# define EQUAL 277 +# define NOTEQUAL 278 +# define LEQ 279 +# define GEQ 280 +# define LSH 281 +# define RSH 282 +# define UNARY 283 +# define INCREMENT 284 +# define DECREMENT 285 +# define ARROW 286 +#define yyclearin yychar = -1 +#define yyerrok yyerrflag = 0 +extern int yychar; +extern short yyerrflag; +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 150 +#endif +YYSTYPE yylval, yyval; +# define YYERRCODE 256 + +# line 625 "expread.y" + + +/* 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); + } +} + +/* 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 only things that + can fit into a single register through here. */ +static void +write_exp_elt (expelt) + /* union exp_element expelt; */ + long expelt; +{ + union exp_element temp; + temp.longconst = 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 */ temp; +} + +/* Things that take more space must come through here. */ +static void +write_exp_elt2 (expelt) + double expelt; +{ + union exp_element temp; + temp.doubleconst = 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++] = temp; +} + +/* 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 (len); +} + +/* 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 (olen) + int olen; +{ + register char *p = lexptr; + register long n = 0; + register int c; + register int base = 10; + register int len = olen; + char *err_copy; + + extern double atof (); + + for (c = 0; c < len; c++) + if (p[c] == '.') + { + /* It's a float since it contains a point. */ + yylval.dval = atof (p); + lexptr += len; + return FLOAT; + } + + if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) + { + p += 2; + base = 16; + len -= 2; + } + else if (*p == '0') + base = 8; + + while (len-- > 0) + { + c = *p++; + n *= base; + if (c >= '0' && c <= '9') + n += c - '0'; + else + { + if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; + if (base == 16 && c >= 'a' && c <= 'f') + n += c - 'a' + 10; + else if (len == 0 && c == 'l') + ; + else + { + err_copy = (char *) alloca (olen + 1); + bcopy (lexptr, err_copy, olen); + err_copy[olen] = 0; + error ("Invalid number \"%s\".", err_copy); + } + } + } + + lexptr = p; + yylval.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} + }; + +/* Read one token, getting characters through lexptr. */ + +static int +yylex () +{ + register int c; + register int namelen; + register int 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 '+': + case '-': + case '*': + case '/': + case '%': + case '|': + case '&': + case '^': + case '~': + case '!': + case '@': + case '<': + case '>': + case '[': + case ']': + case '.': + case '?': + case ':': + case '=': + case '{': + case '}': + 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 >= '0' && c <= '9') + { + /* It's a number */ + for (namelen = 0; + c = tokstart[namelen], + (c == '_' || c == '$' || c == '.' || (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); + namelen++) + ; + return parse_number (namelen); + } + + if (!(c == '_' || c == '$' + || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) + error ("Invalid token in expression."); + + /* It is a name. See how long it is. */ + + for (namelen = 0; + c = tokstart[namelen], + (c == '_' || c == '$' || (c >= '0' && c <= '9') + || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); + 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; + } + + if (namelen == 6 && !strncmp (tokstart, "struct", 6)) + { + return STRUCT; + } + if (namelen == 5) + { + if (!strncmp (tokstart, "union", 5)) + { + return UNION; + } + } + if (namelen == 4) + { + if (!strncmp (tokstart, "enum", 4)) + { + return ENUM; + } + if (!strncmp (tokstart, "this", 4)) + { + return THIS; + } + } + if (namelen == 6 && !strncmp (tokstart, "sizeof", 6)) + { + return SIZEOF; + } + if (namelen == 8 && !strncmp (tokstart, "unsigned", 6)) + { + return UNSIGNED; + } + yylval.sval.ptr = tokstart; + yylval.sval.length = namelen; + + /* Any other names starting in $ are debugger internal variables. */ + + if (*tokstart == '$') + { + yylval.ivar = (struct internalvar *) lookup_internalvar (copy_name (yylval.sval) + 1); + return VARIABLE; + } + + /* 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. */ + if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1)) + return TYPENAME; + return NAME; +} + +static +yyerror () +{ + 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; +} + +/* 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; + } +} + +/* 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; +{ + struct cleanup *old_chain; + + lexptr = *stringptr; + + 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 (); + 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; +} +short yyexca[] ={ +-1, 1, + 0, -1, + -2, 0, +-1, 26, + 268, 79, + -2, 64, +-1, 124, + 268, 60, + -2, 61, + }; +# define YYNPROD 81 +# define YYLAST 696 +short yyact[]={ + + 43, 54, 140, 39, 123, 41, 44, 120, 45, 37, + 42, 78, 77, 73, 39, 29, 30, 31, 142, 32, + 37, 131, 33, 52, 60, 53, 59, 40, 80, 81, + 143, 148, 33, 135, 149, 43, 54, 59, 39, 135, + 41, 44, 71, 45, 37, 42, 137, 129, 122, 138, + 90, 33, 144, 92, 38, 23, 74, 55, 52, 60, + 53, 59, 40, 146, 118, 38, 119, 88, 117, 17, + 43, 54, 1, 39, 0, 41, 44, 0, 45, 37, + 42, 128, 118, 0, 119, 0, 117, 56, 0, 38, + 0, 0, 55, 52, 0, 53, 59, 40, 7, 0, + 0, 75, 2, 5, 0, 13, 0, 4, 0, 0, + 6, 43, 54, 115, 39, 0, 41, 44, 0, 45, + 37, 42, 56, 0, 38, 0, 118, 55, 119, 132, + 117, 0, 0, 0, 52, 0, 53, 59, 40, 7, + 91, 0, 0, 0, 5, 0, 70, 0, 4, 0, + 0, 6, 0, 43, 54, 0, 39, 56, 41, 44, + 0, 45, 37, 42, 0, 38, 0, 0, 55, 116, + 118, 0, 119, 121, 117, 0, 52, 0, 53, 59, + 40, 0, 0, 0, 0, 0, 0, 147, 12, 0, + 0, 8, 150, 0, 145, 0, 43, 54, 56, 39, + 0, 41, 44, 0, 45, 37, 42, 38, 0, 0, + 55, 0, 0, 0, 0, 0, 0, 0, 0, 52, + 0, 53, 59, 40, 0, 0, 0, 0, 0, 12, + 39, 0, 8, 0, 0, 61, 37, 0, 58, 57, + 48, 49, 50, 51, 46, 47, 0, 34, 35, 36, + 38, 80, 81, 59, 40, 0, 0, 0, 34, 35, + 36, 0, 43, 0, 0, 39, 0, 41, 80, 81, + 61, 37, 42, 58, 57, 48, 49, 50, 51, 46, + 47, 38, 34, 35, 36, 80, 81, 0, 59, 40, + 0, 0, 0, 0, 43, 0, 0, 39, 0, 41, + 44, 0, 45, 37, 42, 0, 0, 0, 0, 57, + 48, 49, 50, 51, 46, 47, 38, 34, 35, 36, + 59, 40, 14, 15, 16, 26, 28, 21, 29, 30, + 31, 11, 32, 25, 18, 19, 20, 0, 22, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 38, 9, + 10, 48, 49, 50, 51, 46, 47, 0, 34, 35, + 36, 0, 0, 14, 15, 16, 26, 28, 21, 29, + 30, 31, 11, 32, 25, 18, 19, 20, 43, 22, + 0, 39, 0, 41, 44, 0, 45, 37, 42, 0, + 9, 10, 0, 48, 49, 50, 51, 46, 47, 0, + 34, 35, 36, 43, 59, 40, 39, 0, 41, 44, + 24, 45, 37, 42, 73, 0, 29, 30, 31, 0, + 32, 0, 0, 72, 76, 0, 52, 0, 53, 59, + 40, 0, 38, 0, 0, 0, 48, 49, 50, 51, + 46, 47, 0, 34, 35, 36, 43, 0, 0, 39, + 0, 41, 44, 27, 45, 37, 42, 38, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, + 0, 53, 59, 40, 34, 35, 36, 0, 0, 79, + 0, 76, 0, 82, 83, 84, 85, 0, 0, 0, + 87, 89, 0, 0, 0, 0, 0, 0, 0, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 34, + 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134, 124, 125, 0, 0, 0, 0, 0, 46, 47, + 3, 34, 35, 36, 0, 62, 63, 64, 65, 66, + 67, 68, 69, 0, 0, 72, 0, 0, 0, 0, + 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 0, 0, 125, 0, 0, + 0, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 34, 35, 36, 0, 126, + 0, 127, 0, 130, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 48, 49, 50, 51, 46, 47, 0, + 34, 35, 36, 0, 0, 0, 0, 133, 0, 0, + 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 139, 136, 0, 0, 0, 0, 0, 141, + 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, + 46, 47, 0, 34, 35, 36 }; +short yypact[]={ + + 65,-1000, -22, -2, 65, 65, 65, 65, 65, 65, + 65, 106,-248, 65,-1000,-1000,-1000,-1000,-1000,-1000, +-1000,-1000,-1000,-256,-257,-232,-1000,-1000,-1000,-232, +-232,-232,-232, 65,-1000,-1000, 25, 8, 65,-1000, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, -26, -26, -26, -26, -26, -26, -26, -26, + 65, 44,-261,-1000, 132, 7,-264,-232,-232,-1000, +-1000,-1000,-1000,-1000,-1000,-1000, -2,-1000, 65,-1000, + 65, -12, 65, -26, 190, 190, 190, 225, 225, 341, + 341, 409, 409, 257, 257, 257, 257, 366, 159, 116, + 74, 33, -37, -2, -2, 88, 65,-1000,-1000,-248, + -3, 65,-1000, -9,-1000,-1000, 190, 190,-1000, 5, + -2, 65, 65, -26,-266,-1000, -26,-1000, 65, -2, + -24, -2, -11, 12, 153,-1000, -10, 26,-1000,-248, + 26 }; +short yypgo[]={ + + 0, 540, 101, 72, 69, 42, 410, 63, 55, 453, + 53, 47 }; +short yyr1[]={ + + 0, 3, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, + 1, 11, 11, 11, 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, 1, 1, 1, 8, + 8, 4, 4, 4, 4, 5, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 7, 7, 9, + 9 }; +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, 4, 1, 1, 1, + 3, 3, 3, 2, 1, 1, 2, 2, 3, 6, + 8, 9, 1, 2, 2, 2, 2, 1, 3, 1, + 1 }; +short yychk[]={ + +-1000, -3, -2, -1, 42, 38, 45, 33, 126, 284, + 285, 266, 123, 40, 257, 258, 259, -4, 269, 270, + 271, 262, 273, -8, -6, 268, 260, -9, 261, 263, + 264, 265, 267, 44, 284, 285, 286, 46, 91, 40, + 64, 42, 47, 37, 43, 45, 281, 282, 277, 278, + 279, 280, 60, 62, 38, 94, 124, 276, 275, 63, + 61, 272, -1, -1, -1, -1, -1, -1, -1, -1, + 40, -5, -6, 261, -5, -2, -6, 268, 268, -9, + 260, 261, -9, -9, -9, -9, -1, -9, 42, -9, + 42, -2, -10, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -5, 125, 42, 38, 40, + 268, 41, 41, 268, -9, -9, -1, -1, 93, -11, + -1, 58, 41, -1, -6, 42, -1, 41, 44, -1, + 268, -1, 42, 41, 40, 41, -7, -5, 41, 44, + -5 }; +short yydef[]={ + + 0, -2, 1, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 49, 50, 51, 52, 53, 54, + 55, 57, 58, 0, 0, 0, -2, 59, 72, 0, + 0, 0, 0, 0, 11, 12, 0, 0, 0, 19, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 5, 6, 7, 8, 9, 10, 13, + 0, 0, 65, 72, 0, 0, 65, 0, 0, 63, + 79, 80, 73, 74, 75, 76, 3, 14, 0, 16, + 0, 0, 21, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 0, 47, 48, 0, 0, 66, 67, 0, + 0, 0, 26, 0, -2, 62, 15, 17, 18, 0, + 22, 0, 56, 24, 0, 68, 25, 20, 0, 46, + 0, 23, 0, 69, 0, 70, 0, 77, 71, 0, + 78 }; +#ifndef lint +static char yaccpar_sccsid[] = "@(#)yaccpar 1.6 88/02/08 SMI"; /* from UCB 4.1 83/02/11 */ +#endif + +# +# define YYFLAG -1000 +# define YYERROR goto yyerrlab +# define YYACCEPT return(0) +# define YYABORT return(1) + +/* parser for yacc output */ + +#ifdef YYDEBUG +int yydebug = 0; /* 1 for debugging */ +#endif +YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ +int yychar = -1; /* current input token number */ +int yynerrs = 0; /* number of errors */ +short yyerrflag = 0; /* error recovery flag */ + +yyparse() { + + short yys[YYMAXDEPTH]; + short yyj, yym; + register YYSTYPE *yypvt; + register short yystate, *yyps, yyn; + register YYSTYPE *yypv; + register short *yyxi; + + yystate = 0; + yychar = -1; + yynerrs = 0; + yyerrflag = 0; + yyps= &yys[-1]; + yypv= &yyv[-1]; + + yystack: /* put a state and value onto the stack */ + +#ifdef YYDEBUG + if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar ); +#endif + if( ++yyps>= &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); } + *yyps = yystate; + ++yypv; + *yypv = yyval; + + yynewstate: + + yyn = yypact[yystate]; + + if( yyn<= YYFLAG ) goto yydefault; /* simple state */ + + if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; + if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; + + if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ + yychar = -1; + yyval = yylval; + yystate = yyn; + if( yyerrflag > 0 ) --yyerrflag; + goto yystack; + } + + yydefault: + /* default state action */ + + if( (yyn=yydef[yystate]) == -2 ) { + if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; + /* look through exception table */ + + for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ + + while( *(yyxi+=2) >= 0 ){ + if( *yyxi == yychar ) break; + } + if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ + } + + if( yyn == 0 ){ /* error */ + /* error ... attempt to resume parsing */ + + switch( yyerrflag ){ + + case 0: /* brand new error */ + + yyerror( "syntax error" ); + yyerrlab: + ++yynerrs; + + case 1: + case 2: /* incompletely recovered error ... try again */ + + yyerrflag = 3; + + /* find a state where "error" is a legal shift action */ + + while ( yyps >= yys ) { + yyn = yypact[*yyps] + YYERRCODE; + if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ + yystate = yyact[yyn]; /* simulate a shift of "error" */ + goto yystack; + } + yyn = yypact[*yyps]; + + /* the current yyps has no shift onn "error", pop stack */ + +#ifdef YYDEBUG + if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); +#endif + --yyps; + --yypv; + } + + /* there is no state on the stack with an error shift ... abort */ + + yyabort: + return(1); + + + case 3: /* no shift yet; clobber input char */ + +#ifdef YYDEBUG + if( yydebug ) printf( "error recovery discards char %d\n", yychar ); +#endif + + if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ + yychar = -1; + goto yynewstate; /* try again in the same state */ + + } + + } + + /* reduction by production yyn */ + +#ifdef YYDEBUG + if( yydebug ) printf("reduce %d\n",yyn); +#endif + yyps -= yyr2[yyn]; + yypvt = yypv; + yypv -= yyr2[yyn]; + yyval = yypv[1]; + yym=yyn; + /* consult goto table to find next state */ + yyn = yyr1[yyn]; + yyj = yypgo[yyn] + *yyps + 1; + if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; + switch(yym){ + +case 3: +# line 159 "expread.y" +{ write_exp_elt (BINOP_COMMA); } break; +case 4: +# line 164 "expread.y" +{ write_exp_elt (UNOP_IND); } break; +case 5: +# line 167 "expread.y" +{ write_exp_elt (UNOP_ADDR); } break; +case 6: +# line 170 "expread.y" +{ write_exp_elt (UNOP_NEG); } break; +case 7: +# line 174 "expread.y" +{ write_exp_elt (UNOP_ZEROP); } break; +case 8: +# line 178 "expread.y" +{ write_exp_elt (UNOP_LOGNOT); } break; +case 9: +# line 182 "expread.y" +{ write_exp_elt (UNOP_PREINCREMENT); } break; +case 10: +# line 186 "expread.y" +{ write_exp_elt (UNOP_PREDECREMENT); } break; +case 11: +# line 190 "expread.y" +{ write_exp_elt (UNOP_POSTINCREMENT); } break; +case 12: +# line 194 "expread.y" +{ write_exp_elt (UNOP_POSTDECREMENT); } break; +case 13: +# line 198 "expread.y" +{ write_exp_elt (UNOP_SIZEOF); } break; +case 14: +# line 202 "expread.y" +{ write_exp_elt (STRUCTOP_PTR); + write_exp_string (yypvt[-0].sval); + write_exp_elt (STRUCTOP_PTR); } break; +case 15: +# line 208 "expread.y" +{ write_exp_elt (STRUCTOP_MPTR); } break; +case 16: +# line 212 "expread.y" +{ write_exp_elt (STRUCTOP_STRUCT); + write_exp_string (yypvt[-0].sval); + write_exp_elt (STRUCTOP_STRUCT); } break; +case 17: +# line 218 "expread.y" +{ write_exp_elt (STRUCTOP_MEMBER); } break; +case 18: +# line 222 "expread.y" +{ write_exp_elt (BINOP_SUBSCRIPT); } break; +case 19: +# line 228 "expread.y" +{ start_arglist (); } break; +case 20: +# line 230 "expread.y" +{ write_exp_elt (OP_FUNCALL); + write_exp_elt (end_arglist ()); + write_exp_elt (OP_FUNCALL); } break; +case 22: +# line 239 "expread.y" +{ arglist_len = 1; } break; +case 23: +# line 243 "expread.y" +{ arglist_len++; } break; +case 24: +# line 247 "expread.y" +{ write_exp_elt (UNOP_MEMVAL); + write_exp_elt (yypvt[-2].tval); + write_exp_elt (UNOP_MEMVAL); } break; +case 25: +# line 253 "expread.y" +{ write_exp_elt (UNOP_CAST); + write_exp_elt (yypvt[-2].tval); + write_exp_elt (UNOP_CAST); } break; +case 26: +# line 259 "expread.y" +{ } break; +case 27: +# line 265 "expread.y" +{ write_exp_elt (BINOP_REPEAT); } break; +case 28: +# line 269 "expread.y" +{ write_exp_elt (BINOP_MUL); } break; +case 29: +# line 273 "expread.y" +{ write_exp_elt (BINOP_DIV); } break; +case 30: +# line 277 "expread.y" +{ write_exp_elt (BINOP_REM); } break; +case 31: +# line 281 "expread.y" +{ write_exp_elt (BINOP_ADD); } break; +case 32: +# line 285 "expread.y" +{ write_exp_elt (BINOP_SUB); } break; +case 33: +# line 289 "expread.y" +{ write_exp_elt (BINOP_LSH); } break; +case 34: +# line 293 "expread.y" +{ write_exp_elt (BINOP_RSH); } break; +case 35: +# line 297 "expread.y" +{ write_exp_elt (BINOP_EQUAL); } break; +case 36: +# line 301 "expread.y" +{ write_exp_elt (BINOP_NOTEQUAL); } break; +case 37: +# line 305 "expread.y" +{ write_exp_elt (BINOP_LEQ); } break; +case 38: +# line 309 "expread.y" +{ write_exp_elt (BINOP_GEQ); } break; +case 39: +# line 313 "expread.y" +{ write_exp_elt (BINOP_LESS); } break; +case 40: +# line 317 "expread.y" +{ write_exp_elt (BINOP_GTR); } break; +case 41: +# line 321 "expread.y" +{ write_exp_elt (BINOP_LOGAND); } break; +case 42: +# line 325 "expread.y" +{ write_exp_elt (BINOP_LOGXOR); } break; +case 43: +# line 329 "expread.y" +{ write_exp_elt (BINOP_LOGIOR); } break; +case 44: +# line 333 "expread.y" +{ write_exp_elt (BINOP_AND); } break; +case 45: +# line 337 "expread.y" +{ write_exp_elt (BINOP_OR); } break; +case 46: +# line 341 "expread.y" +{ write_exp_elt (TERNOP_COND); } break; +case 47: +# line 345 "expread.y" +{ write_exp_elt (BINOP_ASSIGN); } break; +case 48: +# line 349 "expread.y" +{ write_exp_elt (BINOP_ASSIGN_MODIFY); + write_exp_elt (yypvt[-1].opcode); + write_exp_elt (BINOP_ASSIGN_MODIFY); } break; +case 49: +# line 355 "expread.y" +{ write_exp_elt (OP_LONG); + write_exp_elt (builtin_type_long); + write_exp_elt (yypvt[-0].lval); + write_exp_elt (OP_LONG); } break; +case 50: +# line 362 "expread.y" +{ write_exp_elt (OP_LONG); + write_exp_elt (builtin_type_char); + write_exp_elt (yypvt[-0].lval); + write_exp_elt (OP_LONG); } break; +case 51: +# line 369 "expread.y" +{ write_exp_elt (OP_DOUBLE); + write_exp_elt (builtin_type_double); + write_exp_elt2 (yypvt[-0].dval); + write_exp_elt (OP_DOUBLE); } break; +case 53: +# line 379 "expread.y" +{ write_exp_elt (OP_LAST); + write_exp_elt (yypvt[-0].lval); + write_exp_elt (OP_LAST); } break; +case 54: +# line 385 "expread.y" +{ write_exp_elt (OP_REGISTER); + write_exp_elt (yypvt[-0].lval); + write_exp_elt (OP_REGISTER); } break; +case 55: +# line 391 "expread.y" +{ write_exp_elt (OP_INTERNALVAR); + write_exp_elt (yypvt[-0].ivar); + write_exp_elt (OP_INTERNALVAR); } break; +case 56: +# line 397 "expread.y" +{ write_exp_elt (OP_LONG); + write_exp_elt (builtin_type_int); + write_exp_elt ((long) TYPE_LENGTH (yypvt[-1].tval)); + write_exp_elt (OP_LONG); } break; +case 57: +# line 404 "expread.y" +{ write_exp_elt (OP_STRING); + write_exp_string (yypvt[-0].sval); + write_exp_elt (OP_STRING); } break; +case 58: +# line 411 "expread.y" +{ write_exp_elt (OP_THIS); + write_exp_elt (OP_THIS); } break; +case 59: +# line 418 "expread.y" +{ + struct symtab *tem = lookup_symtab (copy_name (yypvt[-0].sval)); + struct symbol *sym; + + if (tem) + yyval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1); + else + { + sym = lookup_symbol (copy_name (yypvt[-0].sval), + expression_context_block, + VAR_NAMESPACE); + if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) + yyval.bval = SYMBOL_BLOCK_VALUE (sym); + else + error ("No file or function \"%s\".", + copy_name (yypvt[-0].sval)); + } + } break; +case 60: +# line 439 "expread.y" +{ + struct symbol *tem + = lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE); + if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) + error ("No function \"%s\" in specified context.", + copy_name (yypvt[-0].sval)); + yyval.bval = SYMBOL_BLOCK_VALUE (tem); + } break; +case 61: +# line 450 "expread.y" +{ + struct symbol *sym; + sym = lookup_symbol (copy_name (yypvt[-0].sval), yypvt[-2].bval, VAR_NAMESPACE); + if (sym == 0) + error ("No symbol \"%s\" in specified context.", + copy_name (yypvt[-0].sval)); + write_exp_elt (OP_VAR_VALUE); + write_exp_elt (sym); + write_exp_elt (OP_VAR_VALUE); + } break; +case 62: +# line 463 "expread.y" +{ + struct type *type = yypvt[-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 (OP_SCOPE); + write_exp_elt (type); + write_exp_string (yypvt[-0].sval); + write_exp_elt (OP_SCOPE); + } break; +case 63: +# line 476 "expread.y" +{ + char *name = copy_name (yypvt[-0].sval); + struct symbol *sym; + int i; + + sym = lookup_symbol_2 (name, 0, VAR_NAMESPACE); + if (sym) + { + write_exp_elt (OP_VAR_VALUE); + write_exp_elt (sym); + write_exp_elt (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) + { + write_exp_elt (OP_LONG); + write_exp_elt (builtin_type_int); + write_exp_elt (misc_function_vector[i].address); + write_exp_elt (OP_LONG); + write_exp_elt (UNOP_MEMVAL); + write_exp_elt (builtin_type_char); + write_exp_elt (UNOP_MEMVAL); + } + else + if (symtab_list == 0) + error ("No symbol table is loaded. Use the \"symbol-file\" command."); + else + error ("No symbol \"%s\" in current context.", name); + } break; +case 64: +# line 512 "expread.y" +{ struct symbol *sym; + sym = lookup_symbol_1 (copy_name (yypvt[-0].sval), + expression_context_block, + VAR_NAMESPACE); + if (sym) + { + write_exp_elt (OP_VAR_VALUE); + write_exp_elt (sym); + write_exp_elt (OP_VAR_VALUE); + } + else + { + register char *arg = copy_name (yypvt[-0].sval); + register int i; + int v, val; + /* C++: see if it hangs off of `this'. Must + not inadvertently convert from a method call + to data ref. */ + v = (int)value_of_this (0); + if (v) + { + val = check_field (v, arg); + if (val) + { + write_exp_elt (OP_THIS); + write_exp_elt (OP_THIS); + write_exp_elt (STRUCTOP_PTR); + write_exp_string (yypvt[-0].sval); + write_exp_elt (STRUCTOP_PTR); + break; + } + } + sym = lookup_symbol_2 (arg, 0, VAR_NAMESPACE); + if (sym) + { + write_exp_elt (OP_VAR_VALUE); + write_exp_elt (sym); + write_exp_elt (OP_VAR_VALUE); + break; /* YACC-dependent */ + } + for (i = 0; i < misc_function_count; i++) + if (!strcmp (misc_function_vector[i].name, arg)) + break; + + if (i < misc_function_count) + { + write_exp_elt (OP_LONG); + write_exp_elt (builtin_type_int); + write_exp_elt (misc_function_vector[i].address); + write_exp_elt (OP_LONG); + write_exp_elt (UNOP_MEMVAL); + write_exp_elt (builtin_type_char); + write_exp_elt (UNOP_MEMVAL); + } + else + if (symtab_list == 0) + error ("No symbol table is loaded. Use the \"symbol-file\" command."); + else + error ("No symbol \"%s\" in current context.", + copy_name (yypvt[-0].sval)); + } + } break; +case 66: +# line 578 "expread.y" +{ yyval.tval = lookup_pointer_type (yypvt[-1].tval); } break; +case 67: +# line 580 "expread.y" +{ yyval.tval = lookup_reference_type (yypvt[-1].tval); } break; +case 68: +# line 582 "expread.y" +{ yyval.tval = lookup_member_type (builtin_type_int, yypvt[-2].tval); } break; +case 69: +# line 584 "expread.y" +{ yyval.tval = lookup_member_type (yypvt[-5].tval, yypvt[-3].tval); } break; +case 70: +# line 586 "expread.y" +{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-7].tval, 0), yypvt[-5].tval); } break; +case 71: +# line 588 "expread.y" +{ yyval.tval = lookup_member_type (lookup_function_type (yypvt[-8].tval, yypvt[-1].tvec), yypvt[-6].tval); + free (yypvt[-1].tvec); } break; +case 72: +# line 594 "expread.y" +{ yyval.tval = lookup_typename (copy_name (yypvt[-0].sval), + expression_context_block, 0); } break; +case 73: +# line 597 "expread.y" +{ yyval.tval = lookup_struct (copy_name (yypvt[-0].sval), + expression_context_block); } break; +case 74: +# line 600 "expread.y" +{ yyval.tval = lookup_union (copy_name (yypvt[-0].sval), + expression_context_block); } break; +case 75: +# line 603 "expread.y" +{ yyval.tval = lookup_enum (copy_name (yypvt[-0].sval), + expression_context_block); } break; +case 76: +# line 606 "expread.y" +{ yyval.tval = lookup_unsigned_typename (copy_name (yypvt[-0].sval)); } break; +case 77: +# line 611 "expread.y" +{ yyval.tvec = (struct type **)xmalloc (sizeof (struct type *) * 2); + yyval.tvec[0] = (struct type *)0; + yyval.tvec[1] = yypvt[-0].tval; + } break; +case 78: +# line 616 "expread.y" +{ int len = sizeof (struct type *) * ++(yypvt[-2].ivec[0]); + yyval.tvec = (struct type **)xrealloc (yypvt[-2].tvec, len); + yyval.tvec[yyval.ivec[0]] = yypvt[-0].tval; + } break; + } + goto yystack; /* stack new state and value */ + + } diff --git a/gdb/expread.y b/gdb/expread.y index b112cbce51b..97628efb176 100644 --- a/gdb/expread.y +++ b/gdb/expread.y @@ -43,6 +43,7 @@ static int expout_ptr; static int yylex (); static yyerror (); static void write_exp_elt (); +static void write_exp_elt2 (); static void write_exp_string (); static void start_arglist (); static int end_arglist (); @@ -93,10 +94,14 @@ struct stoken struct block *bval; enum exp_opcode opcode; struct internalvar *ivar; + + struct type **tvec; + int *ivec; } %type exp exp1 start variable %type type typebase +%type nonempty_typelist %type block %token INT CHAR @@ -122,6 +127,9 @@ struct stoken %token ASSIGN_MODIFY +/* C++ */ +%token THIS + %left ',' %left ABOVE_COMMA %right '=' ASSIGN_MODIFY @@ -196,12 +204,20 @@ exp : exp ARROW name write_exp_elt (STRUCTOP_PTR); } ; +exp : exp ARROW '*' exp + { write_exp_elt (STRUCTOP_MPTR); } + ; + exp : exp '.' name { write_exp_elt (STRUCTOP_STRUCT); write_exp_string ($3); write_exp_elt (STRUCTOP_STRUCT); } ; +exp : exp '.' '*' exp + { write_exp_elt (STRUCTOP_MEMBER); } + ; + exp : exp '[' exp1 ']' { write_exp_elt (BINOP_SUBSCRIPT); } ; @@ -352,7 +368,7 @@ exp : CHAR exp : FLOAT { write_exp_elt (OP_DOUBLE); write_exp_elt (builtin_type_double); - write_exp_elt ($1); + write_exp_elt2 ($1); write_exp_elt (OP_DOUBLE); } ; @@ -390,8 +406,17 @@ exp : STRING write_exp_elt (OP_STRING); } ; +/* C++. */ +exp : THIS + { write_exp_elt (OP_THIS); + write_exp_elt (OP_THIS); } + ; + +/* end of C++. */ + block : name - { struct symtab *tem = lookup_symtab (copy_name ($1)); + { + struct symtab *tem = lookup_symtab (copy_name ($1)); struct symbol *sym; if (tem) @@ -406,34 +431,88 @@ block : name else error ("No file or function \"%s\".", copy_name ($1)); - }} + } + } ; block : block COLONCOLON name - { struct symbol *tem + { + struct symbol *tem = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE); if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) error ("No function \"%s\" in specified context.", copy_name ($3)); - $$ = SYMBOL_BLOCK_VALUE (tem); } + $$ = SYMBOL_BLOCK_VALUE (tem); + } ; variable: block COLONCOLON name - { struct symbol *sym; + { + struct symbol *sym; sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE); if (sym == 0) error ("No symbol \"%s\" in specified context.", copy_name ($3)); write_exp_elt (OP_VAR_VALUE); write_exp_elt (sym); - write_exp_elt (OP_VAR_VALUE); } + write_exp_elt (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 (OP_SCOPE); + write_exp_elt (type); + write_exp_string ($3); + write_exp_elt (OP_SCOPE); + } + | COLONCOLON name + { + char *name = copy_name ($2); + struct symbol *sym; + int i; + + sym = lookup_symbol_2 (name, 0, VAR_NAMESPACE); + if (sym) + { + write_exp_elt (OP_VAR_VALUE); + write_exp_elt (sym); + write_exp_elt (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) + { + write_exp_elt (OP_LONG); + write_exp_elt (builtin_type_int); + write_exp_elt (misc_function_vector[i].address); + write_exp_elt (OP_LONG); + write_exp_elt (UNOP_MEMVAL); + write_exp_elt (builtin_type_char); + write_exp_elt (UNOP_MEMVAL); + } + else + if (symtab_list == 0) + error ("No symbol table is loaded. Use the \"symbol-file\" command."); + else + error ("No symbol \"%s\" in current context.", name); + } ; variable: NAME { struct symbol *sym; - sym = lookup_symbol (copy_name ($1), - expression_context_block, - VAR_NAMESPACE); + sym = lookup_symbol_1 (copy_name ($1), + expression_context_block, + VAR_NAMESPACE); if (sym) { write_exp_elt (OP_VAR_VALUE); @@ -444,6 +523,32 @@ variable: NAME { register char *arg = copy_name ($1); register int i; + int v, val; + /* C++: see if it hangs off of `this'. Must + not inadvertently convert from a method call + to data ref. */ + v = (int)value_of_this (0); + if (v) + { + val = check_field (v, arg); + if (val) + { + write_exp_elt (OP_THIS); + write_exp_elt (OP_THIS); + write_exp_elt (STRUCTOP_PTR); + write_exp_string ($1); + write_exp_elt (STRUCTOP_PTR); + break; + } + } + sym = lookup_symbol_2 (arg, 0, VAR_NAMESPACE); + if (sym) + { + write_exp_elt (OP_VAR_VALUE); + write_exp_elt (sym); + write_exp_elt (OP_VAR_VALUE); + break; /* YACC-dependent */ + } for (i = 0; i < misc_function_count; i++) if (!strcmp (misc_function_vector[i].name, arg)) break; @@ -471,6 +576,17 @@ variable: NAME type : typebase | type '*' { $$ = lookup_pointer_type ($1); } + | type '&' + { $$ = lookup_reference_type ($1); } + | 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, 0), $3); } + | type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')' + { $$ = lookup_member_type (lookup_function_type ($1, $8), $3); + free ($8); } ; typebase @@ -490,6 +606,19 @@ typebase { $$ = lookup_unsigned_typename (copy_name ($2)); } ; +nonempty_typelist + : type + { $$ = (struct type **)xmalloc (sizeof (struct type *) * 2); + $$[0] = (struct type *)0; + $$[1] = $1; + } + | nonempty_typelist ',' type + { int len = sizeof (struct type *) * ++($1[0]); + $$ = (struct type **)xrealloc ($1, len); + $$[$$[0]] = $3; + } + ; + name : NAME | TYPENAME ; @@ -543,10 +672,16 @@ free_funcalls () /* Add one element to the end of the expression. */ +/* To avoid a bug in the Sun 4 compiler, we pass only things that + can fit into a single register through here. */ static void write_exp_elt (expelt) - union exp_element expelt; + /* union exp_element expelt; */ + long expelt; { + union exp_element temp; + temp.longconst = expelt; + if (expout_ptr >= expout_size) { expout_size *= 2; @@ -554,7 +689,25 @@ write_exp_elt (expelt) sizeof (struct expression) + expout_size * sizeof (union exp_element)); } - expout->elts[expout_ptr++] = expelt; + expout->elts[expout_ptr++] = /* expelt */ temp; +} + +/* Things that take more space must come through here. */ +static void +write_exp_elt2 (expelt) + double expelt; +{ + union exp_element temp; + temp.doubleconst = 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++] = temp; } /* Add a string constant to the end of the expression. @@ -904,13 +1057,23 @@ yylex () { return STRUCT; } - if (namelen == 5 && !strncmp (tokstart, "union", 5)) + if (namelen == 5) { - return UNION; + if (!strncmp (tokstart, "union", 5)) + { + return UNION; + } } - if (namelen == 4 && !strncmp (tokstart, "enum", 4)) + if (namelen == 4) { - return ENUM; + if (!strncmp (tokstart, "enum", 4)) + { + return ENUM; + } + if (!strncmp (tokstart, "this", 4)) + { + return THIS; + } } if (namelen == 6 && !strncmp (tokstart, "sizeof", 6)) { @@ -991,10 +1154,20 @@ length_of_subexp (expr, endpos) 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; @@ -1025,7 +1198,6 @@ length_of_subexp (expr, endpos) oplen = 3 + ((expr->elts[endpos - 2].longconst + sizeof (union exp_element)) / sizeof (union exp_element)); - break; case TERNOP_COND: @@ -1037,6 +1209,11 @@ length_of_subexp (expr, endpos) args = 2; break; + /* C++ */ + case OP_THIS: + oplen = 2; + break; + default: args = 1 + (i < (int) BINOP_END); } @@ -1074,6 +1251,13 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg) 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; @@ -1116,6 +1300,11 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg) args = 2; break; + /* C++ */ + case OP_THIS: + oplen = 2; + break; + default: args = 1 + ((int) opcode < (int) BINOP_END); } diff --git a/gdb/expression.h b/gdb/expression.h index 7a7bd83f47d..0fac7be1d12 100644 --- a/gdb/expression.h +++ b/gdb/expression.h @@ -60,6 +60,20 @@ enum exp_opcode BINOP_COMMA, /* , */ BINOP_SUBSCRIPT, /* x[y] */ BINOP_EXP, /* Exponentiation */ + +/* C++. */ + BINOP_MIN, /* ? */ + BINOP_SCOPE, /* :: */ + + /* STRUCTOP_MEMBER is used for pointer-to-member constructs. + X . * Y translates into X STRUCTOP_MEMBER Y. */ + STRUCTOP_MEMBER, + /* STRUCTOP_MPTR is used for pointer-to-member constructs + when X is a pointer instead of an aggregate. */ + STRUCTOP_MPTR, +/* end of C++. */ + BINOP_END, BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on. @@ -144,6 +158,17 @@ enum exp_opcode (after the string), followed by another STRUCTOP_... code. */ STRUCTOP_STRUCT, STRUCTOP_PTR, + +/* C++ */ + /* OP_THIS is just a placeholder for the class instance variable. + It just comes in a tight (OP_THIS, OP_THIS) pair. */ + OP_THIS, + + /* OP_SCOPE surrounds a type name and a field name. The type + name is encoded as one element, but the field name stays as + a string, which, of course, is variable length. */ + OP_SCOPE, + }; union exp_element diff --git a/gdb/findvar.c b/gdb/findvar.c index e5f9b4aa336..d7ccdc495a9 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -176,6 +176,12 @@ write_register (regno, val) int regno, val; { /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */ +#if defined(sun4) + /* This is a no-op on a Sun 4. */ + if (regno == 0) + return; +#endif + *(int *) ®isters[REGISTER_BYTE (regno)] = val; if (have_inferior_p ()) @@ -253,6 +259,7 @@ read_var_value (var, frame) return v; case LOC_REGISTER: + case LOC_REGPARM: { char raw_buffer[MAX_REGISTER_RAW_SIZE]; char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; @@ -356,6 +363,7 @@ locate_var_value (var, frame) SYMBOL_NAME (var)); case LOC_REGISTER: + case LOC_REGPARM: addr = find_saved_register (frame, val); if (addr != 0) { diff --git a/gdb/frame.h b/gdb/frame.h index 3f51c459312..acaea8ff26b 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -32,6 +32,10 @@ struct frame_info CORE_ADDR pc; /* The frame called by the frame we are describing, or 0. */ FRAME next_frame; + + /* The frame called by `next_frame', or 0 if there is none + (or `next_frame' is 0). */ + FRAME next_next_frame; }; /* Describe the saved registers of a frame. */ diff --git a/gdb/gdb.ideas b/gdb/gdb.ideas index 96ba6628541..1b3b12fb3ad 100644 --- a/gdb/gdb.ideas +++ b/gdb/gdb.ideas @@ -1031,247 +1031,4 @@ if the symbols proved not to be static, and an auto-display should be disabled automatically when it is not in the block where the results would be meaningful. - -1,, -Received: from ai.ai.mit.edu by wheaties.ai.mit.edu; Sun, 8 May 88 12:52:31 EDT -Received: from prep.ai.mit.edu (TCP 20015020016) by AI.AI.MIT.EDU 8 May 88 05:38:21 EDT -Received: from lilac.Berkeley.EDU by prep.ai.mit.edu; Sun, 8 May 88 04:12:02 EST -Received: from web5h.berkeley.edu - by lilac.berkeley.edu (5.54 (CFC 4.22.3)/1.16.18) - id AA27424; Sun, 8 May 88 02:33:06 PDT -Received: by web5h.berkeley.edu (3.2/SMI-3.0DEV3.8MXl) - id AA05599; Sun, 8 May 88 02:33:41 PDT -Date: Sun, 8 May 88 02:33:41 PDT -From: phr%widow.Berkeley.EDU@lilac.berkeley.edu -Message-Id: <8805080933.AA05599@web5h.berkeley.edu> -To: bug-gdb@prep.ai.mit.edu -Subject: suggestion (gdb 2.4): print function names - -*** EOOH *** -Date: Sun, 8 May 88 02:33:41 PDT -From: phr%widow.Berkeley.EDU@lilac.berkeley.edu -To: bug-gdb@prep.ai.mit.edu -Subject: suggestion (gdb 2.4): print function names - -If p is a pointer to function, "print p" should print the name -of the function that p points to, as well as the numeric value. -Dbx does this. - - - -1,, -Received: from lilac.berkeley.edu by wheaties.ai.mit.edu; Wed, 11 May 88 23:14:39 EDT -Received: from web8e.berkeley.edu - by lilac.berkeley.edu (5.54 (CFC 4.22.3)/1.16.18) - id AA11864; Wed, 11 May 88 20:11:12 PDT -Received: by web8e.berkeley.edu (3.2/SMI-3.0DEV3.8MXl) - id AA06549; Wed, 11 May 88 20:11:44 PDT -Date: Wed, 11 May 88 20:11:44 PDT -From: phr%widow.Berkeley.EDU@lilac.berkeley.edu -Message-Id: <8805120311.AA06549@web8e.berkeley.edu> -To: rms@wheaties.ai.mit.edu -Subject: gdb suggestion - -*** EOOH *** -Date: Wed, 11 May 88 20:11:44 PDT -From: phr%widow.Berkeley.EDU@lilac.berkeley.edu -To: rms@wheaties.ai.mit.edu -Subject: gdb suggestion - -If the process signal mask of a program is saved in the core dump, -then gdb should have a way to read it. I have an xemacs that hangs -in a blocking read from XCreateWindow when I run it from the csh, -but works fine when run under gdb. (Does this mean a gdb bug?). - - -1, answered,, -Return-Path: -Received: by sugar-smacks.ai.mit.edu; Tue, 24 May 88 00:34:01 EDT -Date: Tue, 24 May 88 00:34:01 EDT -From: tmb@wheaties.ai.mit.edu (Thomas M. Breuel) -Message-Id: <8805240434.AA02268@sugar-smacks.ai.mit.edu> -To: rms -Subject: problem with gdb... - -*** EOOH *** -Return-Path: -Date: Tue, 24 May 88 00:34:01 EDT -From: tmb@wheaties.ai.mit.edu (Thomas M. Breuel) -To: rms -Subject: problem with gdb... - -When tracing a program that forks, the breakpoints aren't removed in the -child and it dies with a trace/bpt trap. Isn't there a more proper way to -handle this? - - Thomas. - - -1, forwarded, answered,, -Received: from ATHENA (ATHENA.MIT.EDU) by wheaties.ai.mit.edu; Sat, 25 Jun 88 04:02:57 EDT -From: jbs@athena.mit.edu -Received: by ATHENA.MIT.EDU (5.45/4.7) id AA21892; Sat, 25 Jun 88 04:00:11 EDT -Received: by BRIDGETOWN.MIT.EDU (5.45/4.7) id AA13640; Sat, 25 Jun 88 03:59:57 EDT -Date: Sat, 25 Jun 88 03:59:57 EDT -Message-Id: <8806250759.AA13640@BRIDGETOWN.MIT.EDU> -To: rms@wheaties.ai.mit.edu -Subject: gdb suggestion - -*** EOOH *** -From: jbs@athena.mit.edu -Date: Sat, 25 Jun 88 03:59:57 EDT -To: rms@wheaties.ai.mit.edu -Subject: gdb suggestion - -Debugging X toolkit stuff involves looking at structures that fill up -several screens. GDB would be a lot easier to use if it supported -some sort of pretty-printing of these structures. - -Jeff - - -1, forwarded,, -Received: from prep.ai.mit.edu by wheaties.ai.mit.edu; Thu, 23 Jun 88 04:32:12 EDT -Received: from ic.Berkeley.EDU by prep.ai.mit.edu; Thu, 23 Jun 88 03:19:27 EST -Received: by ic.berkeley.edu (5.57/1.28) - id AA02077; Thu, 23 Jun 88 01:28:08 PDT -Date: Thu, 23 Jun 88 01:28:08 PDT -From: faustus@ic.berkeley.edu (Wayne A. Christopher) -Message-Id: <8806230828.AA02077@ic.berkeley.edu> -To: rms@prep.ai.mit.edu -Subject: gdb request - -*** EOOH *** -Date: Thu, 23 Jun 88 01:28:08 PDT -From: faustus@ic.berkeley.edu (Wayne A. Christopher) -To: rms@prep.ai.mit.edu -Subject: gdb request - -One suggestion for future versions of gdb -- the trace command of dbx is very -useful, and a lot easier to use than the "commands" feature in gdb. Although -it's not necessary, it would be nice to have it. - - Wayne - - -1, forwarded,, -Return-Path: -Received: from prep.ai.mit.edu by life.ai.mit.edu; Sun, 24 Jul 88 03:40:33 EDT -Received: from scruff.Berkeley.EDU by prep.ai.mit.edu; Sun, 24 Jul 88 02:17:27 EST -Received: by scruff.berkeley.edu (5.57/1.28) - id AA19389; Sun, 24 Jul 88 00:35:41 PDT -Date: Sun, 24 Jul 88 00:35:41 PDT -From: faustus@scruff.berkeley.edu (Wayne A. Christopher) -Message-Id: <8807240735.AA19389@scruff.berkeley.edu> -To: rms@prep.ai.mit.edu -Subject: gdb feature - -*** EOOH *** -Return-Path: -Date: Sun, 24 Jul 88 00:35:41 PDT -From: faustus@scruff.berkeley.edu (Wayne A. Christopher) -To: rms@prep.ai.mit.edu -Subject: gdb feature - -It would be nice if I could stop and background a process running under -gdb. Now gdb lets the process get the ^Z and gives me a prompt, instead -of stopping also. - - Wayne - - -1,, -Return-Path: -Received: from prep.ai.mit.edu by life.ai.mit.edu; Tue, 30 Aug 88 23:18:51 EDT -Received: from ATHENA.MIT.EDU by prep.ai.mit.edu; Tue, 30 Aug 88 21:44:58 EST -Received: by ATHENA.MIT.EDU (5.45/4.7) id AA29972; Tue, 30 Aug 88 23:16:03 EDT -Received: by E40-342A-3 (5.45/4.7) - id AA10004; Tue, 30 Aug 88 23:15:58 EDT -Date: Tue, 30 Aug 88 23:15:58 EDT -From: Bill Sommerfeld -Message-Id: <8808310315.AA10004@E40-342A-3> -To: bug-gdb@prep.ai.mit.edu -Subject: SET_STACK_LIMIT_HUGE. - -*** EOOH *** -Return-Path: -Date: Tue, 30 Aug 88 23:15:58 EDT -From: Bill Sommerfeld -To: bug-gdb@prep.ai.mit.edu -Subject: SET_STACK_LIMIT_HUGE. - -I just had the pleasure of figuring out why a program which worked -under GDB failed (with a segv) when run under the shell. It turns out -that it was allocating too much space in the stack, and dying with a -segmentation violation when it overran the stack. - -I note that gdb/main.c unlimits the stack, presumably to allow gdb to -use alloca to its heart's content. This is well and good, but in the -interests of making the execution and debugging environments -functionally identical, could it at least set the limit back down to -what it used to be when it starts the child process? - - - Bill - - -1, answered,, -Return-Path: -Received: from hobbes.ai.mit.edu by wheaties.ai.mit.edu; Thu, 1 Sep 88 23:13:03 EDT -Received: from localhost.ARPA by hobbes.ai.mit.edu; Thu, 1 Sep 88 23:08:41 est -Message-Id: <8809020408.AA09913@hobbes.ai.mit.edu> -To: rms@wheaties.ai.mit.edu (Richard Stallman) -Cc: randy@wheaties.ai.mit.edu -Subject: Re: GDB work that needs to be done -In-Reply-To: Your message of Thu, 01 Sep 88 19:23:47 -0400. - <8809012323.AA01639@sugar-bombs.ai.mit.edu> -Date: Thu, 01 Sep 88 23:08:39 +0900 -From: randy@wheaties.ai.mit.edu - -*** EOOH *** -Return-Path: -To: rms@wheaties.ai.mit.edu (Richard Stallman) -Cc: randy@wheaties.ai.mit.edu -Subject: Re: GDB work that needs to be done -In-Reply-To: Your message of Thu, 01 Sep 88 19:23:47 -0400. - <8809012323.AA01639@sugar-bombs.ai.mit.edu> -Date: Thu, 01 Sep 88 23:08:39 +0900 -From: randy@wheaties.ai.mit.edu - - -Also: - -5. Step until past current line or out of stack frame. - - -1,, -Return-Path: -Received: by sugar-bombs.ai.mit.edu; Fri, 2 Sep 88 12:43:28 EDT -Date: Fri, 2 Sep 88 12:43:28 EDT -From: rms@wheaties.ai.mit.edu (Richard Stallman) -Message-Id: <8809021643.AA00263@sugar-bombs.ai.mit.edu> -To: randy@wheaties.ai.mit.edu -Cc: rms -In-Reply-To: randy@wheaties.ai.mit.edu's message of Thu, 01 Sep 88 23:08:39 +0900 <8809020408.AA09913@hobbes.ai.mit.edu> -Subject: GDB work that needs to be done - -*** EOOH *** -Return-Path: -Date: Fri, 2 Sep 88 12:43:28 EDT -From: rms@wheaties.ai.mit.edu (Richard Stallman) -To: randy@wheaties.ai.mit.edu -Cc: rms -In-Reply-To: randy@wheaties.ai.mit.edu's message of Thu, 01 Sep 88 23:08:39 +0900 <8809020408.AA09913@hobbes.ai.mit.edu> -Subject: GDB work that needs to be done - - Step until past current line or out of stack frame. - -I think this should be a command called `until': - - until LINE run until line LINE. - until run until reach the following line. - -It can work by setting a temporary (delete when hit) breakpoint -at the specified destination and then doing `finish'. - -  \ No newline at end of file diff --git a/gdb/infcmd.c b/gdb/infcmd.c index d87afa4eebd..4f7230ced2c 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -299,6 +299,7 @@ jump_command (arg, from_tty) int from_tty; { register CORE_ADDR addr; + struct symtabs_and_lines sals; struct symtab_and_line sal; ERROR_NO_INFERIOR; @@ -306,7 +307,14 @@ jump_command (arg, from_tty) if (!arg) error_no_arg ("starting address"); - sal = decode_line_spec (arg, 1); + sals = decode_line_spec (arg, 1); + if (sals.nelts != 1) + { + error ("Unreasonable jump request"); + } + + sal = sals.sals[0]; + free (sals.sals); if (sal.symtab == 0 && sal.pc == 0) error ("No source file has been specified."); @@ -458,7 +466,7 @@ finish_command (arg, from_tty) /* Find the function we will return from. */ - fi = get_frame_info (fi.next_frame); + fi = get_frame_info (fi.next_frame, fi.next_next_frame); function = find_pc_function (fi.pc); if (from_tty) @@ -613,6 +621,9 @@ write_pc (val) CORE_ADDR val; { write_register (PC_REGNUM, (long) val); +#ifdef NPC_REGNUM + write_register (NPC_REGNUM, (long) val+4); +#endif } char *reg_names[] = REGISTER_NAMES; @@ -670,7 +681,7 @@ registers_info (addr_exp) /* If virtual format is floating, print it that way. */ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT && ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i))) - val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0); + val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0, 1); /* Else if virtual format is too long for printf, print in hex a byte at a time. */ else if (REGISTER_VIRTUAL_SIZE (i) > sizeof (long)) diff --git a/gdb/inflow.c b/gdb/inflow.c index 386a2e15150..11e5e92153c 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -461,7 +461,15 @@ resume (step, signal) remote_resume (step, signal); else { +#ifdef NO_SINGLE_STEP + if (step) + { + single_step (signal); + } + else ptrace (7, inferior_pid, 1, signal); +#else ptrace (step ? 9 : 7, inferior_pid, 1, signal); +#endif if (errno) perror_with_name ("ptrace"); } @@ -514,6 +522,7 @@ fetch_inferior_registers () ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers); ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers); +#if defined(sun2) || defined(sun3) bcopy (&inferior_registers, registers, 16 * 4); bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], sizeof inferior_fp_registers.fps_regs); @@ -522,6 +531,25 @@ fetch_inferior_registers () bcopy (&inferior_fp_registers.fps_control, ®isters[REGISTER_BYTE (FPC_REGNUM)], sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs); +#endif +#if defined(sun4) + registers[REGISTER_BYTE (0)] = 0; + bcopy (&inferior_registers.r_g1, ®isters[REGISTER_BYTE (1)], 15 * 4); + bcopy (&inferior_fp_registers, ®isters[REGISTER_BYTE (FP0_REGNUM)], + sizeof inferior_fp_registers.fpu_fr); + *(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; +/* *(int *)®isters[REGISTER_BYTE (RP_REGNUM)] = + inferior_registers.r_o7 + 8; + bcopy (&inferior_fp_registers.Fpu_fsr, + ®isters[REGISTER_BYTE (FPS_REGNUM)], + sizeof (FPU_FSR_TYPE)); */ + read_inferior_memory (inferior_registers.r_sp, + ®isters[REGISTER_BYTE (16)], + 16*4); +#endif } } @@ -540,17 +568,61 @@ store_inferior_registers (regno) remote_store_registers (registers); else { - 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); + int in_regs = 1, in_fpregs = 1, in_fparegs, in_cpregs = 1; - ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers); - ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers); +#if defined(sun2) || defined(sun3) + if (in_regs) + { + 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)]; + } + if (in_fpregs) + { + 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); + } + if (in_regs) + ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers); + if (in_fpregs) + ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers); +#endif +#if defined(sun4) + if (regno >= 0) + if (FP0_REGNUM <= regno && regno <= FP0_REGNUM + 32) + in_regs = 0; + else + in_fpregs = 0; + + if (in_regs) + { + bcopy (®isters[REGISTER_BYTE (1)], &inferior_registers.r_g1, 15 * 4); + 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)]; + write_inferior_memory (*(int *)®isters[REGISTER_BYTE (SP_REGNUM)], + ®isters[REGISTER_BYTE (16)], + 16*4); + } + if (in_fpregs) + { + 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 (in_regs) + ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers); + if (in_fpregs) + ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers); +#endif } } diff --git a/gdb/infrun.c b/gdb/infrun.c index 596e17c4abc..67b0c174baa 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -29,7 +29,6 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include #include #include -#include #ifdef UMAX_PTRACE #include @@ -117,6 +116,14 @@ static int running_in_shell; static int stop_print_frame; +#ifdef NO_SINGLE_STEP +/* Non-zero if we just simulated a single-step ptrace call. This is + needed because we cannot remove the breakpoints in the inferior + process until after the `wait' in `wait_for_inferior'. + Used for sun4. */ +int one_stepped; +#endif /* NO_SINGLE_STEP */ + static void insert_step_breakpoint (); static void remove_step_breakpoint (); static void wait_for_inferior (); @@ -178,7 +185,12 @@ proceed (addr, signal, step) oneproc = 1; } else - write_register (PC_REGNUM, addr); + { + write_register (PC_REGNUM, addr); +#ifdef NPC_REGNUM + write_register (NPC_REGNUM, addr+4); +#endif + } if (trap_expected_after_continue) { @@ -351,6 +363,13 @@ wait_for_inferior () continue; } +#ifdef NO_SINGLE_STEP + if (one_stepped) + { + single_step (0); + } +#endif /* NO_SINGLE_STEP */ + pc_changed = 0; fetch_inferior_registers (); stop_pc = read_pc (); @@ -451,6 +470,9 @@ wait_for_inferior () { stop_pc -= DECR_PC_AFTER_BREAK; write_register (PC_REGNUM, stop_pc); +#ifdef NPC_REGNUM + write_register (NPC_REGNUM, stop_pc + 4); +#endif pc_changed = 0; } } @@ -463,6 +485,9 @@ wait_for_inferior () { stop_pc -= DECR_PC_AFTER_BREAK; write_register (PC_REGNUM, stop_pc); +#ifdef NPC_REGNUM + write_register (PC_REGNUM, stop_pc + 4); +#endif pc_changed = 0; } } @@ -766,13 +791,7 @@ Further execution is probably impossible.\n"); if (running_in_shell) { if (stop_signal == SIGSEGV) - { - char *exec_file = (char *) get_exec_file (1); - - if (access (exec_file, X_OK) != 0) - printf ("The file \"%s\" is not executable.\n", exec_file); - else - printf ("\ + printf ("\ You have just encountered a bug in \"sh\". GDB starts your program\n\ by running \"sh\" with a command to exec your program.\n\ This is so that \"sh\" will process wildcards and I/O redirection.\n\ @@ -784,7 +803,6 @@ some variables whose values are large; then do \"run\" again.\n\ \n\ If that works, you might want to put those \"unset-env\" commands\n\ into a \".gdbinit\" file in this directory so they will happen every time.\n"); - } /* Don't confuse user with his program's symbols on sh's data. */ stop_print_frame = 0; } @@ -1026,4 +1044,148 @@ Pass and Stop may be combined."); #endif /* SIGURG */ } +#ifdef NO_SINGLE_STEP +/* This code was written by Gary Beihl (beihl@mcc.com). + It was modified by Michael Tiemann (tiemann@corto.inria.fr). */ + +/* Simulate single-step ptrace call for sun4. */ + +typedef enum +{ + b_error, not_branch, bicc, bicca, ba, baa, ticc, ta, +} branch_type; + +static CORE_ADDR next_pc, pc8, target; +static int brkpc8, brktrg; +typedef char binsn_quantum[sizeof break_insn]; +static binsn_quantum break_mem[3]; + +int +single_step (signal) + int signal; +{ + branch_type br, isabranch(); + + next_pc = read_register (NPC_REGNUM); + pc8 = read_register (PC_REGNUM) + 8; /* branch not taken */ + + if (!one_stepped) + { + /* Always set breakpoint for NPC. */ + read_memory (next_pc, break_mem[0], sizeof break_insn); + write_memory (next_pc, break_insn, sizeof break_insn); + + /* printf ("set break at %x\n",next_pc); */ + br = isabranch (pc8 - 8, &target); + brkpc8 = brktrg = 0; + + if (br == bicca && pc8 != next_pc) + { + /* Handle branches with care */ + brkpc8 = 1; + read_memory (pc8, break_mem[1], sizeof break_insn); + write_memory (pc8, break_insn, sizeof break_insn); + } + else if (br == baa && target != next_pc) + { + brktrg = 1; + read_memory (target, break_mem[2], sizeof break_insn); + write_memory (target, break_insn, sizeof break_insn); + } + + /* Let it go */ + ptrace (7, inferior_pid, 1, signal); + one_stepped = 1; + return; + } + else + { + /* Remove breakpoints */ + write_memory (next_pc, break_mem[0], sizeof break_insn); + + if (brkpc8) + { + write_memory (pc8, break_mem[1], sizeof break_insn); + } + if (brktrg) + { + write_memory (target, break_mem[2], sizeof break_insn); + } + one_stepped = 0; + } +} + +#endif /* NO_SINGLE_STEP */ + +static int save_insn_opcodes[] = { 0x03000000, 0x82007ee0, 0x9de38001, 0x03000000, 0x82007ee0, 0x91d02001, 0x01000000 }; + +void +do_save_insn (size) + int size; +{ + int g1 = read_register (1); + CORE_ADDR sp = read_register (SP_REGNUM); + CORE_ADDR pc = read_register (PC_REGNUM); +#ifdef NPC_REGNUM + CORE_ADDR npc = read_register (NPC_REGNUM); +#endif + CORE_ADDR fake_pc = sp - sizeof (save_insn_opcodes); + save_insn_opcodes[0] = 0x03000000 | ((-size >> 12) & 0x3fffff); + save_insn_opcodes[1] = 0x82006000 | (-size & 0x3ff); + save_insn_opcodes[3] = 0x03000000 | ((g1 >> 12) & 0x3fffff); + save_insn_opcodes[4] = 0x82006000 | (g1 & 0x3ff); + write_memory (fake_pc, save_insn_opcodes, sizeof (save_insn_opcodes)); + clear_proceed_status (); + stop_after_trap = 1; + + proceed (fake_pc, 0, 0); + + write_register (PC_REGNUM, pc); +#ifdef NPC_REGNUM + write_register (NPC_REGNUM, npc); +#endif +} + +static int restore_insn_opcodes[] = { 0x81e80000, 0x91d02001, 0x01000000 }; + +void +do_restore_insn (raw_buffer) + char raw_buffer[]; +{ + CORE_ADDR pc = read_memory_integer (*(int *)&raw_buffer[REGISTER_BYTE (PC_REGNUM)], 4); + CORE_ADDR sp = read_register (SP_REGNUM); +#ifdef NPC_REGNUM + CORE_ADDR npc = *(int *)&raw_buffer[REGISTER_BYTE (NPC_REGNUM)] != 0 + ? read_memory_integer (*(int *)&raw_buffer[REGISTER_BYTE (NPC_REGNUM)], 4) : pc + 4; +#endif + CORE_ADDR fake_pc = sp - sizeof (restore_insn_opcodes); + int saved_stop_stack_dummy = stop_stack_dummy; + + if (*(int *)&raw_buffer[REGISTER_BYTE (PC_REGNUM)] == 0) + abort (); + + write_memory (fake_pc, restore_insn_opcodes, sizeof (restore_insn_opcodes)); + clear_proceed_status (); + stop_after_trap = 1; + + proceed (fake_pc, 0, 0); + + stop_stack_dummy = saved_stop_stack_dummy; + write_register (PC_REGNUM, pc); +#ifdef NPC_REGNUM + write_register (NPC_REGNUM, npc); +#endif + + /* Select innermost stack frame except on return from a stack dummy routine, + or if the program has exited. */ + if (!stop_stack_dummy) + { + select_frame (stop_frame, 0); + } + else + { + select_frame (read_register (FP_REGNUM), 0); + } +} + END_FILE diff --git a/gdb/m-hp9k320.h b/gdb/m-hp9k320.h index 3b83833c023..20209ce0056 100644 --- a/gdb/m-hp9k320.h +++ b/gdb/m-hp9k320.h @@ -256,13 +256,13 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4)) #define FRAME_ARGS_ADDRESS(fi) (fi.frame) @@ -277,7 +277,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) #if 0 #define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ +{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \ register int insn = 0177777 & read_memory_integer (pc, 2); \ val = 0; \ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ diff --git a/gdb/m-hp9k320bsd.h b/gdb/m-hp9k320bsd.h index 66c9b3b43fb..221d3c55431 100644 --- a/gdb/m-hp9k320bsd.h +++ b/gdb/m-hp9k320bsd.h @@ -264,13 +264,13 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4)) #define FRAME_ARGS_ADDRESS(fi) (fi.frame) @@ -285,7 +285,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) #if 0 #define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ +{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \ register int insn = 0177777 & read_memory_integer (pc, 2); \ val = 0; \ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ diff --git a/gdb/m-init.h b/gdb/m-init.h index 5f71ea145b5..a1edc20e7ec 100644 --- a/gdb/m-init.h +++ b/gdb/m-init.h @@ -2,4 +2,4 @@ /* This is how the size of an individual .o file's text segment is rounded on a sun. */ -#define FILEADDR_ROUND(addr) ((addr + 3) & -4) +#define FILEADDR_ROUND(addr) ((addr + 7) & -8) diff --git a/gdb/m-isi.h b/gdb/m-isi.h deleted file mode 100644 index 1e2bb848d3d..00000000000 --- a/gdb/m-isi.h +++ /dev/null @@ -1,533 +0,0 @@ -/* -Date: Thu, 2 Apr 87 00:02:42 EST -From: crl@maxwell.physics.purdue.edu (Charles R. LaBrec) -Message-Id: <8704020502.AA01744@maxwell.physics.purdue.edu> -To: bug-gdb@prep.ai.mit.edu -Subject: gdb for ISI Optimum V - -Here is an m-isi-ov.h file for gdb version 2.1. It supports the 68881 -registers, and tracks down the function prologue (since the ISI cc -puts it at the end of the function and branches to it if not -optimizing). Also included are diffs to core.c, findvar.c, and -inflow.c, since the original code assumed that registers are an int in -the user struct, which isn't the case for 68020's with 68881's (and -not using the NEW_SUN_PTRACE). I have not fixed the bugs associated -with the other direction (writing registers back to the user struct). -I have also included a diff that turns m68k-pinsn.c into isi-pinsn.c, -which is needed since the 3.05 release of as does not understand -floating point ops, and it compiles incorrectly under "cc -20" - -I have used gdb for a while now, and it seems to work relatively well, -but I do not guarantee that it is perfect. The more that use it, the -faster the bugs will get shaken out. One bug I know of is not in gdb, -but in the assembler. It seems to screw up the .stabs of variables. -For externs, this is not important since gdb uses the global symbol -value, but for statics, this makes gdb unable to find them. I am -currently trying to track it down. - -As an aside, I notice that only global functions are used as symbols -to print as relative addresses, i.e. "", and not -static functions, which end up printing as large offsets from the last -global one. Would there be a problem if static functions were also -recorded as misc functions in read_dbx_symtab? - -Charles LaBrec -crl @ maxwell.physics.purdue.edu - - Definitions to make GDB run on a ISI Optimum V (3.05) under 4.2bsd. - - Copyright (C) 1987 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! -*/ - - -/* Identify this machine */ -#ifndef ISI68K -#define ISI68K -#endif - -/* 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, 2); \ - if (op == 0047126) \ - pc += 4; /* Skip link #word */ \ - else if (op == 0044016) \ - pc += 6; /* Skip link #long */ \ - 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) - -/* 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 - -/* Address of end of stack space. */ - -#define STACK_END_ADDR 0x10000000 - -/* Stack grows downward. */ - -#define INNER_THAN < - -/* Sequence of bytes for breakpoint instruction. */ - -#define BREAKPOINT {0x4e, 0x4f} - -/* 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 - -/* Nonzero if instruction at PC is a return instruction. */ - -#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75) - -/* 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 - -/* Number of machine registers */ - -#define NUM_REGS 29 - -/* Initializer for an array of names of registers. - There should be NUM_REGS strings in this initializer. */ - -#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" } - -/* 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 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 */ -#define FP0_REGNUM 18 /* Floating point register 0 */ -#define FPC_REGNUM 26 /* 68881 control register */ - -#ifdef BSD43_ISI40D -#define BLOCKFUDGE 0x400000 -#else -#define BLOCKFUDGE 0 -#endif -#define REGISTER_U_ADDR(addr, blockend, regno) \ -{ blockend -= BLOCKFUDGE; \ - if (regno < 2) addr = blockend - 0x18 + regno * 4; \ - else if (regno < 8) addr = blockend - 0x54 + regno * 4; \ - else if (regno < 10) addr = blockend - 0x30 + regno * 4;\ - else if (regno < 15) addr = blockend - 0x5c + regno * 4;\ - else if (regno < 16) addr = blockend - 0x1c; \ - else if (regno < 18) addr = blockend - 0x44 + 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; \ -} - -/* Total amount of space needed to store our copies of the machine's - register state, the array `registers'. */ -#define REGISTER_BYTES (16*4+8*12+8+20) - -/* Index within `registers' of the first byte of the space for - register N. */ - -#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. */ - -#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) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_from_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) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_to_68881 ((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) - -/* 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)) - -/* 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 ISI, the frame's nominal address - is the address of a 4-byte word containing the calling frame's address. */ - -#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) - -#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. */ - -#define FRAME_SAVED_PC(frame) (read_memory_integer (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(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ - 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; } - -/* 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 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; \ -} - -/* Compensate for lack of `vprintf' function. */ -#define vprintf(format, ap) _doprnt (format, ap, stdout) - -/* 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 CORE_ADDR fp = read_register (FP_REGNUM); \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info fi; \ - char raw_buffer[12]; \ - fi = get_frame_info (fp); \ - 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); \ -} - -/* This sequence of words is the instructions - fmovem #,-(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, fun, nargs) \ -{ *(int *)((char *) dummyname + 20) = nargs * 4; \ - *(int *)((char *) dummyname + 14) = fun; } - -/* 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"); } diff --git a/gdb/m-merlin.h b/gdb/m-merlin.h index 3f30f50ad79..ec06135e823 100644 --- a/gdb/m-merlin.h +++ b/gdb/m-merlin.h @@ -254,13 +254,13 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4)) /* compute base of arguments */ #define FRAME_ARGS_ADDRESS(fi) ((fi).frame) @@ -276,7 +276,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! int addr_mode; \ int width; \ \ - pc = FRAME_SAVED_PC (fi.frame); \ + pc = FRAME_SAVED_PC (fi.frame,0); \ insn = read_memory_integer (pc,2); \ addr_mode = (insn >> 11) & 0x1f; \ insn = insn & 0x7ff; \ diff --git a/gdb/m-news.h b/gdb/m-news.h index 1ae6a173515..9a0f1148b10 100644 --- a/gdb/m-news.h +++ b/gdb/m-news.h @@ -265,13 +265,13 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4)) #define FRAME_ARGS_ADDRESS(fi) (fi.frame) @@ -281,7 +281,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) Can return -1, meaning no way to tell. */ #define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ +{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \ register int insn = 0177777 & read_memory_integer (pc, 2); \ val = 0; \ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ diff --git a/gdb/m-npl.h b/gdb/m-npl.h index 135e5bafe06..422b74aee85 100644 --- a/gdb/m-npl.h +++ b/gdb/m-npl.h @@ -341,7 +341,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! */ (chain) /* Define other aspects of the stack frame on NPL. */ -#define FRAME_SAVED_PC(frame) \ +#define FRAME_SAVED_PC(frame,ignore) \ (read_memory_integer (frame + 8, 4)) #define FRAME_ARGS_ADDRESS(fi) \ diff --git a/gdb/m-pn.h b/gdb/m-pn.h index 6e0bf76f06d..3cfdb03ffa1 100644 --- a/gdb/m-pn.h +++ b/gdb/m-pn.h @@ -325,7 +325,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! */ (chain) /* Define other aspects of the stack frame on NPL. */ -#define FRAME_SAVED_PC(frame) \ +#define FRAME_SAVED_PC(frame,ignore) \ (read_memory_integer (frame + 8, 4)) #define FRAME_ARGS_ADDRESS(fi) \ diff --git a/gdb/m-sun2.h b/gdb/m-sun2.h index 9babd6b649d..74181f8b1bd 100644 --- a/gdb/m-sun2.h +++ b/gdb/m-sun2.h @@ -208,13 +208,13 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4)) #define FRAME_ARGS_ADDRESS(fi) (fi.frame) @@ -229,7 +229,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) #if 0 #define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ +{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \ register int insn = 0177777 & read_memory_integer (pc, 2); \ val = 0; \ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ diff --git a/gdb/m-sun3.h b/gdb/m-sun3.h index 83ebf452d78..9c4095e8e4d 100644 --- a/gdb/m-sun3.h +++ b/gdb/m-sun3.h @@ -233,13 +233,13 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4)) #define FRAME_ARGS_ADDRESS(fi) (fi.frame) @@ -254,7 +254,7 @@ read_memory_integer (read_register (SP_REGNUM), 4) #if 0 #define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ +{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame,0); \ register int insn = 0177777 & read_memory_integer (pc, 2); \ val = 0; \ if (insn == 0047757 || insn == 0157374) /* lea W(sp),sp or addaw #W,sp */ \ diff --git a/gdb/m-sun4.h b/gdb/m-sun4.h new file mode 100644 index 00000000000..255cb56dc3c --- /dev/null +++ b/gdb/m-sun4.h @@ -0,0 +1,493 @@ +/* Parameters for execution on a Sun 4, for GDB, the GNU debugger. + Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@mcc.com) + +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! +*/ + +#ifndef sun4 +#define sun4 +#endif + +/* Get rid of any system-imposed stack limit if possible. */ + +#define SET_STACK_LIMIT_HUGE + +/* 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 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 end of stack space. */ + +#define STACK_END_ADDR 0xf000000 + +/* Stack grows downward. */ + +#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 FP_REGNUM 30 /* Contains address of executing stack frame */ +#define RP_REGNUM 15 /* Contains return address value, *before* \ + any windows get switched. */ +#define SP_REGNUM 14 /* Contains address of top of stack, \ + which is also the bottom of the frame. */ +#define Y_REGNUM 64 /* Temp register for multiplication, etc. */ +#define PS_REGNUM 65 /* Contains processor status */ +#define PC_REGNUM 68 /* Contains program counter */ +#define NPC_REGNUM 69 /* Contains next PC */ +#define FP0_REGNUM 32 /* Floating point register 0 */ +#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) + +/* 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) + +/* 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 ((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) \ + write_register_bytes (REGISTER_BYTE (8), 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)) + +/* Enable use of alternate code to read and write registers. */ + +#define NEW_SUN_PTRACE + +/* 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 + +/* It is safe to look for symsegs on a Sun, because Sun's ld + does not screw up with random garbage at end of file. */ + +#define READ_GDB_SYMSEGS + +/* The SPARC processor has register windows. */ + +#define HAVE_REGISTER_WINDOWS + +/* Describe the pointer in each stack frame to the previous stack frame + (its caller). */ +#include + +#define GET_RWINDOW_REG(FRAME, REG) \ + (read_memory_integer (&((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. */ + +#define FRAME_CHAIN(thisframe) \ + GET_RWINDOW_REG (thisframe, rw_in[6]) + +#define FRAME_CHAIN_VALID(chain, thisframe) \ + (chain != 0 && (FRAME_SAVED_PC (thisframe, 0) >= first_object_file_end)) + +#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) + +/* Define other aspects of the stack frame. */ + +#define FRAME_SAVED_PC(frame, next_frame) frame_saved_pc (frame, next_frame) + +/* 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. + 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 Sun 4, the only time all registers are saved is when + a dummy frame is involved. Otherwise, the only saved registers + are the LOCAL and IN registers which are saved as a result + of the "save/restore" opcodes. This condition is determined + by address rather than by value. */ + +#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs) \ +{ register int regnum; \ + register CORE_ADDR pc; \ + FRAME frame = (fi).frame; \ + FRAME next_frame = (fi).next_frame; \ + bzero (&frame_saved_regs, sizeof frame_saved_regs); \ + if ((fi).pc >= frame - CALL_DUMMY_LENGTH - 0x140 \ + && (fi).pc <= frame) \ + { \ + for (regnum = 0; regnum < 32; regnum++) \ + (frame_saved_regs).regs[regnum+FP0_REGNUM] = frame + regnum * 4 - 0x80;\ + for (regnum = 1; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum] = frame + regnum * 4 - 0xa0; \ + for (regnum = 0; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum+24] = frame + regnum * 4 - 0xc0; \ + for (regnum = 0; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum+64] = frame + regnum * 4 - 0xe0; \ + frame = (fi).next_frame ? \ + (fi).next_frame : read_register (SP_REGNUM); \ + } \ + else \ + { \ + for (regnum = 0; regnum < 16; regnum++) \ + (frame_saved_regs).regs[regnum+16] = frame + regnum * 4; \ + } \ + if (next_frame == 0) next_frame = read_register (SP_REGNUM); \ + for (regnum = 0; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum+8] = next_frame + regnum * 4; \ + (frame_saved_regs).regs[FP_REGNUM] = frame + 14*4; \ + (frame_saved_regs).regs[SP_REGNUM] = frame; \ + (frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \ +} + +/* Things needed for making the inferior call functions. */ + +/* Push an empty stack frame, to record the current PC, etc. */ + +/* NOTE: to be perfectly correct, we will probably have to restore the + IN registers (which were the OUT registers of the calling frame). */ + +#define PUSH_DUMMY_FRAME \ +{ extern char registers[]; \ + register int regnum; \ + CORE_ADDR fp = read_register (FP_REGNUM); \ + CORE_ADDR pc = read_register (PC_REGNUM); \ + void do_save_insn (); \ + supply_register (RP_REGNUM, &pc); \ + do_save_insn (0x140); \ + fp = read_register (FP_REGNUM); \ + write_memory (fp - 0x80, ®isters[REGISTER_BYTE (FP0_REGNUM)], 32 * 4); \ + write_memory (fp - 0xa0, ®isters[REGISTER_BYTE (0)], 8 * 4); \ + write_memory (fp - 0xc0, ®isters[REGISTER_BYTE (24)], 8 * 4); \ + write_memory (fp - 0xe0, ®isters[REGISTER_BYTE (64)], 8 * 4); \ +} + +/* Discard from the stack the innermost frame, + restoring all saved registers. */ + +#define POP_FRAME \ +{ register CORE_ADDR fp = read_register (FP_REGNUM); \ + register int regnum; \ + struct frame_saved_regs fsr; \ + struct frame_info fi; \ + char raw_buffer_fp[REGISTER_BYTES]; \ + char raw_buffer_globals[REGISTER_BYTES]; \ + char raw_buffer_outs[REGISTER_BYTES]; \ + char raw_buffer_xx[REGISTER_BYTES]; \ + void do_restore_insn (); \ + fi = get_frame_info (fp); \ + get_frame_saved_regs (&fi, &fsr); \ + if (fsr.regs[FP0_REGNUM]) \ + read_memory (fsr.regs[FP0_REGNUM], raw_buffer_fp, 32 * 4); \ + if (fsr.regs[1]) \ + read_memory (fsr.regs[1], raw_buffer_globals, 7 * 4); \ + if (fsr.regs[24]) \ + read_memory (fsr.regs[24], raw_buffer_outs, 8 * 4); \ + if (fsr.regs[64]) \ + read_memory (fsr.regs[64], raw_buffer_xx, 8 * 4); \ + do_restore_insn (fsr.regs); \ + if (fsr.regs[FP0_REGNUM]) \ + write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer_fp, 32 * 4); \ + if (fsr.regs[1]) \ + write_register_bytes (REGISTER_BYTE (1), raw_buffer_globals, 7 * 4);\ + if (fsr.regs[24]) \ + write_register_bytes (REGISTER_BYTE (8), raw_buffer_outs, 8 * 4); \ + if (fsr.regs[64]) \ + write_register_bytes (REGISTER_BYTE (64), raw_buffer_xx, 8 * 4); \ + set_current_frame (read_register (FP_REGNUM)); \ +} + +/* 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 call instruction. *../ + + ld [%sp+0x58],%o5 + ld [%sp+0x44],%o4 + ld [%sp+0x50],%o3 + ld [%sp+0x4c],%o2 + ld [%sp+0x48],%o1 + call 0x34343434 + 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, 0xd803a044, 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. */ + +#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \ +{ \ + *(int *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \ + if (TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_UNION) \ + *(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff); \ +} + +/* Sparc has no reliable single step ptrace call */ + +#define NO_SINGLE_STEP 1 + +/* KDB stuff flushed for now. */ diff --git a/gdb/m-sun4init.h b/gdb/m-sun4init.h new file mode 100644 index 00000000000..a1edc20e7ec --- /dev/null +++ b/gdb/m-sun4init.h @@ -0,0 +1,5 @@ + +/* This is how the size of an individual .o file's text segment + is rounded on a sun. */ + +#define FILEADDR_ROUND(addr) ((addr + 7) & -8) diff --git a/gdb/m-suninit.h b/gdb/m-suninit.h new file mode 100644 index 00000000000..5f71ea145b5 --- /dev/null +++ b/gdb/m-suninit.h @@ -0,0 +1,5 @@ + +/* This is how the size of an individual .o file's text segment + is rounded on a sun. */ + +#define FILEADDR_ROUND(addr) ((addr + 3) & -4) diff --git a/gdb/m-umax.h b/gdb/m-umax.h index f9187383468..1065728718c 100644 --- a/gdb/m-umax.h +++ b/gdb/m-umax.h @@ -266,13 +266,13 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame,ignore) (read_memory_integer (frame + 4, 4)) /* Compute base of arguments. */ @@ -311,7 +311,7 @@ extern CORE_ADDR ns32k_get_enter_addr (); { \ pc = (enter_addr == 1) ? \ SAVED_PC_AFTER_CALL () : \ - FRAME_SAVED_PC (fi.frame); \ + FRAME_SAVED_PC (fi.frame,0); \ insn = read_memory_integer (pc,2); \ addr_mode = (insn >> 11) & 0x1f; \ insn = insn & 0x7ff; \ diff --git a/gdb/m-vax.h b/gdb/m-vax.h index 5eb2a9f79d8..1d973bf194f 100644 --- a/gdb/m-vax.h +++ b/gdb/m-vax.h @@ -54,7 +54,7 @@ anyone else from sharing it farther. Help stamp out software hoarding! 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 SAVED_PC_AFTER_CALL(frame) FRAME_SAVED_PC(frame,0) /* This is the amount to subtract from u.u_ar0 to get the offset in the core file of the register values. */ @@ -212,13 +212,13 @@ anyone else from sharing it farther. Help stamp out software hoarding! #define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe + 12, 4)) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe,ignore) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 16, 4)) +#define FRAME_SAVED_PC(frame, ignore) (read_memory_integer (frame + 16, 4), 0) /* 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 diff --git a/gdb/main.c b/gdb/main.c index 352089736ec..13141554e9b 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -1153,7 +1153,7 @@ dump_me_command () static void initialize_main () { - prompt = savestring ("(gdb) ", 6); + prompt = savestring ("(gdb+) ", 7); /* Define the classes of commands. They will appear in the help list in the reverse of this order. */ diff --git a/gdb/opcode.h b/gdb/opcode.h index acb9df9fb8f..112214236f9 100644 --- a/gdb/opcode.h +++ b/gdb/opcode.h @@ -1,1272 +1 @@ -/* Opcode table for m68000/m68020 and m68881. */ - -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. - - 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 - - These specify various classes of addressing modes. - 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) -*/ - -/* 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) - -/* 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 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(0003000), one(0177700), "#b$b"}, /* addi written as add */ -{"addb", one(0050000), one(0170700), "Qd$b"}, /* addq written as add */ -{"addb", one(0150000), one(0170700), ";bDd"}, /* addb , Dd */ -{"addb", one(0150400), one(0170700), "Dd~b"}, /* addb Dd, */ - -{"addw", one(0003100), one(0177700), "#w$w"}, /* addi written as add */ -{"addw", one(0150300), one(0170700), "*wAd"}, /* adda written as add */ -{"addw", one(0050100), one(0170700), "Qd%w"}, /* addq written as add */ -{"addw", one(0150100), one(0170700), "*wDd"}, /* addw , Dd */ -{"addw", one(0150500), one(0170700), "Dd~w"}, /* addw Dd, */ - -{"addl", one(0003200), one(0177700), "#l$l"}, /* addi written as add */ -{"addl", one(0150700), one(0170700), "*lAd"}, /* adda written as add */ -{"addl", one(0050200), one(0170700), "Qd%l"}, /* addq written as add */ -{"addl", one(0150200), one(0170700), "*lDd"}, /* addl , Dd */ -{"addl", one(0150600), one(0170700), "Dd~l"}, /* addl Dd, */ - -{"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"}, -{"bsr", one(0060400), one(0177400), "Bg"}, -{"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 */ - -{"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"}, - -{"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 */ -{"movel", one(0070000), one(0170400), "MsDd"}, /* moveq written as move */ - -{"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. */ - -{"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(0002000), one(0177700), "#b$s"}, /* subi written as sub */ -{"subb", one(0050400), one(0170700), "Qd%s"}, /* subq 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(0002200), one(0177700), "#l$s"}, -{"subl", one(0050600), one(0170700), "Qd%s"}, -{"subl", one(0110200), one(0170700), "*lDd"}, -{"subl", one(0110600), one(0170700), "Dd~s"}, -{"subl", one(0110700), one(0170700), "*lAd"}, -{"subqb", one(0050400), one(0170700), "Qd%s"}, -{"subql", one(0050600), one(0170700), "Qd%s"}, -{"subqw", one(0050500), one(0170700), "Qd%s"}, -{"subw", one(0002100), one(0177700), "#w$s"}, -{"subw", one(0050500), one(0170700), "Qd%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"}, - -{"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(0xF1FF), "IdBc"}, -{"fbf", one(0xF080), one(0xF1FF), "IdBc"}, -{"fbge", one(0xF093), one(0xF1FF), "IdBc"}, -{"fbgl", one(0xF096), one(0xF1FF), "IdBc"}, -{"fbgle", one(0xF097), one(0xF1FF), "IdBc"}, -{"fbgt", one(0xF092), one(0xF1FF), "IdBc"}, -{"fble", one(0xF095), one(0xF1FF), "IdBc"}, -{"fblt", one(0xF094), one(0xF1FF), "IdBc"}, -{"fbne", one(0xF08E), one(0xF1FF), "IdBc"}, -{"fbnge", one(0xF09C), one(0xF1FF), "IdBc"}, -{"fbngl", one(0xF099), one(0xF1FF), "IdBc"}, -{"fbngle", one(0xF098), one(0xF1FF), "IdBc"}, -{"fbngt", one(0xF09D), one(0xF1FF), "IdBc"}, -{"fbnle", one(0xF09A), one(0xF1FF), "IdBc"}, -{"fbnlt", one(0xF09B), one(0xF1FF), "IdBc"}, -{"fboge", one(0xF083), one(0xF1FF), "IdBc"}, -{"fbogl", one(0xF086), one(0xF1FF), "IdBc"}, -{"fbogt", one(0xF082), one(0xF1FF), "IdBc"}, -{"fbole", one(0xF085), one(0xF1FF), "IdBc"}, -{"fbolt", one(0xF084), one(0xF1FF), "IdBc"}, -{"fbor", one(0xF087), one(0xF1FF), "IdBc"}, -{"fbseq", one(0xF091), one(0xF1FF), "IdBc"}, -{"fbsf", one(0xF090), one(0xF1FF), "IdBc"}, -{"fbsne", one(0xF09E), one(0xF1FF), "IdBc"}, -{"fbst", one(0xF09F), one(0xF1FF), "IdBc"}, -{"fbt", one(0xF08F), one(0xF1FF), "IdBc"}, -{"fbueq", one(0xF089), one(0xF1FF), "IdBc"}, -{"fbuge", one(0xF08B), one(0xF1FF), "IdBc"}, -{"fbugt", one(0xF08A), one(0xF1FF), "IdBc"}, -{"fbule", one(0xF08D), one(0xF1FF), "IdBc"}, -{"fbult", one(0xF08C), one(0xF1FF), "IdBc"}, -{"fbun", one(0xF088), one(0xF1FF), "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"}, - -{"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"}, - -{"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"}, - -{"fmoveb", two(0xF000, 0x5800), two(0xF1C0, 0xFC7F), "Ii;bF7"}, /* fmove from to fp */ -{"fmoveb", two(0xF000, 0x7800), two(0xF1C0, 0xFC7F), "IiF7@b"}, /* fmove from fp to */ -{"fmoved", two(0xF000, 0x5400), two(0xF1C0, 0xFC7F), "Ii;FF7"}, /* fmove from to fp */ -{"fmoved", two(0xF000, 0x7400), two(0xF1C0, 0xFC7F), "IiF7@F"}, /* fmove from fp to */ -{"fmovel", two(0xF000, 0x4000), two(0xF1C0, 0xFC7F), "Ii;lF7"}, /* fmove from to fp */ -{"fmovel", two(0xF000, 0x6000), two(0xF1C0, 0xFC7F), "IiF7@l"}, /* fmove from fp to */ - /* JF for the assembler */ -{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8%l"}, -{"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ls8"}, -/* JF {"fmovep", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7"}, /* fmove from to fp */ -{"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 to fp */ -{"fmoves", two(0xF000, 0x6400), two(0xF1C0, 0xFC7F), "IiF7@f"}, /* fmove from fp to */ -{"fmovew", two(0xF000, 0x5000), two(0xF1C0, 0xFC7F), "Ii;wF7"}, /* fmove from to fp */ -{"fmovew", two(0xF000, 0x7000), two(0xF1C0, 0xFC7F), "IiF7@w"}, /* fmove from fp to */ -{"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiF8F7"}, /* fmove from to fp */ -{"fmovex", two(0xF000, 0x4800), two(0xF1C0, 0xFC7F), "Ii;xF7"}, /* fmove from to fp */ -{"fmovex", two(0xF000, 0x6800), two(0xF1C0, 0xFC7F), "IiF7@x"}, /* fmove from fp to */ - - /* fmove.l from/to system control registers: */ - -/* fmove.l and fmovem.l are the same instruction. fmovem.l makes sense in - more cases, so I've dumped fmove.l pro tem, but this is the wrong - way to solve the problem in the long run. Hmmm. */ -/* {"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s"}, */ -/* {"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii@ss8"}, */ - -{"fmovecrx", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"}, /* fmovecr.x #ccc, FPn */ -{"fmovecr", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7"}, - -{"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(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id#3+s"}, /* fmovem.x from autoincrement, static and dynamic: */ -{"fmovemx", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "IiDk+s"}, /* fmovem.x from autoincrement, static and dynamic: */ - -{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id#3&s"}, /* fmovem.x from control, static and dynamic: */ -{"fmovemx", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "IiDk&s"}, /* fmovem.x from control, static and dynamic: */ - -/* fmoveml and fmovel are the same instruction. This may cause some - confusion in the assembler. */ - -{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Ii#8%s"}, /* fmovem.l to/from system control register(s): */ -{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii%s#8"}, /* fmovem.l to/from system control register(s): */ - -{"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"}, - -{"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"}, - -{"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"}, - -{"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"}, - -{"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"}, - -{"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"}, - -{"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"}, - -{"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"}, - -/* 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"}, - -{"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(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 */ -{"movl", one(0070000), one(0170400), "MsDd"}, /* movq written as mov */ -{"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. */ -{"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. */ -{"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 */ -/* movc not done*/ - -{"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"}, -}; - -int numopcodes=sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]); - -struct m68k_opcode *endop = m68k_opcodes+sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);; +/* This file is empty. */ diff --git a/gdb/param.h b/gdb/param.h index 83ebf452d78..255cb56dc3c 100644 --- a/gdb/param.h +++ b/gdb/param.h @@ -1,5 +1,6 @@ -/* Parameters for execution on a Sun, for GDB, the GNU debugger. +/* Parameters for execution on a Sun 4, for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@mcc.com) GDB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone @@ -18,8 +19,8 @@ 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! */ -#ifndef sun3 -#define sun3 +#ifndef sun4 +#define sun4 #endif /* Get rid of any system-imposed stack limit if possible. */ @@ -43,21 +44,21 @@ anyone else from sharing it farther. Help stamp out software hoarding! /* 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 */ \ -} +#define SKIP_PROLOGUE(pc) \ + { pc = skip_prologue (pc); } /* 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_memory_integer (read_register (SP_REGNUM), 4) +/* 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 end of stack space. */ @@ -67,19 +68,26 @@ read_memory_integer (read_register (SP_REGNUM), 4) #define INNER_THAN < +/* Stack has strict alignment. */ + +#define STACK_ALIGN(ADDR) (((ADDR)+7)&-8) + /* Sequence of bytes for breakpoint instruction. */ -#define BREAKPOINT {0x4e, 0x4f} +#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 2 +#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". -#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 2) == 0x4e75) + 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. */ @@ -91,17 +99,23 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Number of machine registers */ -#define NUM_REGS 31 +#define NUM_REGS 72 /* Initializer for an array of names of registers. There should be NUM_REGS strings in this initializer. */ #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" } +{ "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, @@ -110,40 +124,45 @@ read_memory_integer (read_register (SP_REGNUM), 4) 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 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 */ -#define FP0_REGNUM 18 /* Floating point register 0 */ -#define FPC_REGNUM 26 /* 68881 control register */ +#define FP_REGNUM 30 /* Contains address of executing stack frame */ +#define RP_REGNUM 15 /* Contains return address value, *before* \ + any windows get switched. */ +#define SP_REGNUM 14 /* Contains address of top of stack, \ + which is also the bottom of the frame. */ +#define Y_REGNUM 64 /* Temp register for multiplication, etc. */ +#define PS_REGNUM 65 /* Contains processor status */ +#define PC_REGNUM 68 /* Contains program counter */ +#define NPC_REGNUM 69 /* Contains next PC */ +#define FP0_REGNUM 32 /* Floating point register 0 */ +#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 (16*4+8*12+8+20) +#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) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 168 \ - : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 12) + 72 \ - : (N) * 4) +/* ?? */ +#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 - except the floating point regs which are 12 bytes. */ + for register N. */ + +/* On the SPARC, all regs are 4 bytes. */ -#define REGISTER_RAW_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 12 : 4) +#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 - except the floating point regs which are 8-byte doubles. */ + for register N. */ -#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)(N) - FP0_REGNUM) < 8 ? 8 : 4) +/* 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 12 +#define MAX_REGISTER_RAW_SIZE 8 /* Largest value REGISTER_VIRTUAL_SIZE can have. */ @@ -152,50 +171,44 @@ read_memory_integer (read_register (SP_REGNUM), 4) /* Nonzero if register N requires conversion from raw format to virtual format. */ -#define REGISTER_CONVERTIBLE(N) (((unsigned)(N) - FP0_REGNUM) < 8) +#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) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_from_68881 ((FROM), (TO)); \ - else \ - bcopy ((FROM), (TO), 4); } +#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) \ -{ if ((REGNUM) >= FP0_REGNUM && (REGNUM) < FPC_REGNUM) \ - convert_to_68881 ((FROM), (TO)); \ - else \ - bcopy ((FROM), (TO), 4); } +{ 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) + ((N) < 32 ? builtin_type_int : (N) < 64 ? builtin_type_float : builtin_type_int) /* 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)) + 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) \ - write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE)) + write_register_bytes (REGISTER_BYTE (8), 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)) +#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (read_memory_integer (((int *)(REGBUF))[SP_REGNUM]+(16*4), 4)) /* Enable use of alternate code to read and write registers. */ @@ -213,9 +226,17 @@ read_memory_integer (read_register (SP_REGNUM), 4) does not screw up with random garbage at end of file. */ #define READ_GDB_SYMSEGS + +/* The SPARC processor has register windows. */ + +#define HAVE_REGISTER_WINDOWS /* Describe the pointer in each stack frame to the previous stack frame (its caller). */ +#include + +#define GET_RWINDOW_REG(FRAME, REG) \ + (read_memory_integer (&((struct rwindow *)FRAME)->REG, 4)) /* FRAME_CHAIN takes a frame's nominal address and produces the frame's chain-pointer. @@ -227,22 +248,30 @@ read_memory_integer (read_register (SP_REGNUM), 4) 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, the frame's nominal address - is the address of a 4-byte word containing the calling frame's address. */ +/* 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. */ -#define FRAME_CHAIN(thisframe) (read_memory_integer (thisframe, 4)) +#define FRAME_CHAIN(thisframe) \ + GET_RWINDOW_REG (thisframe, rw_in[6]) #define FRAME_CHAIN_VALID(chain, thisframe) \ - (chain != 0 && (FRAME_SAVED_PC (thisframe) >= first_object_file_end)) + (chain != 0 && (FRAME_SAVED_PC (thisframe, 0) >= first_object_file_end)) #define FRAME_CHAIN_COMBINE(chain, thisframe) (chain) /* Define other aspects of the stack frame. */ -#define FRAME_SAVED_PC(frame) (read_memory_integer (frame + 4, 4)) +#define FRAME_SAVED_PC(frame, next_frame) frame_saved_pc (frame, next_frame) +/* 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. @@ -252,226 +281,213 @@ read_memory_integer (read_register (SP_REGNUM), 4) now that the C compiler delays popping them. */ #define FRAME_NUM_ARGS(val,fi) (val = -1) -#if 0 -#define FRAME_NUM_ARGS(val, fi) \ -{ register CORE_ADDR pc = FRAME_SAVED_PC (fi.frame); \ - 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; } -#endif - /* Return number of bytes at start of arglist that are not really args. */ -#define FRAME_ARGS_SKIP 8 +#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. 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. */ + the address we return for it IS the sp for the next frame. -#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \ + On the Sun 4, the only time all registers are saved is when + a dummy frame is involved. Otherwise, the only saved registers + are the LOCAL and IN registers which are saved as a result + of the "save/restore" opcodes. This condition is determined + by address rather than by value. */ + +#define FRAME_FIND_SAVED_REGS(fi, frame_saved_regs) \ { register int regnum; \ - register int regmask; \ - register CORE_ADDR next_addr; \ register CORE_ADDR pc; \ - int nextinsn; \ + FRAME frame = (fi).frame; \ + FRAME next_frame = (fi).next_frame; \ 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; \ + if ((fi).pc >= frame - CALL_DUMMY_LENGTH - 0x140 \ + && (fi).pc <= frame) \ + { \ + for (regnum = 0; regnum < 32; regnum++) \ + (frame_saved_regs).regs[regnum+FP0_REGNUM] = frame + regnum * 4 - 0x80;\ + for (regnum = 1; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum] = frame + regnum * 4 - 0xa0; \ + for (regnum = 0; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum+24] = frame + regnum * 4 - 0xc0; \ + for (regnum = 0; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum+64] = frame + regnum * 4 - 0xe0; \ + frame = (fi).next_frame ? \ + (fi).next_frame : read_register (SP_REGNUM); \ + } \ + else \ + { \ + for (regnum = 0; regnum < 16; regnum++) \ + (frame_saved_regs).regs[regnum+16] = frame + regnum * 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; \ + if (next_frame == 0) next_frame = read_register (SP_REGNUM); \ + for (regnum = 0; regnum < 8; regnum++) \ + (frame_saved_regs).regs[regnum+8] = next_frame + regnum * 4; \ + (frame_saved_regs).regs[FP_REGNUM] = frame + 14*4; \ + (frame_saved_regs).regs[SP_REGNUM] = frame; \ + (frame_saved_regs).regs[PC_REGNUM] = frame + 15*4; \ } /* Things needed for making the inferior call functions. */ /* Push an empty stack frame, to record the current PC, etc. */ +/* NOTE: to be perfectly correct, we will probably have to restore the + IN registers (which were the OUT registers of the calling frame). */ + #define PUSH_DUMMY_FRAME \ -{ register CORE_ADDR sp = read_register (SP_REGNUM); \ +{ extern char registers[]; \ 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); } + CORE_ADDR fp = read_register (FP_REGNUM); \ + CORE_ADDR pc = read_register (PC_REGNUM); \ + void do_save_insn (); \ + supply_register (RP_REGNUM, &pc); \ + do_save_insn (0x140); \ + fp = read_register (FP_REGNUM); \ + write_memory (fp - 0x80, ®isters[REGISTER_BYTE (FP0_REGNUM)], 32 * 4); \ + write_memory (fp - 0xa0, ®isters[REGISTER_BYTE (0)], 8 * 4); \ + write_memory (fp - 0xc0, ®isters[REGISTER_BYTE (24)], 8 * 4); \ + write_memory (fp - 0xe0, ®isters[REGISTER_BYTE (64)], 8 * 4); \ +} /* Discard from the stack the innermost frame, restoring all saved registers. */ #define POP_FRAME \ -{ register CORE_ADDR fp = read_register (FP_REGNUM); \ - register int regnum; \ - struct frame_saved_regs fsr; \ - struct frame_info fi; \ - char raw_buffer[12]; \ - fi = get_frame_info (fp); \ - 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); \ - set_current_frame (read_register (FP_REGNUM)); } +{ register CORE_ADDR fp = read_register (FP_REGNUM); \ + register int regnum; \ + struct frame_saved_regs fsr; \ + struct frame_info fi; \ + char raw_buffer_fp[REGISTER_BYTES]; \ + char raw_buffer_globals[REGISTER_BYTES]; \ + char raw_buffer_outs[REGISTER_BYTES]; \ + char raw_buffer_xx[REGISTER_BYTES]; \ + void do_restore_insn (); \ + fi = get_frame_info (fp); \ + get_frame_saved_regs (&fi, &fsr); \ + if (fsr.regs[FP0_REGNUM]) \ + read_memory (fsr.regs[FP0_REGNUM], raw_buffer_fp, 32 * 4); \ + if (fsr.regs[1]) \ + read_memory (fsr.regs[1], raw_buffer_globals, 7 * 4); \ + if (fsr.regs[24]) \ + read_memory (fsr.regs[24], raw_buffer_outs, 8 * 4); \ + if (fsr.regs[64]) \ + read_memory (fsr.regs[64], raw_buffer_xx, 8 * 4); \ + do_restore_insn (fsr.regs); \ + if (fsr.regs[FP0_REGNUM]) \ + write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer_fp, 32 * 4); \ + if (fsr.regs[1]) \ + write_register_bytes (REGISTER_BYTE (1), raw_buffer_globals, 7 * 4);\ + if (fsr.regs[24]) \ + write_register_bytes (REGISTER_BYTE (8), raw_buffer_outs, 8 * 4); \ + if (fsr.regs[64]) \ + write_register_bytes (REGISTER_BYTE (64), raw_buffer_xx, 8 * 4); \ + set_current_frame (read_register (FP_REGNUM)); \ +} /* This sequence of words is the instructions - fmovem 0xff,-(sp) - moveml 0xfffc,-(sp) - clrw -(sp) - movew ccr,-(sp) + + 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 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 + the following call instruction. *../ + + ld [%sp+0x58],%o5 + ld [%sp+0x44],%o4 + ld [%sp+0x50],%o3 + ld [%sp+0x4c],%o2 + ld [%sp+0x48],%o1 + call 0x34343434 + 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, 0xd803a044, 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. */ -#define FIX_CALL_DUMMY(dummyname, fun, nargs) \ -{ *(int *)((char *) dummyname + 20) = nargs * 4; \ - *(int *)((char *) dummyname + 14) = fun; } +#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, type) \ +{ \ + *(int *)((char *) dummyname+168) = (0x40000000|((fun-(pc+168))>>2)); \ + if (TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_UNION) \ + *(int *)((char *) dummyname+176) = (TYPE_LENGTH (type) & 0x1fff); \ +} -/* 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"); } +/* Sparc has no reliable single step ptrace call */ + +#define NO_SINGLE_STEP 1 + +/* KDB stuff flushed for now. */ diff --git a/gdb/pinsn.c b/gdb/pinsn.c index 94ac7f7c909..e7aba3213b5 100644 --- a/gdb/pinsn.c +++ b/gdb/pinsn.c @@ -1,5 +1,6 @@ -/* Print m68k instructions for GDB, the GNU debugger. +/* Print sparc instructions for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@mcc.com) GDB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone @@ -23,747 +24,788 @@ anyone else from sharing it farther. Help stamp out software hoarding! #include "defs.h" #include "param.h" #include "symtab.h" -#include "opcode.h" +#include "sparc-opcode.h" -/* 68k instructions are never longer than this many bytes. */ -#define MAXLEN 22 +/* sparc instructions are never longer than this many bytes. */ +#define MAXLEN 4 + +/* Print the sparc instruction at address MEMADDR in debugged memory, + on STREAM. Returns length of the instruction, in bytes, which + is always 4. */ + +struct op1_fmt +{ + unsigned op1 : 2; + unsigned dummy : 30; +}; + +struct op2_fmt +{ + unsigned dummy1 : 7; + unsigned op2 : 3; + unsigned dummy2 : 22; +}; + +struct op3_fmt +{ + unsigned dummy1 : 7; + unsigned op3 : 6; + unsigned dummy2 : 19; +}; + +struct call_fmt +{ + unsigned op : 2; + unsigned disp : 30; +}; + +struct sethi_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op2 : 3; + unsigned imm : 22; +}; + +struct branch_fmt +{ + unsigned op : 2; + unsigned a : 1; + unsigned cond : 4; + unsigned op2 : 3; + unsigned disp : 22; /* this should really be signed. */ +}; + +struct ldst_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op3 : 6; + unsigned rs1 : 5; + unsigned i : 1; + unsigned asi : 8; + unsigned rs2 : 5; +}; + +struct arith_imm_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op3 : 6; + unsigned rs1 : 5; + unsigned i : 1; + unsigned simm : 13; +}; + +struct arith_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op3 : 6; + unsigned rs1 : 5; + unsigned i : 1; + unsigned opf : 8; + unsigned rs2 : 5; +}; + +union insn_fmt +{ + struct op1_fmt op1; + struct op2_fmt op2; + struct op3_fmt op3; + struct call_fmt call; + struct sethi_fmt sethi; + struct branch_fmt branch; + struct ldst_fmt ldst; + struct arith_imm_fmt arith_imm; + struct arith_fmt arith; + int intval; + float floatval; /* ?? */ +}; + +typedef enum +{ + Error, not_branch, bicc, bicca, ba, baa, ticc, ta, +} branch_type; -/* Number of elements in the opcode table. */ -#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0]) +static char *icc_name[] = +{ "~", "eq", "le", "lt", "leu", "ltu", "neg", "vs", + "", "ne", "gt", "ge", "gtu", "geu", "pos", "vc"}; -extern char *reg_names[]; -char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr", - "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"}; +static char *fcc_name[] = +{ "~fb", "fbne", "fblg", "fbul", "fbl", "fbug", "fbg", "fbu", + "fb", "fbe", "fbue", "fbge", "fbuge", "fble", "fbule", "fbo"}; -static unsigned char *print_insn_arg (); -static unsigned char *print_indexed (); -static void print_base (); -static int fetch_arg (); +static char *ccc_name[] = +{ "~cb", "cb123", "cb12", "cb13", "cb1", "cb23", "cb2", "cb3", + "cb", "cb0", "cb03", "cb02", "cb023", "cb01", "cb013", "cb012"}; -#define NEXTBYTE(p) (p += 2, ((char *)p)[-1]) +static char *arith_name[] = +{ "add", "and", "or", "xor", "sub", "andn", "orn", "xnor", + "addx", 0, 0, 0, "subx", 0, 0, 0}; -#define NEXTWORD(p) \ - (p += 2, ((((char *)p)[-2]) << 8) + p[-1]) +static char *xarith_name[] = +{ "taddcc", "tsubcc", "taddcctv", "tsubcctv", "mulscc", "sll", "srl", "sra"}; -#define NEXTLONG(p) \ - (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]) +static char *state_reg_name[] = +{ "%y", "%psr", "%wim", "%tbr", 0, 0, 0, 0}; -#define NEXTSINGLE(p) \ - (p += 4, *((float *)(p - 4))) +static char *ldst_i_name[] = +{ "ld", "ldub", "lduh", "ldd", "st", "stb", "sth", "std", + 0, "ldsb", "ldsh", 0, 0, "ldstub", 0, "swap", + "lda", "lduba", "lduha", "ldda", "sta", "stba", "stha", "stda", + 0, "ldsba", "ldsha", 0, 0, "ldstuba", 0, "swapa"}; -#define NEXTDOUBLE(p) \ - (p += 8, *((double *)(p - 8))) +static char *ldst_f_name[] = +{ "ldf", "ldfsr", 0, "lddf", "stf", "stfsr", "stdfq", "stdf"}; -#define NEXTEXTEND(p) \ - (p += 12, 0.0) /* Need a function to convert from extended to double - precision... */ +static char *ldst_c_name[] = +{ "ldc", "ldcsr", 0, "lddc", "stc", "stcsr", "stdcq", "stdc"}; -#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... */ - -/* Print the m68k instruction at address MEMADDR in debugged memory, - on STREAM. Returns length of the instruction, in bytes. */ +static int this_sethi_target = -1; +static int last_sethi_target = -1; +static int sethi_value = 0; + +static void fprint_addr1 (); +static void fprint_ldst (); +static void fprint_f_ldst (); +static void fprint_c_ldst (); +static void fprint_fpop (); 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++) + union insn_fmt insn; + int disp22; + + read_memory (memaddr, &insn, MAXLEN); + + this_sethi_target = -1; + switch (insn.op1.op1) { - 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))) + case 1: + /* CALL format. */ + fprintf (stream, "call "); + print_address (memaddr + (insn.call.disp << 2), stream); + break; + case 0: + /* Bicc, FBfcc, CBccc, SETHI format. */ + switch (insn.op2.op2) { - /* 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') + case 0: + fprintf (stream, "unimp"); + break; + case 2: + /* Bicc. */ + fprintf (stream, "b%s", icc_name[insn.branch.cond]); + if (insn.branch.a) fprintf (stream, ",a "); + else fprintf (stream, " "); + disp22 = insn.branch.disp; + disp22 = ((disp22 << 10) >> 10); + print_address (memaddr + (disp22 << 2), stream); + break; + case 4: + /* SETHI. */ + fprintf (stream, "sethi %%hi(0x%x),%s", + insn.sethi.imm << 10, reg_names[insn.sethi.rd]); + this_sethi_target = insn.sethi.rd; + sethi_value = insn.sethi.imm << 12; + break; + case 6: + /* FBdfcc. */ + fprintf (stream, "fb%s", fcc_name[insn.branch.cond]); + if (insn.branch.a) fprintf (stream, ",a "); + else fprintf (stream, " "); + disp22 = insn.branch.disp; + disp22 = ((disp22 << 10) >> 10); + print_address (memaddr + (disp22 << 2), stream); + break; + case 7: + /* CBccc. */ + fprintf (stream, "cb%s", ccc_name[insn.branch.cond]); + if (insn.branch.a) fprintf (stream, ",a "); + else fprintf (stream, " "); + disp22 = insn.branch.disp; + disp22 = ((disp22 << 10) >> 10); + print_address (memaddr + (disp22 << 2), stream); + break; + default: + fprintf (stream, "0x%x (illegal op2 format)", insn.intval); + break; + } + break; + case 2: + { + /* vaguely arithmetic insns. */ + char *rd = reg_names[insn.arith.rd]; + char *rs1 = reg_names[insn.arith.rs1]; + + if (insn.op3.op3 <= 28) + { + /* Arithmetic insns, with a few unimplemented. */ + register int affect_cc = insn.op3.op3 & 16; + char *name = arith_name[insn.op3.op3 ^ affect_cc]; + char *tmp = affect_cc ? "cc" : ""; + + if (name == 0) + { + fprintf (stream, "0x%08x (unimplemented arithmetic insn)", + insn.intval); + } + else if (insn.arith.i) + { + fprintf (stream, "%s%s %s,0x%x,%s", + name, tmp, rs1, insn.arith_imm.simm, rd); + if (last_sethi_target == insn.arith.rd) + { + fprintf (stream, "\t! "); + print_address (sethi_value + insn.arith_imm.simm); + } + } + else + { + fprintf (stream, "%s%s %s,%s,%s", + name, tmp, rs1, reg_names[insn.arith.rs2], rd); + } + break; + } + if (insn.op3.op3 < 32) + { + fprintf (stream, "0x%08x (unimplemented arithmetic insn)", + insn.intval); + break; + } + else + { + int op = insn.op3.op3 ^ 32; + + if (op < 8) + { + char *name = xarith_name[op]; + /* tagged add/sub insns and shift insns. */ + if (insn.arith.i) + { + int i = insn.arith_imm.simm; + if (op > 4) + /* Its a shift insn. */ + i &= 31; + + fprintf (stream, "%s %s,0x%x,%s", + name, rs1, i, rd); + } + else + { + fprintf (stream, "%s %s,%s,%s", + name, rs1, reg_names[insn.arith.rs2], rd); + } break; + } + if (op < 20) + { + /* read/write state registers. */ + char *sr = state_reg_name[op & 7]; + if (sr == 0) + fprintf (stream, "0x%08x (unimplemented state register insn", + insn.intval); + else + fprintf (stream, "%s %s,%s", op & 16 ? "wr" : "rd", sr, rd); + break; + } + if (op < 22) + { + /* floating point insns. */ + int opcode = insn.arith.opf; - if (*d == 0 && match > bestmask) - { - best = i; - bestmask = match; - } - } - } + fprint_fpop (stream, insn, op & 3, opcode); + break; + } + if (op < 24) + { + /* coprocessor insns. */ + char *rs2 = reg_names[insn.arith.rs2]; + int opcode = insn.arith.opf; - /* Handle undefined instructions. */ - if (best < 0) - { - fprintf (stream, "0%o", (buffer[0] << 8) + buffer[1]); - return 2; - } + fprintf (stream, "cpop%d rs1=%s,rs2=%s,op=0x%x,rd=%s", + op & 1, rs1, rs2, opcode, rd); + break; + } - fprintf (stream, "%s", m68k_opcodes[best].name); + switch (op) + { + char *rndop_ptr; - /* 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; - } + case 24: + fprint_addr1 (stream, "jumpl", insn); + break; + case 25: + fprint_addr1 (stream, "rett", insn); + break; + case 26: + { + char rndop_buf[32]; + sprintf (rndop_buf, "t%s", icc_name[insn.branch.cond]); + fprint_addr1 (stream, rndop_buf, insn); + } + break; + case 27: + fprint_addr1 (stream, "iflush", insn); + break; - d = m68k_opcodes[best].args; + case 28: + rndop_ptr = "save"; + case 29: + if (op == 29) + rndop_ptr = "restore"; + + if (insn.arith.i) + { + fprintf (stream, "%s %s,0x%x,%s", + rndop_ptr, rs1, + ((insn.arith_imm.simm << 19) >> 19), rd); + } + else + { + fprintf (stream, "%s %s,%s,%s", + rndop_ptr, rs1, reg_names[insn.arith.rs2], rd); + } + break; + case 30: + case 31: + fprintf (stream, "0x%08x (unimplemented op3 insn)", + insn.intval); + break; + } + break; + } + } + case 3: + /* load and store insns. */ + { + char *rd = reg_names[insn.arith.rd]; + char *rs1 = reg_names[insn.arith.rs1]; + int op = insn.arith.op3; + + if ((op & 32) == 0) + { + /* Integer ops. */ + fprint_ldst (stream, insn, op); + break; + } + if ((op & 16) == 0) + { + /* Float ops. */ + op ^= 32; + if (op <= 7) + { + fprint_f_ldst (stream, insn, op); + } + else + fprintf (stream, "0x%08x (unimplemented float load/store insn)", + insn.intval); + } + else + { + /* Coprocessor ops. */ + op ^= (32+16); + if (op <= 7) + { + fprint_c_ldst (stream, insn, op); + } + else + fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)", + insn.intval); + } + break; + } + } + return 4; +} - if (*d) - fputc (' ', stream); +/* It would be nice if this routine could print out a symbolic address + when appropriate. */ +static void +fprint_addr1 (stream, name, insn) + FILE *stream; + char *name; + union insn_fmt insn; +{ + char *rs1 = reg_names[insn.arith.rs1]; + char *rd = reg_names[insn.arith.rd]; - while (*d) + if (insn.arith.i) + { + fprintf (stream, "%s %s,0x%x,%s", + name, rs1, insn.arith_imm.simm, rd); + } + else { - p = print_insn_arg (d, buffer, p, memaddr + p - buffer, stream); - d += 2; - if (*d && *(d - 2) != 'I' && *d != 'k') - fprintf (stream, ","); + fprintf (stream, "%s %s,%s,%s", + name, rs1, reg_names[insn.arith.rs2], rd); } - 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 */ +static void +fprint_mem (stream, insn) FILE *stream; + union insn_fmt insn; { - 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) + char *reg_name = reg_names[insn.arith.rs1]; + if (insn.arith.i) { - case 'C': - fprintf (stream, "ccr"); - break; - - case 'S': - fprintf (stream, "sr"); - break; - - case 'U': - fprintf (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 (stream, names[regno].name); - break; - } - if (regno < 0) - fprintf (stream, "%d", val); - } - break; - - case 'Q': - val = fetch_arg (buffer, place, 3); - if (val == 0) val = 8; - fprintf (stream, "#%d", val); - break; - - case 'M': - val = fetch_arg (buffer, place, 8); - if (val & 0x80) - val = val - 0x100; - fprintf (stream, "#%d", val); - break; - - case 'T': - val = fetch_arg (buffer, place, 4); - fprintf (stream, "#%d", val); - break; - - case 'D': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]); - break; - - case 'A': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 3) + 010]); - break; - - case 'R': - fprintf (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]); - break; + if (insn.arith_imm.simm == 0) + fprintf (stream, "[%s]", reg_name); + else if (insn.arith_imm.simm & 0x1000) + fprintf (stream, "[%s-0x%x]", reg_name, + - (insn.arith_imm.simm | 0xffffe000)); + else + fprintf (stream, "[%s+0x%x]", reg_name, insn.arith_imm.simm); + } + else + { + if (insn.arith.rs2 == 0) + fprintf (stream, "[%s]", reg_name); + else + fprintf (stream, "[%s,%s]", reg_names[insn.arith.rs2], reg_name); + } +} - case 'F': - fprintf (stream, "fp%d", fetch_arg (buffer, place, 3)); - break; +static void +fprint_ldst (stream, insn, op) + FILE *stream; + union insn_fmt insn; + int op; +{ + char *name = ldst_i_name[op]; + char *rd = reg_names[insn.arith.rd]; - case 'O': - val = fetch_arg (buffer, place, 6); - if (val & 0x20) - fprintf (stream, "%s", reg_names [val & 7]); + if (name) + { + if (name[0] == 's') + { + fprintf (stream, "%s %s,", name, rd); + fprint_mem (stream, insn); + } else - fprintf (stream, "%d", val); - break; - - case '+': - fprintf (stream, "(%s)+", reg_names[fetch_arg (buffer, place, 3) + 8]); - break; + { + fprintf (stream, "%s ", name); + fprint_mem (stream, insn); + fprintf (stream, ",%s", rd); + } + } + else + fprintf (stream, "0x%08x (unimplemented load/store insn)", insn.intval); +} - case '-': - fprintf (stream, "-(%s)", reg_names[fetch_arg (buffer, place, 3) + 8]); - break; +static void +fprint_f_ldst (stream, insn, op) + FILE *stream; + union insn_fmt insn; + int op; +{ + char *name = ldst_f_name[op]; + if (name) + { + char *rd = reg_names[insn.arith.rd + 32]; - case 'k': - if (place == 'k') - fprintf (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]); - else if (place == 'C') + if (name[0] == 's') { - val = fetch_arg (buffer, place, 7); - if ( val > 63 ) /* This is a signed constant. */ - val -= 128; - fprintf (stream, "{#%d}", val); + fprintf (stream, "%s %s,", name, rd); + fprint_mem (stream, insn); } else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - break; + { + fprintf (stream, "%s ", name); + fprint_mem (stream, insn); + fprintf (stream, ",%s", rd); + } + } + else + fprintf (stream, "0x%08x (unimplemented float load/store insn)", insn.intval); +} - case '#': - p1 = buffer + 2; - 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); +static void +fprint_c_ldst (stream, insn, op) + FILE *stream; + union insn_fmt insn; + int op; +{ + char *name = ldst_c_name[op]; + if (name) + { + if (name[0] == 's') + { + fprintf (stream, "%s %%cpreg(%d),", name, insn.arith.rs1); + fprint_mem (stream, insn); + } else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - fprintf (stream, "#%d", val); - break; + { + fprintf (stream, "%s "); + fprint_mem (stream, insn); + fprintf (stream, ",%%cpreg(%d)", insn.arith.rd); + } + } + else + fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)", + insn.intval); +} - case '^': - 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 == 'b') - val = NEXTBYTE (p); - else if (place == 'w') - val = NEXTWORD (p); - else if (place == 'l') - val = NEXTLONG (p); - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - fprintf (stream, "#%d", val); - break; +static void +fprint_fpop (stream, insn, op, opcode) + FILE *stream; + union insn_fmt insn; + int op, opcode; +{ + char *name; + char *rs1, *rs2, *rd; - 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') + switch (op) + { + case 0: + rs2 = reg_names[insn.arith.rs2 + 32]; + rd = reg_names[insn.arith.rd + 32]; + if ((opcode ^ 0x2f) <= 0x2f) { - val = ((char *)buffer)[1]; - if (val == 0) - val = NEXTWORD (p); - else if (val == -1) - val = NEXTLONG (p); + switch (opcode) + { + case 0x1: + name = "fmovs"; + break; + case 0x5: + name = "fnegs"; + break; + case 0x9: + name = "fabss"; + break; + case 0x29: + name = "fsqrts"; + break; + case 0x2a: + name = "fsqrtd"; + break; + case 0x2b: + name = "fsqrtx"; + break; + } + fprintf (stream, "%s %s,%s", name, rs2, rd); + return; } - else if (place == 'c') + if ((opcode ^ 0x5f) <= 0x5f) { - if (buffer[1] & 0x40) /* If bit six is one, long offset */ - val = NEXTLONG (p); + rs1 = reg_names[insn.arith.rs1 + 32]; + switch (opcode) + { + case 0x41: + name = "fadds"; + break; + case 0x42: + name = "faddd"; + break; + case 0x43: + name = "faddx"; + break; + case 0x45: + name = "fsubs"; + break; + case 0x46: + name = "fsubd"; + break; + case 0x47: + name = "fsubx"; + break; + case 0x49: + name = "fmuls"; + break; + case 0x4a: + name = "fmuld"; + break; + case 0x4b: + name = "fmulx"; + break; + case 0x4d: + name = "fdivs"; + break; + case 0x4e: + name = "fdivd"; + break; + case 0x4f: + name = "fdivx"; + break; + default: + goto unimplemented; + } + if ((opcode & 0x10) == 0) + fprintf (stream, "%s %s,%s,%s", name, rs1, rs2, rd); else - val = NEXTWORD (p); + fprintf (stream, "%s %s,%s", name, rs1, rs2); + return; } - else - error ("Invalid arg format in opcode table: \"%c%c\".", - *d, place); - - print_address (addr + val, stream); - break; - - case 'd': - val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, reg_names[fetch_arg (buffer, place, 3)]); - break; - - case 's': - fprintf (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 (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') + if ((opcode ^ 0xdf) <= 0xdf) { - val = fetch_arg (buffer, 'x', 6); - val = ((val & 7) << 3) + ((val >> 3) & 7); + switch (opcode) + { + case 0xc4: + name = "fitos"; + break; + case 0xc8: + name = "fitod"; + break; + case 0xcc: + name = "fitox"; + break; + case 0xd1: + name = "fstoi"; + break; + case 0xd2: + name = "fdtoi"; + break; + case 0xd3: + name = "fxtoi"; + break; + case 0xc9: + name = "fstod"; + break; + case 0xcd: + name = "fstox"; + break; + case 0xc6: + name = "fdtos"; + break; + case 0xce: + name = "fdtox"; + break; + case 0xc7: + name = "fxtos"; + break; + case 0xcb: + name = "fxtod"; + break; + default: + goto unimplemented; + } + fprintf (stream, "%s %s,%s", name, rs2, rd); + return; } - else - val = fetch_arg (buffer, 's', 6); + goto unimplemented; - /* Get register number assuming address register. */ - regno = (val & 7) + 8; - regname = reg_names[regno]; - switch (val >> 3) + case 1: + rs1 = reg_names[insn.arith.rs1 + 32]; + rs2 = reg_names[insn.arith.rs2 + 32]; + if ((opcode ^ 0x57) <= 0x57) { - case 0: - fprintf (stream, "%s", reg_names[val]); - break; - - case 1: - fprintf (stream, "%s", regname); - break; - - case 2: - fprintf (stream, "(%s)", regname); - break; - - case 3: - fprintf (stream, "(%s)+", regname); - break; - - case 4: - fprintf (stream, "-(%s)", regname); - break; - - case 5: - val = NEXTWORD (p); - fprintf (stream, "%d(%s)", val, regname); - break; - - case 6: - p = print_indexed (regno, p, addr, stream); - break; - - case 7: - switch (val & 7) + switch (opcode) { - case 0: - val = NEXTWORD (p); - fprintf (stream, "@#"); - print_address (val, stream); + case 0x51: + name = "fcmps"; break; - - case 1: - val = NEXTLONG (p); - fprintf (stream, "@#"); - print_address (val, stream); + case 0x52: + name = "fcmpd"; break; - - case 2: - val = NEXTWORD (p); - print_address (addr + val, stream); + case 0x53: + name = "fcmpx"; break; - - case 3: - p = print_indexed (-1, p, addr, stream); + case 0x55: + name = "fcmpes"; 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 (stream, "#%g", flval); - else - fprintf (stream, "#%d", val); + case 0x56: + name = "fcmped"; + break; + case 0x57: + name = "fcmpex"; break; - default: - fprintf (stream, "", val); + goto unimplemented; } + fprintf (stream, "%s %s,%s", name, rs1, rs2); + return; } - break; + else goto unimplemented; - default: - error ("Invalid arg format in opcode table: \"%c\".", *d); + case 2: + case 3: + goto unimplemented; } - - return (unsigned char *) p; + unimplemented: + fprintf (stream, "0x%08x (unimplemented fpop insn)", insn.intval); } -/* 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; +/* Set *target if we find a branch */ +branch_type +isabranch (addr, target) + CORE_ADDR addr, *target; { - register int val; - switch (code) + union insn_fmt instr; + branch_type val = not_branch; + long offset; /* Must be signed for sign-extend */ + + *target = 0; + instr.intval = read_memory_integer (addr, 4); + /* printf("intval = %x\n",instr.intval); */ + switch (instr.op1.op1) { - 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; + case 0: /* Format 2 */ + switch(instr.op2.op2) + { + case 2: case 6: /* BICC & FBCC */ + if (instr.branch.cond == 8) + val = instr.branch.a ? baa : ba; + else + val = instr.branch.a ? bicca : bicc; + /* 22 bits, sign extended */ + offset = ((instr.branch.disp << 10) >> 10); + *target = addr + offset; + break; + } 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 (); } + /*printf("isabranch ret: %d\n",val); */ + return val; } -/* 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; +CORE_ADDR skip_prologue (pc) + CORE_ADDR pc; { - 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) + union { - print_base (basereg, - ((word & 0x80) ? word | 0xff00 : word & 0xff) - + ((basereg == -1) ? addr : 0), - stream); - fprintf (stream, "%s", buf); - return p; - } - - /* Handle the generalized kind. */ - /* First, compute the displacement to add to the base register. */ + struct insn_fmt insn; + int i; + } x; + int dest = -1; - if (word & 0200) - basereg = -2; - if (word & 0100) - buf[0] = 0; - base_disp = 0; - switch ((word >> 4) & 3) + x.i = read_memory_integer (pc, 4); + if (x.insn.sethi.op == 0 && x.insn.sethi.op2 == 4) { - case 2: - base_disp = NEXTWORD (p); - break; - case 3: - base_disp = NEXTLONG (p); + dest = x.insn.sethi.rd; + pc += 4; + x.i = read_memory_integer (pc, 4); } - if (basereg == -1) - base_disp += addr; - - /* Handle single-level case (not indirect) */ - - if ((word & 7) == 0) + if (x.insn.arith_imm.op == 2 && x.insn.arith_imm.i == 1 + && (x.insn.arith_imm.rd == 1 || x.insn.arith_imm.rd == dest)) { - print_base (basereg, base_disp, stream); - fprintf (stream, "%s", buf); - return p; + pc += 4; + x.i = read_memory_integer (pc, 4); } - - /* Two level. Compute displacement to add after indirection. */ - - outer_disp = 0; - switch (word & 3) + if (x.insn.arith.op == 2 && (x.insn.arith.op3 ^ 32) == 28) { - case 2: - outer_disp = NEXTWORD (p); - break; - case 3: - outer_disp = NEXTLONG (p); + pc += 4; } - - fprintf (stream, "%d(", outer_disp); - print_base (basereg, base_disp, stream); - - /* If postindexed, print the closeparen before the index. */ - if (word & 4) - fprintf (stream, ")%s", buf); - /* If preindexed, print the closeparen after the index. */ - else - fprintf (stream, "%s)", buf); - - return p; + return pc; } -/* 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; +CORE_ADDR +frame_saved_pc (frame, next_frame) + CORE_ADDR frame; + CORE_ADDR next_frame; { - if (regno == -2) - fprintf (stream, "%d", disp); - else if (regno == -1) - fprintf (stream, "0x%x", disp); - else - fprintf (stream, "%d(%s)", disp, reg_names[regno]); -} - -/* This is not part of insn printing, but it is machine-specific, - so this is a convenient place to put it. + CORE_ADDR prev_pc; - Convert a 68881 extended float to a double. - FROM is the address of the extended float. - Store the double in *TO. */ - -convert_from_68881 (from, to) - char *from; - double *to; -{ -#ifdef HPUX_ASM - asm ("mov.l 8(%a6),%a0"); - asm ("mov.l 12(%a6),%a1"); - asm ("fmove.x (%a0),%fp0"); - asm ("fmove.d %fp0,(%a1)"); -#else /* not HPUX_ASM */ -#if 0 - asm ("movl a6@(8),a0"); - asm ("movl a6@(12),a1"); - asm ("fmovex a0@,fp0"); - asm ("fmoved fp0,a1@"); -#else - /* Hand-assemble those insns since some assemblers lose - and some have different syntax. */ - asm (".word 020156"); - asm (".word 8"); - asm (".word 021156"); - asm (".word 12"); - asm (".long 0xf2104800"); - asm (".long 0xf2117400"); -#endif -#endif /* not HPUX_ASM */ -} - -/* The converse: convert the double *FROM to an extended float - and store where TO points. */ + if (next_frame) + prev_pc = GET_RWINDOW_REG (next_frame, rw_in[7]); + else if (frame) + prev_pc = GET_RWINDOW_REG (read_register (SP_REGNUM), rw_in[7]); + else + error ("frame_saved_pc called without a frame"); -convert_to_68881 (from, to) - double *from; - char *to; -{ -#ifdef HPUX_ASM - asm ("mov.l 8(%a6),%a0"); - asm ("mov.l 12(%a6),%a1"); - asm ("fmove.d (%a0),%fp0"); - asm ("fmove.x %fp0,(%a1)"); -#else /* not HPUX_ASM */ -#if 0 - asm ("movl a6@(8),a0"); - asm ("movl a6@(12),a1"); - asm ("fmoved a0@,fp0"); - asm ("fmovex fp0,a1@"); -#else - /* Hand-assemble those insns since some assemblers lose. */ - asm (".word 020156"); - asm (".word 8"); - asm (".word 021156"); - asm (".word 12"); - asm (".long 0xf2105400"); - asm (".long 0xf2116800"); -#endif -#endif /* not HPUX_ASM */ + return PC_ADJUST (prev_pc); } diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 3fb12e46b2c..56278ee0601 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -499,6 +499,10 @@ address_info (exp) printf ("static at address 0x%x", val); break; + case LOC_REGPARM: + printf ("an argument in register %s", reg_names[val]); + break; + case LOC_ARG: printf ("an argument at offset %d", val); break; @@ -934,6 +938,7 @@ print_frame_args (func, addr, num, stream) int first = 1; register int i; register int last_offset = FRAME_ARGS_SKIP; + register int last_regparm = 0; register struct symbol *sym, *nextsym; register value val; @@ -951,31 +956,73 @@ print_frame_args (func, addr, num, stream) { QUIT; sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG - && SYMBOL_VALUE (sym) >= last_offset - && (nextsym == 0 - || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) - nextsym = sym; + if (SYMBOL_CLASS (sym) == LOC_ARG) + { + if (SYMBOL_VALUE (sym) >= last_offset + && (nextsym == 0 + || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) + nextsym = sym; + } + else if (SYMBOL_CLASS (sym) == LOC_REGPARM) + { + if (SYMBOL_VALUE (sym) >= last_regparm + && (nextsym == 0 + || SYMBOL_VALUE (sym) < SYMBOL_VALUE (nextsym))) + nextsym = sym; + } } if (nextsym == 0) break; sym = nextsym; /* Print any nameless args between the last arg printed and the next arg. */ - if (last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) + if (SYMBOL_CLASS (sym) == LOC_ARG + && last_offset != (SYMBOL_VALUE (sym) / sizeof (int)) * sizeof (int)) { print_frame_nameless_args (addr, last_offset, SYMBOL_VALUE (sym), stream); first = 0; } /* Print the next arg. */ - val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); + if (SYMBOL_CLASS (sym) == LOC_REGPARM) + { + unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE]; + unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; + + read_relative_register_raw_bytes (SYMBOL_VALUE (sym), raw_buffer); + if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT) + val = value_from_double (SYMBOL_TYPE (sym), *(double *)raw_buffer); + else if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT + || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM) + val = value_from_long (SYMBOL_TYPE (sym), *(int *)raw_buffer); + else if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR) + { + if (sizeof (char *) == sizeof (int)) + val = value_from_long (builtin_type_int, *(int *)raw_buffer); + else if (sizeof (char *) == sizeof (long)) + val = value_from_long (builtin_type_long, *(long *)raw_buffer); + else + error ("pointer size not sizeof (int) or sizeof (long)"); + VALUE_TYPE (val) = SYMBOL_TYPE (sym); + } + else + error ("can't extract non-scalar from register"); + } + else + val = value_at (SYMBOL_TYPE (sym), addr + SYMBOL_VALUE (sym)); + if (! first) fprintf (stream, ", "); fprintf (stream, "%s=", SYMBOL_NAME (sym)); value_print (val, stream, 0); first = 0; - last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); + if (SYMBOL_CLASS (sym) == LOC_ARG) + last_offset = SYMBOL_VALUE (sym) + TYPE_LENGTH (SYMBOL_TYPE (sym)); + else + { + last_regparm = SYMBOL_VALUE (sym) + 1; + last_offset += TYPE_LENGTH (SYMBOL_TYPE (sym)); + } /* Round up address of next arg to multiple of size of int. */ last_offset = ((last_offset + sizeof (int) - 1) / sizeof (int)) * sizeof (int); diff --git a/gdb/source.c b/gdb/source.c index bfce8f95e8a..6126d5b1b90 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -59,13 +59,16 @@ select_source_symtab (s) { if (s) { + struct symtabs_and_lines sals; struct symtab_and_line sal; /* Make the default place to list be the function `main' if one exists. */ if (lookup_symbol ("main", 0, VAR_NAMESPACE)) { - sal = decode_line_spec ("main", 1); + sals = decode_line_spec ("main", 1); + sal = sals.sals[0]; + free (sals.sals); current_source_symtab = sal.symtab; current_source_line = sal.line - 9; return; @@ -490,6 +493,7 @@ list_command (arg, from_tty) char *arg; int from_tty; { + struct symtabs_and_lines sals, sals_end; struct symtab_and_line sal, sal_end; struct symbol *sym; char *arg1; @@ -534,7 +538,18 @@ list_command (arg, from_tty) if (*arg1 == ',') dummy_beg = 1; else - sal = decode_line_1 (&arg1, 0, 0, 0); + { + sals = decode_line_1 (&arg1, 0, 0, 0); + + if (! sals.nelts) return; /* C++ */ + if (sals.nelts != 1) + { + error ("Unreasonable listing request"); + } + + sal = sals.sals[0]; + free (sals.sals); + } /* Record whether the BEG arg is all digits. */ @@ -551,10 +566,16 @@ list_command (arg, from_tty) arg1++; if (*arg1 == 0) dummy_end = 1; - else if (dummy_beg) - sal_end = decode_line_1 (&arg1, 0, 0, 0); else - sal_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line); + { + if (dummy_beg) + sals_end = decode_line_1 (&arg1, 0, 0, 0); + else + sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line); + if (! sals_end.nelts) return; /* C++ */ + sal_end = sals_end.sals[0]; + free (sals_end.sals); + } } if (*arg1) @@ -607,8 +628,7 @@ list_command (arg, from_tty) print_source_lines (sal.symtab, max (sal.line - 5, 1), sal.line + 5, 0); else print_source_lines (sal.symtab, sal.line, - dummy_end ? sal.line + 10 : sal_end.line + 1, - 0); + dummy_end ? sal.line + 10 : sal_end.line + 1, 0); } /* Print info on range of pc's in a specified line. */ @@ -618,6 +638,7 @@ line_info (arg, from_tty) char *arg; int from_tty; { + struct symtabs_and_lines sals; struct symtab_and_line sal; int start_pc, end_pc; @@ -628,8 +649,15 @@ line_info (arg, from_tty) } else { - sal = decode_line_spec (arg, 0); - + sals = decode_line_spec (arg); + + if (sals.nelts == 0) + return; /* C++ */ + if (sals.nelts != 1) + error ("unreasonable line info request"); + + sal = sals.sals[0]; + free (sals.sals); /* If this command is repeated with RET, turn it into the no-arg variant. */ diff --git a/gdb/sparc-opcode.h b/gdb/sparc-opcode.h new file mode 100644 index 00000000000..112214236f9 --- /dev/null +++ b/gdb/sparc-opcode.h @@ -0,0 +1 @@ +/* This file is empty. */ diff --git a/gdb/sparc-pinsn.c b/gdb/sparc-pinsn.c new file mode 100644 index 00000000000..e7aba3213b5 --- /dev/null +++ b/gdb/sparc-pinsn.c @@ -0,0 +1,811 @@ +/* Print sparc instructions for GDB, the GNU debugger. + Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Contributed by Michael Tiemann (tiemann@mcc.com) + +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 + +#include "defs.h" +#include "param.h" +#include "symtab.h" +#include "sparc-opcode.h" + +/* sparc instructions are never longer than this many bytes. */ +#define MAXLEN 4 + +/* Print the sparc instruction at address MEMADDR in debugged memory, + on STREAM. Returns length of the instruction, in bytes, which + is always 4. */ + +struct op1_fmt +{ + unsigned op1 : 2; + unsigned dummy : 30; +}; + +struct op2_fmt +{ + unsigned dummy1 : 7; + unsigned op2 : 3; + unsigned dummy2 : 22; +}; + +struct op3_fmt +{ + unsigned dummy1 : 7; + unsigned op3 : 6; + unsigned dummy2 : 19; +}; + +struct call_fmt +{ + unsigned op : 2; + unsigned disp : 30; +}; + +struct sethi_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op2 : 3; + unsigned imm : 22; +}; + +struct branch_fmt +{ + unsigned op : 2; + unsigned a : 1; + unsigned cond : 4; + unsigned op2 : 3; + unsigned disp : 22; /* this should really be signed. */ +}; + +struct ldst_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op3 : 6; + unsigned rs1 : 5; + unsigned i : 1; + unsigned asi : 8; + unsigned rs2 : 5; +}; + +struct arith_imm_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op3 : 6; + unsigned rs1 : 5; + unsigned i : 1; + unsigned simm : 13; +}; + +struct arith_fmt +{ + unsigned op : 2; + unsigned rd : 5; + unsigned op3 : 6; + unsigned rs1 : 5; + unsigned i : 1; + unsigned opf : 8; + unsigned rs2 : 5; +}; + +union insn_fmt +{ + struct op1_fmt op1; + struct op2_fmt op2; + struct op3_fmt op3; + struct call_fmt call; + struct sethi_fmt sethi; + struct branch_fmt branch; + struct ldst_fmt ldst; + struct arith_imm_fmt arith_imm; + struct arith_fmt arith; + int intval; + float floatval; /* ?? */ +}; + +typedef enum +{ + Error, not_branch, bicc, bicca, ba, baa, ticc, ta, +} branch_type; + +static char *icc_name[] = +{ "~", "eq", "le", "lt", "leu", "ltu", "neg", "vs", + "", "ne", "gt", "ge", "gtu", "geu", "pos", "vc"}; + +static char *fcc_name[] = +{ "~fb", "fbne", "fblg", "fbul", "fbl", "fbug", "fbg", "fbu", + "fb", "fbe", "fbue", "fbge", "fbuge", "fble", "fbule", "fbo"}; + +static char *ccc_name[] = +{ "~cb", "cb123", "cb12", "cb13", "cb1", "cb23", "cb2", "cb3", + "cb", "cb0", "cb03", "cb02", "cb023", "cb01", "cb013", "cb012"}; + +static char *arith_name[] = +{ "add", "and", "or", "xor", "sub", "andn", "orn", "xnor", + "addx", 0, 0, 0, "subx", 0, 0, 0}; + +static char *xarith_name[] = +{ "taddcc", "tsubcc", "taddcctv", "tsubcctv", "mulscc", "sll", "srl", "sra"}; + +static char *state_reg_name[] = +{ "%y", "%psr", "%wim", "%tbr", 0, 0, 0, 0}; + +static char *ldst_i_name[] = +{ "ld", "ldub", "lduh", "ldd", "st", "stb", "sth", "std", + 0, "ldsb", "ldsh", 0, 0, "ldstub", 0, "swap", + "lda", "lduba", "lduha", "ldda", "sta", "stba", "stha", "stda", + 0, "ldsba", "ldsha", 0, 0, "ldstuba", 0, "swapa"}; + +static char *ldst_f_name[] = +{ "ldf", "ldfsr", 0, "lddf", "stf", "stfsr", "stdfq", "stdf"}; + +static char *ldst_c_name[] = +{ "ldc", "ldcsr", 0, "lddc", "stc", "stcsr", "stdcq", "stdc"}; + +static int this_sethi_target = -1; +static int last_sethi_target = -1; +static int sethi_value = 0; + +static void fprint_addr1 (); +static void fprint_ldst (); +static void fprint_f_ldst (); +static void fprint_c_ldst (); +static void fprint_fpop (); + +int +print_insn (memaddr, stream) + CORE_ADDR memaddr; + FILE *stream; +{ + union insn_fmt insn; + int disp22; + + read_memory (memaddr, &insn, MAXLEN); + + this_sethi_target = -1; + switch (insn.op1.op1) + { + case 1: + /* CALL format. */ + fprintf (stream, "call "); + print_address (memaddr + (insn.call.disp << 2), stream); + break; + case 0: + /* Bicc, FBfcc, CBccc, SETHI format. */ + switch (insn.op2.op2) + { + case 0: + fprintf (stream, "unimp"); + break; + case 2: + /* Bicc. */ + fprintf (stream, "b%s", icc_name[insn.branch.cond]); + if (insn.branch.a) fprintf (stream, ",a "); + else fprintf (stream, " "); + disp22 = insn.branch.disp; + disp22 = ((disp22 << 10) >> 10); + print_address (memaddr + (disp22 << 2), stream); + break; + case 4: + /* SETHI. */ + fprintf (stream, "sethi %%hi(0x%x),%s", + insn.sethi.imm << 10, reg_names[insn.sethi.rd]); + this_sethi_target = insn.sethi.rd; + sethi_value = insn.sethi.imm << 12; + break; + case 6: + /* FBdfcc. */ + fprintf (stream, "fb%s", fcc_name[insn.branch.cond]); + if (insn.branch.a) fprintf (stream, ",a "); + else fprintf (stream, " "); + disp22 = insn.branch.disp; + disp22 = ((disp22 << 10) >> 10); + print_address (memaddr + (disp22 << 2), stream); + break; + case 7: + /* CBccc. */ + fprintf (stream, "cb%s", ccc_name[insn.branch.cond]); + if (insn.branch.a) fprintf (stream, ",a "); + else fprintf (stream, " "); + disp22 = insn.branch.disp; + disp22 = ((disp22 << 10) >> 10); + print_address (memaddr + (disp22 << 2), stream); + break; + default: + fprintf (stream, "0x%x (illegal op2 format)", insn.intval); + break; + } + break; + case 2: + { + /* vaguely arithmetic insns. */ + char *rd = reg_names[insn.arith.rd]; + char *rs1 = reg_names[insn.arith.rs1]; + + if (insn.op3.op3 <= 28) + { + /* Arithmetic insns, with a few unimplemented. */ + register int affect_cc = insn.op3.op3 & 16; + char *name = arith_name[insn.op3.op3 ^ affect_cc]; + char *tmp = affect_cc ? "cc" : ""; + + if (name == 0) + { + fprintf (stream, "0x%08x (unimplemented arithmetic insn)", + insn.intval); + } + else if (insn.arith.i) + { + fprintf (stream, "%s%s %s,0x%x,%s", + name, tmp, rs1, insn.arith_imm.simm, rd); + if (last_sethi_target == insn.arith.rd) + { + fprintf (stream, "\t! "); + print_address (sethi_value + insn.arith_imm.simm); + } + } + else + { + fprintf (stream, "%s%s %s,%s,%s", + name, tmp, rs1, reg_names[insn.arith.rs2], rd); + } + break; + } + if (insn.op3.op3 < 32) + { + fprintf (stream, "0x%08x (unimplemented arithmetic insn)", + insn.intval); + break; + } + else + { + int op = insn.op3.op3 ^ 32; + + if (op < 8) + { + char *name = xarith_name[op]; + /* tagged add/sub insns and shift insns. */ + if (insn.arith.i) + { + int i = insn.arith_imm.simm; + if (op > 4) + /* Its a shift insn. */ + i &= 31; + + fprintf (stream, "%s %s,0x%x,%s", + name, rs1, i, rd); + } + else + { + fprintf (stream, "%s %s,%s,%s", + name, rs1, reg_names[insn.arith.rs2], rd); + } + break; + } + if (op < 20) + { + /* read/write state registers. */ + char *sr = state_reg_name[op & 7]; + if (sr == 0) + fprintf (stream, "0x%08x (unimplemented state register insn", + insn.intval); + else + fprintf (stream, "%s %s,%s", op & 16 ? "wr" : "rd", sr, rd); + break; + } + if (op < 22) + { + /* floating point insns. */ + int opcode = insn.arith.opf; + + fprint_fpop (stream, insn, op & 3, opcode); + break; + } + if (op < 24) + { + /* coprocessor insns. */ + char *rs2 = reg_names[insn.arith.rs2]; + int opcode = insn.arith.opf; + + fprintf (stream, "cpop%d rs1=%s,rs2=%s,op=0x%x,rd=%s", + op & 1, rs1, rs2, opcode, rd); + break; + } + + switch (op) + { + char *rndop_ptr; + + case 24: + fprint_addr1 (stream, "jumpl", insn); + break; + case 25: + fprint_addr1 (stream, "rett", insn); + break; + case 26: + { + char rndop_buf[32]; + sprintf (rndop_buf, "t%s", icc_name[insn.branch.cond]); + fprint_addr1 (stream, rndop_buf, insn); + } + break; + case 27: + fprint_addr1 (stream, "iflush", insn); + break; + + case 28: + rndop_ptr = "save"; + case 29: + if (op == 29) + rndop_ptr = "restore"; + + if (insn.arith.i) + { + fprintf (stream, "%s %s,0x%x,%s", + rndop_ptr, rs1, + ((insn.arith_imm.simm << 19) >> 19), rd); + } + else + { + fprintf (stream, "%s %s,%s,%s", + rndop_ptr, rs1, reg_names[insn.arith.rs2], rd); + } + break; + case 30: + case 31: + fprintf (stream, "0x%08x (unimplemented op3 insn)", + insn.intval); + break; + } + break; + } + } + case 3: + /* load and store insns. */ + { + char *rd = reg_names[insn.arith.rd]; + char *rs1 = reg_names[insn.arith.rs1]; + int op = insn.arith.op3; + + if ((op & 32) == 0) + { + /* Integer ops. */ + fprint_ldst (stream, insn, op); + break; + } + if ((op & 16) == 0) + { + /* Float ops. */ + op ^= 32; + if (op <= 7) + { + fprint_f_ldst (stream, insn, op); + } + else + fprintf (stream, "0x%08x (unimplemented float load/store insn)", + insn.intval); + } + else + { + /* Coprocessor ops. */ + op ^= (32+16); + if (op <= 7) + { + fprint_c_ldst (stream, insn, op); + } + else + fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)", + insn.intval); + } + break; + } + } + return 4; +} + +/* It would be nice if this routine could print out a symbolic address + when appropriate. */ +static void +fprint_addr1 (stream, name, insn) + FILE *stream; + char *name; + union insn_fmt insn; +{ + char *rs1 = reg_names[insn.arith.rs1]; + char *rd = reg_names[insn.arith.rd]; + + if (insn.arith.i) + { + fprintf (stream, "%s %s,0x%x,%s", + name, rs1, insn.arith_imm.simm, rd); + } + else + { + fprintf (stream, "%s %s,%s,%s", + name, rs1, reg_names[insn.arith.rs2], rd); + } +} + +static void +fprint_mem (stream, insn) + FILE *stream; + union insn_fmt insn; +{ + char *reg_name = reg_names[insn.arith.rs1]; + if (insn.arith.i) + { + if (insn.arith_imm.simm == 0) + fprintf (stream, "[%s]", reg_name); + else if (insn.arith_imm.simm & 0x1000) + fprintf (stream, "[%s-0x%x]", reg_name, + - (insn.arith_imm.simm | 0xffffe000)); + else + fprintf (stream, "[%s+0x%x]", reg_name, insn.arith_imm.simm); + } + else + { + if (insn.arith.rs2 == 0) + fprintf (stream, "[%s]", reg_name); + else + fprintf (stream, "[%s,%s]", reg_names[insn.arith.rs2], reg_name); + } +} + +static void +fprint_ldst (stream, insn, op) + FILE *stream; + union insn_fmt insn; + int op; +{ + char *name = ldst_i_name[op]; + char *rd = reg_names[insn.arith.rd]; + + if (name) + { + if (name[0] == 's') + { + fprintf (stream, "%s %s,", name, rd); + fprint_mem (stream, insn); + } + else + { + fprintf (stream, "%s ", name); + fprint_mem (stream, insn); + fprintf (stream, ",%s", rd); + } + } + else + fprintf (stream, "0x%08x (unimplemented load/store insn)", insn.intval); +} + +static void +fprint_f_ldst (stream, insn, op) + FILE *stream; + union insn_fmt insn; + int op; +{ + char *name = ldst_f_name[op]; + if (name) + { + char *rd = reg_names[insn.arith.rd + 32]; + + if (name[0] == 's') + { + fprintf (stream, "%s %s,", name, rd); + fprint_mem (stream, insn); + } + else + { + fprintf (stream, "%s ", name); + fprint_mem (stream, insn); + fprintf (stream, ",%s", rd); + } + } + else + fprintf (stream, "0x%08x (unimplemented float load/store insn)", insn.intval); +} + +static void +fprint_c_ldst (stream, insn, op) + FILE *stream; + union insn_fmt insn; + int op; +{ + char *name = ldst_c_name[op]; + if (name) + { + if (name[0] == 's') + { + fprintf (stream, "%s %%cpreg(%d),", name, insn.arith.rs1); + fprint_mem (stream, insn); + } + else + { + fprintf (stream, "%s "); + fprint_mem (stream, insn); + fprintf (stream, ",%%cpreg(%d)", insn.arith.rd); + } + } + else + fprintf (stream, "0x%08x (unimplemented coprocessor load/store insn)", + insn.intval); +} + +static void +fprint_fpop (stream, insn, op, opcode) + FILE *stream; + union insn_fmt insn; + int op, opcode; +{ + char *name; + char *rs1, *rs2, *rd; + + switch (op) + { + case 0: + rs2 = reg_names[insn.arith.rs2 + 32]; + rd = reg_names[insn.arith.rd + 32]; + if ((opcode ^ 0x2f) <= 0x2f) + { + switch (opcode) + { + case 0x1: + name = "fmovs"; + break; + case 0x5: + name = "fnegs"; + break; + case 0x9: + name = "fabss"; + break; + case 0x29: + name = "fsqrts"; + break; + case 0x2a: + name = "fsqrtd"; + break; + case 0x2b: + name = "fsqrtx"; + break; + } + fprintf (stream, "%s %s,%s", name, rs2, rd); + return; + } + if ((opcode ^ 0x5f) <= 0x5f) + { + rs1 = reg_names[insn.arith.rs1 + 32]; + switch (opcode) + { + case 0x41: + name = "fadds"; + break; + case 0x42: + name = "faddd"; + break; + case 0x43: + name = "faddx"; + break; + case 0x45: + name = "fsubs"; + break; + case 0x46: + name = "fsubd"; + break; + case 0x47: + name = "fsubx"; + break; + case 0x49: + name = "fmuls"; + break; + case 0x4a: + name = "fmuld"; + break; + case 0x4b: + name = "fmulx"; + break; + case 0x4d: + name = "fdivs"; + break; + case 0x4e: + name = "fdivd"; + break; + case 0x4f: + name = "fdivx"; + break; + default: + goto unimplemented; + } + if ((opcode & 0x10) == 0) + fprintf (stream, "%s %s,%s,%s", name, rs1, rs2, rd); + else + fprintf (stream, "%s %s,%s", name, rs1, rs2); + return; + } + if ((opcode ^ 0xdf) <= 0xdf) + { + switch (opcode) + { + case 0xc4: + name = "fitos"; + break; + case 0xc8: + name = "fitod"; + break; + case 0xcc: + name = "fitox"; + break; + case 0xd1: + name = "fstoi"; + break; + case 0xd2: + name = "fdtoi"; + break; + case 0xd3: + name = "fxtoi"; + break; + case 0xc9: + name = "fstod"; + break; + case 0xcd: + name = "fstox"; + break; + case 0xc6: + name = "fdtos"; + break; + case 0xce: + name = "fdtox"; + break; + case 0xc7: + name = "fxtos"; + break; + case 0xcb: + name = "fxtod"; + break; + default: + goto unimplemented; + } + fprintf (stream, "%s %s,%s", name, rs2, rd); + return; + } + goto unimplemented; + + case 1: + rs1 = reg_names[insn.arith.rs1 + 32]; + rs2 = reg_names[insn.arith.rs2 + 32]; + if ((opcode ^ 0x57) <= 0x57) + { + switch (opcode) + { + case 0x51: + name = "fcmps"; + break; + case 0x52: + name = "fcmpd"; + break; + case 0x53: + name = "fcmpx"; + break; + case 0x55: + name = "fcmpes"; + break; + case 0x56: + name = "fcmped"; + break; + case 0x57: + name = "fcmpex"; + break; + default: + goto unimplemented; + } + fprintf (stream, "%s %s,%s", name, rs1, rs2); + return; + } + else goto unimplemented; + + case 2: + case 3: + goto unimplemented; + } + unimplemented: + fprintf (stream, "0x%08x (unimplemented fpop insn)", insn.intval); +} + +/* Set *target if we find a branch */ +branch_type +isabranch (addr, target) + CORE_ADDR addr, *target; +{ + union insn_fmt instr; + branch_type val = not_branch; + long offset; /* Must be signed for sign-extend */ + + *target = 0; + instr.intval = read_memory_integer (addr, 4); + /* printf("intval = %x\n",instr.intval); */ + switch (instr.op1.op1) + { + case 0: /* Format 2 */ + switch(instr.op2.op2) + { + case 2: case 6: /* BICC & FBCC */ + if (instr.branch.cond == 8) + val = instr.branch.a ? baa : ba; + else + val = instr.branch.a ? bicca : bicc; + /* 22 bits, sign extended */ + offset = ((instr.branch.disp << 10) >> 10); + *target = addr + offset; + break; + } + break; + } + /*printf("isabranch ret: %d\n",val); */ + return val; +} + +CORE_ADDR skip_prologue (pc) + CORE_ADDR pc; +{ + union + { + struct insn_fmt insn; + int i; + } x; + int dest = -1; + + x.i = read_memory_integer (pc, 4); + if (x.insn.sethi.op == 0 && x.insn.sethi.op2 == 4) + { + dest = x.insn.sethi.rd; + pc += 4; + x.i = read_memory_integer (pc, 4); + } + if (x.insn.arith_imm.op == 2 && x.insn.arith_imm.i == 1 + && (x.insn.arith_imm.rd == 1 || x.insn.arith_imm.rd == dest)) + { + pc += 4; + x.i = read_memory_integer (pc, 4); + } + if (x.insn.arith.op == 2 && (x.insn.arith.op3 ^ 32) == 28) + { + pc += 4; + } + return pc; +} + +CORE_ADDR +frame_saved_pc (frame, next_frame) + CORE_ADDR frame; + CORE_ADDR next_frame; +{ + CORE_ADDR prev_pc; + + if (next_frame) + prev_pc = GET_RWINDOW_REG (next_frame, rw_in[7]); + else if (frame) + prev_pc = GET_RWINDOW_REG (read_register (SP_REGNUM), rw_in[7]); + else + error ("frame_saved_pc called without a frame"); + + return PC_ADJUST (prev_pc); +} diff --git a/gdb/stack.c b/gdb/stack.c index 6c3443c33fe..439a7298b89 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -196,7 +196,7 @@ frame_info (addr_exp) printf (" in %s", funname); if (sal.symtab) printf (" (%s line %d)", sal.symtab->filename, sal.line); - printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame)); + printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame, fi.next_frame)); if (calling_frame) printf (" called by frame at 0x%x", calling_frame); if (fi.next_frame && calling_frame) @@ -347,7 +347,7 @@ print_frame_arg_vars (frame, stream) for (i = 0; i < nsyms; i++) { sym = BLOCK_SYM (b, i); - if (SYMBOL_CLASS (sym) == LOC_ARG) + if (SYMBOL_CLASS (sym) == LOC_ARG || SYMBOL_CLASS (sym) == LOC_REGPARM) { fprintf (stream, "%s = ", SYMBOL_NAME (sym)); print_variable_value (sym, frame, stream); @@ -433,7 +433,7 @@ find_relative_frame (frame, level_offset_ptr) /* Going down could be done by iterating get_frame_info to find the next frame, but that would be quadratic since get_frame_info must scan all the way from the current frame. - The following algotithm is linear. */ + The following algorithm is linear. */ if (*level_offset_ptr < 0) { /* First put frame1 at innermost frame diff --git a/gdb/symmisc.c b/gdb/symmisc.c index cb631cb7f3f..5d50b0fce08 100644 --- a/gdb/symmisc.c +++ b/gdb/symmisc.c @@ -521,6 +521,10 @@ print_symbol (symbol, depth, outfile) fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol)); break; + case LOC_REGPARM: + fprintf (outfile, "parmameter register %d,", SYMBOL_VALUE (symbol)); + break; + case LOC_LOCAL: fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol)); break; diff --git a/gdb/symseg.h b/gdb/symseg.h index e233f171add..a04727e827c 100644 --- a/gdb/symseg.h +++ b/gdb/symseg.h @@ -1,5 +1,6 @@ /* GDB symbol table format definitions. Copyright (C) 1986 Free Software Foundation, Inc. + Hacked by Michael Tiemann (tiemann@mcc.com) GDB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone @@ -117,6 +118,10 @@ enum type_code TYPE_CODE_SET, /* Pascal sets */ TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */ TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */ + + /* C++ */ + TYPE_CODE_MEMBER, /* Member type */ + TYPE_CODE_REF, /* C++ Reference types */ }; /* This appears in a type's flags word for an unsigned integer type. */ @@ -124,6 +129,11 @@ enum type_code /* Other flag bits are used with GDB. */ +#define TYPE_FLAG_HAS_CONSTRUCTOR 256 +#define TYPE_FLAG_HAS_DESTRUCTOR 512 +#define TYPE_FLAG_VIA_PUBLIC 1024 +#define TYPE_FLAG_VIA_VIRTUAL 2048 + struct type { /* Code for kind of type */ @@ -144,11 +154,23 @@ struct type The debugger may add the address of such a type if it has to construct one later. */ struct type *pointer_type; + /* C++: also need a reference type. */ + struct type *reference_type; /* Type that is a function returning this type. Zero if no such function type is known here. The debugger may add the address of such a type if it has to construct one later. */ struct type *function_type; + +/* Handling of pointers to members: + MAIN_VARIANT is used for pointer and pointer + to member types. Normally it the value of the address of its + containing type. However, for pointers to members, we must be + able to allocate pointer to member types and look them up + from some place of reference. + NEXT_VARIANT is the next element in the chain. */ + struct type *main_variant, *next_variant; + /* Flags about this type. */ short flags; /* Number of fields described for this type */ @@ -185,6 +207,67 @@ struct type Zero for range bounds and array domains. */ char *name; } *fields; + + /* C++ */ + int *private_field_bits; + int *protected_field_bits; + + /* Number of methods described for this type */ + short nfn_fields; + /* Number of base classes this type derives from. */ + short n_baseclasses; + + /* Number of methods described for this type plus all the + methods that it derives from. */ + int nfn_fields_total; + + /* For classes, structures, and unions, a description of each field, + which consists of an overloaded name, followed by the types of + arguments that the method expects, and then the name after it + has been renamed to make it distinct. */ + struct fn_fieldlist + { + /* The overloaded name. */ + char *name; + /* The number of methods with this name. */ + int length; + /* The list of methods. */ + struct fn_field + { +#if 0 + /* The overloaded name */ + char *name; +#endif + /* The type of the argument */ + struct type *type; + /* The argument list */ + struct type **args; + /* The name after it has been processed */ + char *physname; + /* If this is a virtual function, the offset into the vtbl-1, + else 0. */ + int voffset; + } *fn_fields; + + int *private_fn_field_bits; + int *protected_fn_field_bits; + + } *fn_fieldlists; + + /* For types with virtual functions, VPTR_BASETYPE is the base class which + defined the virtual function table pointer. VPTR_FIELDNO is + the field number of that pointer in the structure. + + For types that are pointer to member types, VPTR_BASETYPE + ifs the type that this pointer is a member of. + + Unused otherwise. */ + struct type *vptr_basetype; + + int vptr_fieldno; + + /* If this type has base classes, put them here. */ + struct type **baseclasses; }; /* All of the name-scope contours of the program @@ -287,6 +370,7 @@ enum address_class LOC_STATIC, /* Value is at fixed address */ LOC_REGISTER, /* Value is in register */ LOC_ARG, /* Value is at spec'd position in arglist */ + LOC_REGPARM, /* Value is at spec'd position in register window */ LOC_LOCAL, /* Value is at spec'd pos in stack frame */ LOC_TYPEDEF, /* Value not used; definition in SYMBOL_TYPE Symbols in the namespace STRUCT_NAMESPACE diff --git a/gdb/symtab.c b/gdb/symtab.c index 5c08d88572a..19fa4942e59 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -28,6 +28,9 @@ anyone else from sharing it farther. Help stamp out software hoarding! START_FILE +static int find_line_common(); +static int lookup_misc_func(); + /* Allocate an obstack to hold objects that should be freed when we load a new symbol table. This includes the symbols made by dbxread @@ -176,14 +179,17 @@ lookup_enum (name, block) } /* Given a type TYPE, return a type of pointers to that type. - May need to construct such a type if this is the first use. */ + May need to construct such a type if this is the first use. + + C++: use TYPE_MAIN_VARIANT and TYPE_CHAIN to keep pointer + to member types under control. */ struct type * lookup_pointer_type (type) struct type *type; { register struct type *ptype = TYPE_POINTER_TYPE (type); - if (ptype) return ptype; + if (ptype) return TYPE_MAIN_VARIANT (ptype); /* This is the first time anyone wanted a pointer to a TYPE. */ if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) @@ -193,6 +199,7 @@ lookup_pointer_type (type) sizeof (struct type)); bzero (ptype, sizeof (struct type)); + TYPE_MAIN_VARIANT (ptype) = ptype; TYPE_TARGET_TYPE (ptype) = type; TYPE_POINTER_TYPE (type) = ptype; /* New type is permanent if type pointed to is permanent. */ @@ -204,12 +211,150 @@ lookup_pointer_type (type) return ptype; } +struct type * +lookup_reference_type (type) + struct type *type; +{ + register struct type *rtype = TYPE_REFERENCE_TYPE (type); + if (rtype) return TYPE_MAIN_VARIANT (rtype); + + /* This is the first time anyone wanted a pointer to a TYPE. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + rtype = (struct type *) xmalloc (sizeof (struct type)); + else + rtype = (struct type *) obstack_alloc (symbol_obstack, + sizeof (struct type)); + + bzero (rtype, sizeof (struct type)); + TYPE_MAIN_VARIANT (rtype) = rtype; + TYPE_TARGET_TYPE (rtype) = type; + TYPE_REFERENCE_TYPE (type) = rtype; + /* New type is permanent if type pointed to is permanent. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + TYPE_FLAGS (rtype) |= TYPE_FLAG_PERM; + /* We assume the machine has only one representation for pointers! */ + TYPE_LENGTH (rtype) = sizeof (char *); + TYPE_CODE (rtype) = TYPE_CODE_REF; + return rtype; +} + +/* Implement direct support for MEMBER_TYPE in GNU C++. + May need to construct such a type if this is the first use. + The TYPE is the type of the member. The DOMAIN is the type + of the aggregate that the member belongs to. */ + +struct type * +lookup_member_type (domain, type) + struct type *domain, *type; +{ + register struct type *mtype = TYPE_MAIN_VARIANT (type); + struct type *main_type; + + main_type = mtype; + while (mtype) + { + if (TYPE_DOMAIN_TYPE (mtype) == domain) + return mtype; + mtype = TYPE_NEXT_VARIANT (mtype); + } + + /* This is the first time anyone wanted this member type. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + mtype = (struct type *) xmalloc (sizeof (struct type)); + else + mtype = (struct type *) obstack_alloc (symbol_obstack, + sizeof (struct type)); + + bzero (mtype, sizeof (struct type)); + if (main_type == 0) main_type = mtype; + else + { + TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type); + TYPE_NEXT_VARIANT (main_type) = mtype; + } + TYPE_MAIN_VARIANT (mtype) = main_type; + TYPE_TARGET_TYPE (mtype) = type; + TYPE_DOMAIN_TYPE (mtype) = domain; + /* New type is permanent if type pointed to is permanent. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM; + + /* In practice, this is never used. */ + TYPE_LENGTH (mtype) = 1; + TYPE_CODE (mtype) = TYPE_CODE_MEMBER; + + return mtype; +} + +/* Given a type TYPE, return a type which has offset OFFSET, + via_virtual VIA_VIRTUAL, and via_public VIA_PUBLIC. + May need to construct such a type if none exists. */ +struct type * +lookup_basetype_type (type, offset, via_virtual, via_public) + struct type *type; + int offset; + int via_virtual, via_public; +{ + register struct type *btype = TYPE_MAIN_VARIANT (type); + struct type *main_type; + + if (offset != 0) + { + printf ("type offset non-zero in lookup_basetype_type"); + offset = 0; + } + + main_type = btype; + while (btype) + { + if (/* TYPE_OFFSET (btype) == offset + && */ TYPE_VIA_PUBLIC (btype) == via_public + && TYPE_VIA_VIRTUAL (btype) == via_virtual) + return btype; + btype = TYPE_NEXT_VARIANT (btype); + } + + /* This is the first time anyone wanted this member type. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + btype = (struct type *) xmalloc (sizeof (struct type)); + else + btype = (struct type *) obstack_alloc (symbol_obstack, + sizeof (struct type)); + + if (main_type == 0) + { + main_type = btype; + bzero (btype, sizeof (struct type)); + TYPE_MAIN_VARIANT (btype) = main_type; + } + else + { + bcopy (main_type, btype, sizeof (struct type)); + TYPE_NEXT_VARIANT (main_type) = btype; + } +/* TYPE_OFFSET (btype) = offset; */ + if (via_public) + TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_PUBLIC; + if (via_virtual) + TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_VIRTUAL; + /* New type is permanent if type pointed to is permanent. */ + if (TYPE_FLAGS (type) & TYPE_FLAG_PERM) + TYPE_FLAGS (btype) |= TYPE_FLAG_PERM; + + /* In practice, this is never used. */ + TYPE_LENGTH (btype) = 1; + TYPE_CODE (btype) = TYPE_CODE_STRUCT; + + return btype; +} + /* Given a type TYPE, return a type of functions that return that type. May need to construct such a type if this is the first use. */ struct type * -lookup_function_type (type) +lookup_function_type (type, argtypes) struct type *type; + struct type **argtypes; { register struct type *ptype = TYPE_FUNCTION_TYPE (type); if (ptype) return ptype; @@ -247,6 +392,8 @@ smash_to_pointer_type (type, to_type) TYPE_LENGTH (type) = sizeof (char *); TYPE_CODE (type) = TYPE_CODE_PTR; + TYPE_MAIN_VARIANT (type) = type; + if (TYPE_POINTER_TYPE (to_type) == 0 && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM)) { @@ -254,6 +401,46 @@ smash_to_pointer_type (type, to_type) } } +/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. */ + +void +smash_to_member_type (type, domain, to_type) + struct type *type, *domain, *to_type; +{ + bzero (type, sizeof (struct type)); + TYPE_TARGET_TYPE (type) = to_type; + TYPE_DOMAIN_TYPE (type) = domain; + + /* In practice, this is never needed. */ + TYPE_LENGTH (type) = 1; + TYPE_CODE (type) = TYPE_CODE_MEMBER; + + TYPE_MAIN_VARIANT (type) = lookup_member_type (domain, to_type); +} + +/* Smash TYPE to be a type of reference to TO_TYPE. + If TO_TYPE is not permanent and has no pointer-type yet, + record TYPE as its pointer-type. */ + +void +smash_to_reference_type (type, to_type) + struct type *type, *to_type; +{ + bzero (type, sizeof (struct type)); + TYPE_TARGET_TYPE (type) = to_type; + /* We assume the machine has only one representation for pointers! */ + TYPE_LENGTH (type) = sizeof (char *); + TYPE_CODE (type) = TYPE_CODE_REF; + + TYPE_MAIN_VARIANT (type) = type; + + if (TYPE_REFERENCE_TYPE (to_type) == 0 + && !(TYPE_FLAGS (type) & TYPE_FLAG_PERM)) + { + TYPE_REFERENCE_TYPE (to_type) = type; + } +} + /* Smash TYPE to be a type of functions returning TO_TYPE. If TO_TYPE is not permanent and has no function-type yet, record TYPE as its function-type. */ @@ -281,6 +468,62 @@ static struct symbol *lookup_block_symbol (); in namespace NAMESPACE, visible from lexical block BLOCK. Returns the struct symbol pointer, or zero if no symbol is found. */ +struct symbol * +lookup_symbol_1 (name, block, namespace) + char *name; + register struct block *block; + enum namespace namespace; +{ + register int i, n; + register struct symbol *sym; + register struct symtab *s; + struct blockvector *bv; + + /* Search specified block and its superiors. */ + + while (block != 0) + { + sym = lookup_block_symbol (block, name, namespace); + if (sym) return sym; + block = BLOCK_SUPERBLOCK (block); + } + return 0; +} + +struct symbol * +lookup_symbol_2 (name, block, namespace) + char *name; + register struct block *block; /* ignored as parameter */ + enum namespace namespace; +{ + register int i, n; + register struct symbol *sym; + register struct symtab *s; + struct blockvector *bv; + + /* Now search all symtabs' global blocks. */ + + for (s = symtab_list; s; s = s->next) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, 0); + sym = lookup_block_symbol (block, name, namespace); + if (sym) return sym; + } + + /* Now search all symtabs' per-file blocks. + Not strictly correct, but more useful than an error. */ + + for (s = symtab_list; s; s = s->next) + { + bv = BLOCKVECTOR (s); + block = BLOCKVECTOR_BLOCK (bv, 1); + sym = lookup_block_symbol (block, name, namespace); + if (sym) return sym; + } + return 0; +} + struct symbol * lookup_symbol (name, block, namespace) char *name; @@ -742,13 +985,15 @@ find_pc_line_pc_range (pc, startptr, endptr) if no file is validly specified. Callers must check that. Also, the line number returned may be invalid. */ -struct symtab_and_line +struct symtabs_and_lines decode_line_1 (argptr, funfirstline, default_symtab, default_line) char **argptr; int funfirstline; struct symtab *default_symtab; int default_line; { + struct symtabs_and_lines decode_line_2 (); + struct symtabs_and_lines values; struct symtab_and_line value; register char *p, *p1; register struct symtab *s; @@ -756,6 +1001,13 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) register CORE_ADDR pc; register int i; char *copy; + struct symbol *sym_class; + char *class_name, *method_name, *phys_name; + int method_counter; + int i1; + struct symbol **sym_arr; + struct type *t, *field; + char **physnames; /* Defaults have defaults. */ @@ -771,9 +1023,11 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) { (*argptr)++; pc = parse_and_eval_address_1 (argptr); - value = find_pc_line (pc, 0); - value.pc = pc; - return value; + values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line)); + values.nelts = 1; + values.sals[0] = find_pc_line (pc, 0); + values.sals[0].pc = pc; + return values; } /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */ @@ -789,6 +1043,121 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) if (p[0] == ':') { + /* C++ */ + if (p[1] ==':') + { + /* Extract the class name. */ + p1 = p; + while (p != *argptr && p[-1] == ' ') --p; + copy = (char *) alloca (p - *argptr + 1); + bcopy (*argptr, copy, p - *argptr); + copy[p - *argptr] = 0; + + /* Discard the class name from the arg. */ + p = p1 + 2; + while (*p == ' ' || *p == '\t') p++; + *argptr = p; + + sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE); + + if (sym_class && + (TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_STRUCT + || TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION)) + { + /* Arg token is not digits => try it as a function name + Find the next token (everything up to end or next whitespace). */ + p = *argptr; + while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++; + copy = (char *) alloca (p - *argptr + 1); + bcopy (*argptr, copy, p - *argptr); + copy[p - *argptr] = '\0'; + + /* no line number may be specified */ + while (*p == ' ' || *p == '\t') p++; + *argptr = p; + + sym = 0; + i1 = 0; /* counter for the symbol array */ + t = SYMBOL_TYPE (sym_class); + sym_arr = (struct symbol **) alloca(TYPE_NFN_FIELDS_TOTAL (t) * sizeof(struct symbol*)); + physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*)); + + if (destructor_name_p (copy, t)) + { + /* destructors are a special case. */ + struct fn_field *f = TYPE_FN_FIELDLIST1 (t, 0); + int len = TYPE_FN_FIELDLIST_LENGTH (t, 0) - 1; + phys_name = TYPE_FN_FIELD_PHYSNAME (f, len); + physnames[i1] = (char *)alloca (strlen (phys_name) + 1); + strcpy (physnames[i1], phys_name); + sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE); + if (sym_arr[i1]) i1++; + } + else while (t) + { + class_name = TYPE_NAME (t); + while (*class_name++ != ' '); + + sym_class = lookup_symbol (class_name, 0, STRUCT_NAMESPACE); + for (method_counter = TYPE_NFN_FIELDS (SYMBOL_TYPE (sym_class)) - 1; + method_counter >= 0; + --method_counter) + { + int field_counter; + struct fn_field *f = + TYPE_FN_FIELDLIST1 (SYMBOL_TYPE (sym_class), method_counter); + + method_name = TYPE_FN_FIELDLIST_NAME (SYMBOL_TYPE (sym_class), method_counter); + if (!strcmp (copy, method_name)) + for (field_counter = TYPE_FN_FIELDLIST_LENGTH (SYMBOL_TYPE (sym_class), method_counter) - 1; + field_counter >= 0; + --field_counter) + { + phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter); + physnames[i1] = (char*) alloca (strlen (phys_name) + 1); + strcpy (physnames[i1], phys_name); + sym_arr[i1] = lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class), VAR_NAMESPACE); + if (sym_arr[i1]) i1++; + } + } + if (TYPE_N_BASECLASSES (t)) + t = TYPE_BASECLASS(t, 1); + else break; + } + + if (i1 == 1) + { + sym = sym_arr[0]; + + if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) + { + /* Arg is the name of a function */ + pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) + FUNCTION_START_OFFSET; + if (funfirstline) + SKIP_PROLOGUE (pc); + values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line)); + values.nelts = 1; + values.sals[0] = find_pc_line (pc, 0); + values.sals[0].pc = (values.sals[0].end && values.sals[0].pc != pc) ? values.sals[0].end : pc; + } + else + { + values.nelts = 0; + } + return values; + } + if (i1 > 0) + { + return decode_line_2 (argptr, sym_arr, physnames, i1, funfirstline); + } + else + error ("that class does not have any method named %s",copy); + } + else + error("no class, struct, or union named %s", copy ); + } + /* end of C++ */ + /* Extract the file name. */ p1 = p; while (p != *argptr && p[-1] == ' ') --p; @@ -855,7 +1224,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) s = default_symtab; value.symtab = s; value.pc = 0; - return value; + values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line)); + values.sals[0] = value; + values.nelts = 1; + return values; } /* Arg token is not digits => try it as a function name @@ -882,7 +1254,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) SKIP_PROLOGUE (pc); value = find_pc_line (pc, 0); value.pc = (value.end && value.pc != pc) ? value.end : pc; - return value; + values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line)); + values.sals[0] = value; + values.nelts = 1; + return values; } if (sym) @@ -897,7 +1272,10 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET; if (funfirstline) SKIP_PROLOGUE (value.pc); - return value; + values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line)); + values.sals[0] = value; + values.nelts = 1; + return values; } if (symtab_list == 0) @@ -905,19 +1283,114 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) error ("Function %s not defined.", copy); } -struct symtab_and_line +struct symtabs_and_lines decode_line_spec (string, funfirstline) char *string; int funfirstline; { - struct symtab_and_line sal; + struct symtabs_and_lines sals; if (string == 0) error ("Empty line specification."); - sal = decode_line_1 (&string, funfirstline, - current_source_symtab, current_source_line); + sals = decode_line_1 (&string, funfirstline, + current_source_symtab, current_source_line); if (*string) error ("Junk at end of line specification: %s", string); - return sal; + return sals; +} + +struct symtabs_and_lines +decode_line_2 (argptr, sym_arr, physnames, nelts, funfirstline) + char **argptr; + struct symbol *sym_arr[]; + char *physnames[]; + int nelts; + int funfirstline; +{ + char *getenv(); + struct symtabs_and_lines values, return_values; + register CORE_ADDR pc; + char *args, *arg1, *read_line (); + int i; + char *prompt; + + values.sals = (struct symtab_and_line *) alloca (nelts * sizeof(struct symtab_and_line)); + return_values.sals = (struct symtab_and_line *) malloc (nelts * sizeof(struct symtab_and_line)); + + i = 0; + printf("[0] cancel\n[1] all\n"); + while (i < nelts) + { + if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK) + { + /* Arg is the name of a function */ + pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym_arr[i])) + + FUNCTION_START_OFFSET; + if (funfirstline) + SKIP_PROLOGUE (pc); + values.sals[i] = find_pc_line (pc, 0); + printf("[%d] file:%s; line number:%d\n", + (i+2), values.sals[i].symtab->filename, values.sals[i].line); + } + else printf ("?HERE\n"); + i++; + } + + if ((prompt = getenv ("PS2")) == NULL) + { + prompt = ">"; + } + printf("%s ",prompt); + fflush(stdout); + + args = read_line (0); + + if (args == 0) + error_no_arg ("one or more choice numbers"); + + i = 0; + while (*args) + { + int num; + + arg1 = args; + while (*arg1 >= '0' && *arg1 <= '9') arg1++; + if (*arg1 && *arg1 != ' ' && *arg1 != '\t') + error ("Arguments must be choice numbers."); + + num = atoi (args); + + if (num == 0) + error ("cancelled"); + else if (num == 1) + { + bcopy (values.sals, return_values.sals, (nelts * sizeof(struct symtab_and_line))); + return_values.nelts = nelts; + return return_values; + } + + if (num > nelts + 2) + { + printf ("No choice number %d.\n", num); + } + else + { + num -= 2; + if (values.sals[num].pc) + { + return_values.sals[i++] = values.sals[num]; + values.sals[num].pc = 0; + } + else + { + printf ("duplicate request for %d ignored.\n", num); + } + } + + args = arg1; + while (*args == ' ' || *args == '\t') args++; + } + return_values.nelts = i; + return return_values; } /* Return the index of misc function named NAME. */ @@ -998,7 +1471,7 @@ list_symbols (regexp, class) char *val; int found_in_file; static char *classnames[] - = {"variable", "function", "type"}; + = {"variable", "function", "type", "method"}; int print_count = 0; if (regexp) @@ -1035,7 +1508,8 @@ list_symbols (regexp, class) && ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF && SYMBOL_CLASS (sym) != LOC_BLOCK) || (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK) - || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF))) + || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF) + || (class == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK))) { if (!found_in_file) { @@ -1050,17 +1524,30 @@ list_symbols (regexp, class) && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE) printf ("typedef "); - type_print (SYMBOL_TYPE (sym), - (SYMBOL_CLASS (sym) == LOC_TYPEDEF - ? "" : SYMBOL_NAME (sym)), - stdout, 0); + if (class < 3) + { + type_print (SYMBOL_TYPE (sym), + (SYMBOL_CLASS (sym) == LOC_TYPEDEF + ? "" : SYMBOL_NAME (sym)), + stdout, 0); + printf (";\n"); + } + else + { + char buf[1024]; +# if 0 + type_print_base (TYPE_FN_FIELD_TYPE(t, i), stdout, 0, 0); + type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), stdout, 0); + sprintf (buf, " %s::", TYPE_NAME (t)); + type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), buf, name, stdout); +# endif + } if (class == 2 && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE && (TYPE_NAME ((SYMBOL_TYPE (sym))) == 0 || 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (sym))), SYMBOL_NAME (sym)))) printf (" %s", SYMBOL_NAME (sym)); - printf (";\n"); } } } @@ -1088,6 +1575,13 @@ types_info (regexp) { list_symbols (regexp, 2); } + +static void +methods_info (regexp) + char *regexp; +{ + list_symbols (regexp, 3); +} /* Call sort_block_syms to sort alphabetically the symbols of one block. */ @@ -1124,6 +1618,7 @@ init_type (code, length, uns, name) type = (struct type *) xmalloc (sizeof (struct type)); bzero (type, sizeof *type); + TYPE_MAIN_VARIANT (type) = type; TYPE_CODE (type) = code; TYPE_LENGTH (type) = length; TYPE_FLAGS (type) = uns ? TYPE_FLAG_UNSIGNED : 0; @@ -1131,6 +1626,10 @@ init_type (code, length, uns, name) TYPE_NFIELDS (type) = 0; TYPE_NAME (type) = name; + /* C++ fancies. */ + TYPE_NFN_FIELDS (type) = 0; + TYPE_N_BASECLASSES (type) = 0; + TYPE_BASECLASSES (type) = 0; return type; } @@ -1143,6 +1642,11 @@ initialize () "All function names, or those matching REGEXP."); add_info ("types", types_info, "All types names, or those matching REGEXP."); + add_info ("methods", methods_info, + "All method names, or those matching REGEXP::REGEXP.\n\ +If the class qualifier is ommited, it is assumed to be the current scope.\n\ +If the first REGEXP is ommited, then all methods matching the second REGEXP\n\ +are listed."); add_info ("sources", sources_info, "Source files in the program."); diff --git a/gdb/symtab.h b/gdb/symtab.h index deab276a8f1..10c33925f5b 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -75,7 +75,7 @@ struct symtab free_linetable => free just the linetable. */ enum free_code {free_nothing, free_contents, free_linetable} free_code; - /* Pointer to one block storage to be freed, if nonzero. */ + /* Pointer to one block of storage to be freed, if nonzero. */ char *free_ptr; /* Total number of lines found in source file. */ int nlines; @@ -148,16 +148,36 @@ int current_source_line; These types are never freed. */ #define TYPE_FLAG_PERM 4 +/* Some macros for bitfields. */ +#define B_SET(a,x) (a[x>>5] |= (1 << (x&31))) +#define B_CLR(a,x) (a[x>>5] &= ~(1 << (x&31))) +#define B_TST(a,x) (a[x>>5] & (1 << (x&31))) + #define TYPE_NAME(thistype) (thistype)->name #define TYPE_TARGET_TYPE(thistype) (thistype)->target_type #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type +#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type #define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type +#define TYPE_MAIN_VARIANT(thistype) (thistype)->main_variant +#define TYPE_NEXT_VARIANT(thistype) (thistype)->next_variant #define TYPE_LENGTH(thistype) (thistype)->length #define TYPE_FLAGS(thistype) (thistype)->flags #define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED) #define TYPE_CODE(thistype) (thistype)->code #define TYPE_NFIELDS(thistype) (thistype)->nfields #define TYPE_FIELDS(thistype) (thistype)->fields +/* C++ */ +#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype +#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype +#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno +#define TYPE_FN_FIELDS(thistype) (thistype)->fn_fields +#define TYPE_NFN_FIELDS(thistype) (thistype)->nfn_fields +#define TYPE_NFN_FIELDS_TOTAL(thistype) (thistype)->nfn_fields_total +#define TYPE_BASECLASSES(thistype) (thistype)->baseclasses +#define TYPE_BASECLASS(thistype,index) (thistype)->baseclasses[index] +#define TYPE_N_BASECLASSES(thistype) (thistype)->n_baseclasses +#define TYPE_VIA_PUBLIC(thistype) ((thistype)->flags & TYPE_FLAG_VIA_PUBLIC) +#define TYPE_VIA_VIRTUAL(thistype) ((thistype)->flags & TYPE_FLAG_VIA_VIRTUAL) #define TYPE_FIELD(thistype, n) (thistype)->fields[n] #define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type @@ -166,11 +186,46 @@ int current_source_line; #define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos #define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize #define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize + +#define TYPE_FIELD_PRIVATE_BITS(thistype) (thistype)->private_field_bits +#define TYPE_FIELD_PROTECTED_BITS(thistype) (thistype)->protected_field_bits +#define SET_TYPE_FIELD_PRIVATE(thistype, n) B_SET ((thistype)->private_field_bits, (n)) +#define SET_TYPE_FIELD_PROTECTED(thistype, n) B_SET ((thistype)->protected_field_bits, (n)) +#define TYPE_FIELD_PRIVATE(thistype, n) B_TST((thistype)->private_field_bits, (n)) +#define TYPE_FIELD_PROTECTED(thistype, n) B_TST((thistype)->protected_field_bits, (n)) + +#define TYPE_HAS_DESTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_DESTRUCTOR) +#define TYPE_HAS_CONSTRUCTOR(thistype) ((thistype)->flags & TYPE_FLAG_HAS_CONSTRUCTOR) + +#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1) +#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize) + +#define TYPE_FN_FIELDLISTS(thistype) (thistype)->fn_fieldlists +#define TYPE_FN_FIELDLIST(thistype, n) (thistype)->fn_fieldlists[n] +#define TYPE_FN_FIELDLIST1(thistype, n) (thistype)->fn_fieldlists[n].fn_fields +#define TYPE_FN_FIELDLIST_NAME(thistype, n) (thistype)->fn_fieldlists[n].name +#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) (thistype)->fn_fieldlists[n].length + +#define TYPE_FN_FIELD(thistype) (thistype)[n] +#define TYPE_FN_FIELD_NAME(thistype, n) (thistype)[n].name +#define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type +#define TYPE_FN_FIELD_ARGS(thistype, n) (thistype)[n].args +#define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname +#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) (thistype)[n].voffset +#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1) + +#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits +#define TYPE_FN_PROTECTED_BITS(thistype) (thistype).protected_fn_field_bits +#define SET_TYPE_FN_PRIVATE(thistype, n) B_SET ((thistype).private_fn_field_bits, n) +#define SET_TYPE_FN_PROTECTED(thistype, n) B_SET ((thistype).protected_fn_field_bits, n) +#define TYPE_FN_PRIVATE(thistype, n) B_TST ((thistype).private_fn_field_bits, n) +#define TYPE_FN_PROTECTED(thistype, n) B_TST ((thistype).protected_fn_field_bits, n) /* Functions that work on the objects described above */ extern struct symtab *lookup_symtab (); extern struct symbol *lookup_symbol (); +extern struct symbol *lookup_symbol_1 (), *lookup_symbol_2 (); extern struct type *lookup_typename (); extern struct type *lookup_unsigned_typename (); extern struct type *lookup_struct (); @@ -178,10 +233,17 @@ extern struct type *lookup_union (); extern struct type *lookup_enum (); extern struct type *lookup_pointer_type (); extern struct type *lookup_function_type (); +extern struct type *lookup_basetype_type (); extern struct symbol *block_function (); extern struct symbol *find_pc_function (); extern int find_pc_misc_function (); +/* C++ stuff. */ +extern struct type *lookup_reference_type (); +extern struct type *lookup_member_type (); +extern struct type *lookup_class (); +/* end of C++ stuff. */ + extern struct type *builtin_type_void; extern struct type *builtin_type_char; extern struct type *builtin_type_short; @@ -202,6 +264,12 @@ struct symtab_and_line CORE_ADDR end; }; +struct symtabs_and_lines +{ + struct symtab_and_line *sals; + int nelts; +}; + /* Given a pc value, return line number it is in. Second arg nonzero means if pc is on the boundary use the previous statement's line number. */ @@ -211,5 +279,5 @@ struct symtab_and_line find_pc_line (); /* Given a string, return the line specified by it. For commands like "list" and "breakpoint". */ -struct symtab_and_line decode_line_spec (); -struct symtab_and_line decode_line_1 (); +struct symtabs_and_lines decode_line_spec (); +struct symtabs_and_lines decode_line_1 (); diff --git a/gdb/test.c b/gdb/test.c new file mode 100644 index 00000000000..ff92691d53e --- /dev/null +++ b/gdb/test.c @@ -0,0 +1,6 @@ +#include + +main () +{ + Rational r = Rational (PI); +} diff --git a/gdb/test4.c b/gdb/test4.c new file mode 100644 index 00000000000..e46553446c5 --- /dev/null +++ b/gdb/test4.c @@ -0,0 +1,40 @@ +main() +{ + int i,j,k; + + i = 100; + j = 101; + k = foo(0,1,2,3,4,5,6,7,8); +} + +int f3 (x) +{ + return x; +} + +int f2 (x) +{ + return f3 (x+1); +} + +int f1 (x) +{ + return f2 (x+1); +} + +foo(a,b,c,d,e,f,g,h,i) + int a,b,c,d,e,f,g,h,i; +{ + int r; + r = a + b + c + d + e + f + g + h + i; + if (f1 (11)) + return r; + else + return 0; +} + +bar(ind) + int ind; +{ + printf("this is a test\n"); +} diff --git a/gdb/teststruct.c b/gdb/teststruct.c new file mode 100644 index 00000000000..75f16422f0a --- /dev/null +++ b/gdb/teststruct.c @@ -0,0 +1,111 @@ +struct small +{ + int i; +}; + +struct med +{ + struct small s1, s2; +}; + +struct large +{ + struct med m1, m2; +}; + +struct xlarge +{ + struct large l1, l2; +}; + +struct small ret_small (); +struct med ret_med (); +struct large ret_large (); +struct xlarge ret_xlarge (); + +void print_small (); +void print_med (); +void print_large (); +void print_xlarge (); + +main () +{ + struct small s; + struct med m; + struct large l; + struct xlarge x; + + s = ret_small (1); + m = ret_med (s,s); + l = ret_large (m, m); + x = ret_xlarge (l, l); + + print_small (s); + print_med (m); + print_large (l); + print_xlarge (x); +} + +struct small ret_small (i) + int i; +{ + struct small s; + s.i = i; + return s; +} + +struct med ret_med (s1, s2) + struct small s1, s2; +{ + struct med m; + m.s1 = s1; + m.s2 = s2; + return m; +} + +struct large ret_large (m1, m2) + struct med m1, m2; +{ + struct large l; + l.m1 = m1; + l.m2 = m2; + return l; +} + +struct xlarge ret_xlarge (l1, l2) + struct large l1, l2; +{ + struct xlarge x; + x.l1 = l1; + x.l2 = l2; + return x; +} + +void print_small (s) + struct small s; +{ + printf ("small: s.i = %d\n", s.i); +} + +void print_med (m) + struct med m; +{ + printf ("med: m.s1.i = %d; m.s2.i = %d\n", m.s1.i, m.s2.i); +} + +void print_large (l) + struct large l; +{ + printf ("large: l.m1.s1.i = %d; l.m1.s2.i = %d; l.m2.s1.i = %d; l.m2.s2.i = %d\n", + l.m1.s1.i, l.m1.s2.i, l.m2.s1.i, l.m2.s2.i); +} + +void print_xlarge (x) + struct xlarge x; +{ + printf ("xlarge: x.l1: "); + print_large (x.l1); + printf ("xlarge: x.l2: "); + print_large (x.l2); +} + diff --git a/gdb/valarith.c b/gdb/valarith.c index 03bc1e1e923..adf0044cc03 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -27,6 +27,8 @@ anyone else from sharing it farther. Help stamp out software hoarding! START_FILE +value value_x_binop (); + value value_add (arg1, arg2) value arg1, arg2; @@ -107,7 +109,172 @@ value_subscript (array, idx) { return value_ind (value_add (array, idx)); } + +/* Check to see if either argument is a structure. This is called so + we know whether to go ahead with the normal binop or look for a + user defined function instead. + For now, we do not overload the `=' operator. */ + +int +binop_user_defined_p (op, arg1, arg2) + enum exp_opcode op; + value arg1, arg2; +{ + if (op == BINOP_ASSIGN) + return 0; + return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT + || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_STRUCT + || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF + && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT) + || (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_REF + && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_STRUCT)); +} + +/* Check to see if argument is a structure. This is called so + we know whether to go ahead with the normal unop or look for a + user defined function instead. + + For now, we do not overload the `&' operator. */ + +int unop_user_defined_p (op, arg1) + enum exp_opcode op; + value arg1; +{ + if (op == UNOP_ADDR) + return 0; + return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT + || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF + && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT)); +} + +/* We know either arg1 or arg2 is a structure, so try to find the right + user defined function. Create an argument vector that calls + arg1.operator @ (arg1,arg2) and return that value (where '@' is any + binary operator which is legal for GNU C++). */ + +value +value_x_binop (arg1, arg2, op, otherop) + value arg1, arg2; + int op, otherop; +{ + value * argvec; + char *ptr; + char tstr[13]; + + COERCE_ENUM (arg1); + COERCE_ENUM (arg2); + + /* now we know that what we have to do is construct our + arg vector and find the right function to call it with. */ + + if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) + error ("friend functions not implemented yet"); + + argvec = (value *) alloca (sizeof (value) * 4); + argvec[1] = value_addr (arg1); + argvec[2] = arg2; + argvec[3] = 0; + + /* make the right function name up */ + strcpy(tstr, "operator __"); + ptr = tstr+9; + switch (op) + { + case BINOP_ADD: strcpy(ptr,"+"); break; + case BINOP_SUB: strcpy(ptr,"-"); break; + case BINOP_MUL: strcpy(ptr,"*"); break; + case BINOP_DIV: strcpy(ptr,"/"); break; + case BINOP_REM: strcpy(ptr,"%"); break; + case BINOP_LSH: strcpy(ptr,"<<"); break; + case BINOP_RSH: strcpy(ptr,">>"); break; + case BINOP_LOGAND: strcpy(ptr,"&"); break; + case BINOP_LOGIOR: strcpy(ptr,"|"); break; + case BINOP_LOGXOR: strcpy(ptr,"^"); break; + case BINOP_AND: strcpy(ptr,"&&"); break; + case BINOP_OR: strcpy(ptr,"||"); break; + case BINOP_MIN: strcpy(ptr,"?"); break; + case BINOP_ASSIGN: strcpy(ptr,"="); break; + case BINOP_ASSIGN_MODIFY: + switch (otherop) + { + case BINOP_ADD: strcpy(ptr,"+="); break; + case BINOP_SUB: strcpy(ptr,"-="); break; + case BINOP_MUL: strcpy(ptr,"*="); break; + case BINOP_DIV: strcpy(ptr,"/="); break; + case BINOP_REM: strcpy(ptr,"%="); break; + case BINOP_LOGAND: strcpy(ptr,"&="); break; + case BINOP_LOGIOR: strcpy(ptr,"|="); break; + case BINOP_LOGXOR: strcpy(ptr,"^="); break; + default: + error ("Invalid binary operation specified."); + } + break; + case BINOP_SUBSCRIPT: strcpy(ptr,"[]"); break; + case BINOP_EQUAL: strcpy(ptr,"=="); break; + case BINOP_NOTEQUAL: strcpy(ptr,"!="); break; + case BINOP_LESS: strcpy(ptr,"<"); break; + case BINOP_GTR: strcpy(ptr,">"); break; + case BINOP_GEQ: strcpy(ptr,">="); break; + case BINOP_LEQ: strcpy(ptr,"<="); break; + default: + error ("Invalid binary operation specified."); + } + argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure"); + if (argvec[0]) + return call_function (argvec[0], 2, argvec + 1); + else error ("member function %s not found", tstr); +} + +/* We know that arg1 is a structure, so try to find a unary user + defined operator that matches the operator in question. + Create an argument vector that calls arg1.operator @ (arg1) + and return that value (where '@' is (almost) any unary operator which + is legal for GNU C++). */ + +value +value_x_unop (arg1, op) + value arg1; + int op; +{ + value * argvec; + char *ptr; + char tstr[13]; + + COERCE_ENUM (arg1); + + /* now we know that what we have to do is construct our + arg vector and find the right function to call it with. */ + + if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) + error ("friend functions not implemented yet"); + + argvec = (value *) alloca (sizeof (value) * 3); + argvec[1] = value_addr (arg1); + argvec[2] = 0; + + /* make the right function name up */ + strcpy(tstr,"operator __"); + ptr = tstr+9; + switch (op) + { + case UNOP_PREINCREMENT: strcpy(ptr,"++"); break; + case UNOP_PREDECREMENT: strcpy(ptr,"++"); break; + case UNOP_POSTINCREMENT: strcpy(ptr,"++"); break; + case UNOP_POSTDECREMENT: strcpy(ptr,"++"); break; + case UNOP_ZEROP: strcpy(ptr,"!"); break; + case UNOP_LOGNOT: strcpy(ptr,"~"); break; + case UNOP_NEG: strcpy(ptr,"-"); break; + default: + error ("Invalid binary operation specified."); + } + argvec[0] = value_struct_elt (arg1, argvec+1, tstr, "structure"); + if (argvec[0]) + return call_function (argvec[0], 1, argvec + 1); + else error ("member function %s not found", tstr); +} + /* Perform a binary operation on two integers or two floats. Does not support addition and subtraction on pointers; use value_add or value_sub if you want to handle those possibilities. */ @@ -219,6 +386,14 @@ value_binop (arg1, arg2, op) v = v1 || v2; break; + case BINOP_MIN: + v = v1 < v2 ? v1 : v2; + break; + + case BINOP_MAX: + v = v1 > v2 ? v1 : v2; + break; + default: error ("Invalid binary operation on numbers."); } diff --git a/gdb/valops.c b/gdb/valops.c index 9f0e3cced9f..f88069f5003 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -276,8 +276,17 @@ value value_ind (arg1) value arg1; { + /* Must do this before COERCE_ARRAY, otherwise an infinite loop + will result. */ + if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF) + return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), + (CORE_ADDR) value_as_long (arg1)); + COERCE_ARRAY (arg1); + if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_MEMBER) + error ("not implemented: member types in value_ind"); + /* Allow * on an integer so we can cast it to whatever we want. */ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT) return value_at (builtin_type_long, @@ -285,6 +294,9 @@ value_ind (arg1) else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), (CORE_ADDR) value_as_long (arg1)); + else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF) + return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), + (CORE_ADDR) value_as_long (arg1)); error ("Attempt to take contents of a non-pointer value."); } @@ -406,11 +418,29 @@ call_function (function, nargs, args) 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 + { register CORE_ADDR funaddr; register struct type *ftype = VALUE_TYPE (function); register enum type_code code = TYPE_CODE (ftype); + /* If it's a member function, just look at the function + part of it. */ + if (code == TYPE_CODE_MEMBER) + { + ftype = TYPE_TARGET_TYPE (ftype); + code = TYPE_CODE (ftype); + } + /* Determine address to call. */ if (code == TYPE_CODE_FUNC) { @@ -444,24 +474,40 @@ call_function (function, nargs, args) /* Create a call sequence customized for this function and the number of arguments for it. */ bcopy (dummy, dummy1, sizeof dummy); +#ifdef sun4 + FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, value_type); +#else FIX_CALL_DUMMY (dummy1, funaddr, nargs); +#endif } - old_sp = sp = read_register (SP_REGNUM); + write_memory (start_sp, dummy1, sizeof dummy); + +#ifdef STACK_ALIGN + /* If stack grows down, we must leave a hole at the top. */ + { + int len = 0; + for (i = nargs - 1; i >= 0; i--) + len += TYPE_LENGTH (VALUE_TYPE (args[i])); + len += CALL_DUMMY_STACK_ADJUST; +#if 1 INNER_THAN 2 + sp -= STACK_ALIGN (len) - len; +#else + sp += STACK_ALIGN (len) - len; +#endif + } +#endif -#if 1 INNER_THAN 2 /* Stack grows down */ - sp -= sizeof dummy; - write_memory (sp, dummy1, sizeof dummy); - start_sp = sp; for (i = nargs - 1; i >= 0; i--) sp = value_arg_push (sp, args[i]); -#else /* Stack grows up */ - start_sp = sp; - write_memory (sp, dummy1, sizeof dummy); - sp += sizeof dummy; - for (i = 0; i < nargs; i++) - sp = value_arg_push (sp, args[i]); -#endif /* Stack grows up */ + +#ifdef CALL_DUMMY_STACK_ADJUST +#if 1 INNER_THAN 2 + sp -= CALL_DUMMY_STACK_ADJUST; +#else + sp += CALL_DUMMY_STACK_ADJUST; +#endif +#endif write_register (SP_REGNUM, sp); @@ -552,16 +598,24 @@ value_string (ptr, len) /* Given ARG1, a value of type (pointer to a)* structure/union, extract the component named NAME from the ultimate target structure/union and return it as a value with its appropriate type. - ERR is used in the error message if ARG1's type is wrong. */ - + ERR is used in the error message if ARG1's type is wrong. + + C++: ARGS is a list of argument types to aid in the selection of + an appropriate method. Also, handle derived types. + + ERR is an error message to be printed in case the field is not found. */ + value -value_struct_elt (arg1, name, err) - register value arg1; +value_struct_elt (arg1, args, name, err) + register value arg1, *args; char *name; char *err; { register struct type *t; register int i; + int found = 0; + + struct type *baseclass; COERCE_ARRAY (arg1); @@ -569,28 +623,443 @@ value_struct_elt (arg1, name, err) /* Follow pointers until we get to a non-pointer. */ - while (TYPE_CODE (t) == TYPE_CODE_PTR) + while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF) { arg1 = value_ind (arg1); COERCE_ARRAY (arg1); t = VALUE_TYPE (arg1); } + if (TYPE_CODE (t) == TYPE_CODE_MEMBER) + error ("not implemented: member type in value_struct_elt"); + if (TYPE_CODE (t) != TYPE_CODE_STRUCT && TYPE_CODE (t) != TYPE_CODE_UNION) error ("Attempt to extract a component of a value that is not a %s.", err); - for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) + baseclass = t; + + if (!args) + { + /* if there are no arguments ...do this... */ + + /* Try as a variable first, because if we succeed, there + is less work to be done. */ + while (t) + { + for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) + { + if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + { + found = 1; + break; + } + } + + if (i >= 0) + return TYPE_FIELD_STATIC (t, i) + ? value_static_field (t, name, i) : value_field (arg1, i); + + if (TYPE_N_BASECLASSES (t) == 0) + break; + + t = TYPE_BASECLASS (t, 1); + VALUE_TYPE (arg1) = t; /* side effect! */ + } + + /* C++: If it was not found as a data field, then try to + return it as a pointer to a method. */ + t = baseclass; + VALUE_TYPE (arg1) = t; /* side effect! */ + + if (destructor_name_p (name, t)) + error ("use `info method' command to print out value of destructor"); + + while (t) + { + for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i) + { + if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name)) + { + error ("use `info method' command to print value of method \"%s\"", name); + } + } + + if (TYPE_N_BASECLASSES (t) == 0) + break; + + t = TYPE_BASECLASS (t, 1); + } + + if (found == 0) + error("there is no field named %s", name); + return 0; + } + + if (destructor_name_p (name, t)) + { + if (!args[1]) + { + /* destructors are a special case. */ + return (value)value_fn_field (arg1, 0, TYPE_FN_FIELDLIST_LENGTH (t, 0)); + } + else + { + error ("destructor should not have any argument"); + } + } + + /* This following loop is for methods with arguments. */ + while (t) + { + /* Look up as method first, because that is where we + expect to find it first. */ + for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--) + { + struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i); + + if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name)) + { + int j; + struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i); + + found = 1; + for (j = TYPE_FN_FIELDLIST_LENGTH (t, i) - 1; j >= 0; --j) + { + if (!typecmp (TYPE_FN_FIELD_ARGS (f, j), args)) + { + if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + return (value)value_virtual_fn_field (arg1, f, j, t); + else + return (value)value_fn_field (arg1, i, j); + } + } + } + } + + if (TYPE_N_BASECLASSES (t) == 0) + break; + + t = TYPE_BASECLASS (t, 1); + VALUE_TYPE (arg1) = t; /* side effect! */ + } + + if (found) + { + error ("Structure method %s not defined for arglist.", name); + return 0; + } + else + { + /* See if user tried to invoke data as function */ + t = baseclass; + while (t) + { + for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) + { + if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + { + found = 1; + break; + } + } + + if (i >= 0) + return TYPE_FIELD_STATIC (t, i) + ? value_static_field (t, name, i) : value_field (arg1, i); + + if (TYPE_N_BASECLASSES (t) == 0) + break; + + t = TYPE_BASECLASS (t, 1); + VALUE_TYPE (arg1) = t; /* side effect! */ + } + error ("Structure has no component named %s.", name); + } +} + +/* C++: return 1 is NAME is a legitimate name for the destructor + of type TYPE. If TYPE does not have a destructor, or + if NAME is inappropriate for TYPE, an error is signaled. */ +int +destructor_name_p (name, type) + char *name; + struct type *type; +{ + /* destructors are a special case. */ + char *dname = TYPE_NAME (type); + + if (name[0] == '~') + { + if (! TYPE_HAS_DESTRUCTOR (type)) + error ("type `%s' does not have destructor defined", + TYPE_NAME (type)); + /* Skip past the "struct " at the front. */ + while (*dname++ != ' ') ; + if (strcmp (dname, name+1)) + error ("destructor specification error"); + else + return 1; + } + return 0; +} + +/* C++: Given ARG1, a value of type (pointer to a)* structure/union, + return 1 if the component named NAME from the ultimate + target structure/union is defined, otherwise, return 0. */ + +int +check_field (arg1, name) + register value arg1; + char *name; +{ + register struct type *t; + register int i; + int found = 0; + + struct type *baseclass; + + COERCE_ARRAY (arg1); + + t = VALUE_TYPE (arg1); + + /* Follow pointers until we get to a non-pointer. */ + + while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF) + { + arg1 = value_ind (arg1); + COERCE_ARRAY (arg1); + t = VALUE_TYPE (arg1); + } + + if (TYPE_CODE (t) == TYPE_CODE_MEMBER) + error ("not implemented: member type in check_field"); + + if (TYPE_CODE (t) != TYPE_CODE_STRUCT + && TYPE_CODE (t) != TYPE_CODE_UNION) + error ("Internal error: `this' is not an aggregate"); + + baseclass = t; + + while (t) { - if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) + { + if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + { + return 1; + } + } + + if (TYPE_N_BASECLASSES (t) == 0) break; + + t = TYPE_BASECLASS (t, 1); + VALUE_TYPE (arg1) = t; /* side effect! */ } - if (i < 0) - error ("Structure has no component named %s.", name); + /* C++: If it was not found as a data field, then try to + return it as a pointer to a method. */ + t = baseclass; + VALUE_TYPE (arg1) = t; /* side effect! */ - return value_field (arg1, i); + /* Destructors are a special case. */ + if (destructor_name_p (name, t)) + return 1; + + while (t) + { + for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i) + { + if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name)) + return 1; + } + + if (TYPE_N_BASECLASSES (t) == 0) + break; + + t = TYPE_BASECLASS (t, 1); + } + return 0; +} + +/* C++: Given an aggregate type DOMAIN, and a member name NAME, + return the address of this member as a pointer to member + type. If INTYPE is non-null, then it will be the type + of the member we are looking for. This will help us resolve + pointers to member functions. */ + +value +value_struct_elt_for_address (domain, intype, name) + struct type *domain, *intype; + char *name; +{ + register struct type *t = domain; + register int i; + int found = 0; + value v; + + struct type *baseclass; + + if (TYPE_CODE (t) != TYPE_CODE_STRUCT + && TYPE_CODE (t) != TYPE_CODE_UNION) + error ("Internal error: non-aggregate type to value_struct_elt_for_address"); + + baseclass = t; + + while (t) + { + for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--) + { + if (!strcmp (TYPE_FIELD_NAME (t, i), name)) + { + if (TYPE_FIELD_PACKED (t, i)) + error ("pointers to bitfield members not allowed"); + + v = value_from_long (builtin_type_int, TYPE_FIELD_BITPOS (t, i) >> 3); + VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FIELD_TYPE (t, i), baseclass)); + return v; + } + } + + if (TYPE_N_BASECLASSES (t) == 0) + break; + + t = TYPE_BASECLASS (t, 1); + } + + /* C++: If it was not found as a data field, then try to + return it as a pointer to a method. */ + t = baseclass; + + /* Destructors are a special case. */ + if (destructor_name_p (name, t)) + { + error ("pointers to destructors not implemented yet"); + } + + /* Perform all necessary dereferencing. */ + while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR) + intype = TYPE_TARGET_TYPE (intype); + + while (t) + { + for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i) + { + if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name)) + { + int j = TYPE_FN_FIELDLIST_LENGTH (t, i); + struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i); + + if (intype == 0 && j > 1) + error ("non-unique member `%s' requires type instantiation", name); + if (intype) + { + while (j--) + if (TYPE_FN_FIELD_TYPE (f, j) == intype) + break; + if (j < 0) + error ("no member function matches that type instantiation"); + } + else + j = 0; + + if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + { + v = value_from_long (builtin_type_long, + TYPE_FN_FIELD_VOFFSET (f, j)); + } + else + { + struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j), + 0, VAR_NAMESPACE); + v = locate_var_value (s, 0); + } + VALUE_TYPE (v) = lookup_pointer_type (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j), baseclass)); + return v; + } + } + + if (TYPE_N_BASECLASSES (t) == 0) + break; + + t = TYPE_BASECLASS (t, 1); + } + return 0; +} + +/* Compare two argument lists and return the position in which they differ, + or zero if equal. Note that we ignore the first argument, which is + the type of the instance variable. This is because we want to handle + derived classes. This is not entirely correct: we should actually + check to make sure that a requested operation is type secure, + shouldn't we? */ +int typecmp(t1, t2) + struct type *t1[]; + value t2[]; +{ + int i; + + if (t1[0]->code == TYPE_CODE_VOID) return 0; + if (!t1[1]) return 0; + for (i = 1; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++) + { + if (! t2[i] + || t1[i]->code != t2[i]->type->code + || t1[i]->target_type != t2[i]->type->target_type) + { + return i+1; + } + } + if (!t1[i]) return 0; + return t2[i] ? i+1 : 0; +} + +#ifndef FRAME +#include "frame.h" +#endif + +/* C++: return the value of the class instance variable, if one exists. + Flag COMPLAIN signals an error if the request is made in an + inappropriate context. */ +value +value_of_this (complain) + int complain; +{ + extern FRAME selected_frame; + struct symbol *func, *sym; + char *funname = 0; + struct block *b; + int i; + + if (selected_frame == 0) + if (complain) + error ("no frame selected"); + else return 0; + + func = get_frame_function (selected_frame); + if (func) + funname = SYMBOL_NAME (func); + else + if (complain) + error ("no `this' in nameless context"); + else return 0; + + b = SYMBOL_BLOCK_VALUE (func); + i = BLOCK_NSYMS (b); + if (i <= 0) + if (complain) + error ("no args, no `this'"); + else return 0; + + sym = BLOCK_SYM (b, 0); + if (strncmp ("$this", SYMBOL_NAME (sym), 5)) + if (complain) + error ("current stack frame not in method"); + else return 0; + + return read_var_value (sym, selected_frame); } static diff --git a/gdb/valprint.c b/gdb/valprint.c index 8087ef8248c..1aae021ecbb 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -33,6 +33,7 @@ static int print_max; static void type_print_varspec_suffix (); static void type_print_varspec_prefix (); static void type_print_base (); +static void type_print_method_args (); START_FILE @@ -82,7 +83,7 @@ value_print (val, stream, format) if (i) fprintf (stream, ", "); val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, - VALUE_ADDRESS (val) + typelen * i, stream, format); + VALUE_ADDRESS (val) + typelen * i, stream, format, 1); } if (i < n) fprintf (stream, "..."); @@ -92,15 +93,21 @@ value_print (val, stream, format) else { /* A simple (nonrepeated) value */ - /* If it is a pointer, indicate what it points to. */ - if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR) + /* If it is a pointer, indicate what it points to. + + C++: print type also if it is a reference. + + If it is a member pointer, we will take care + of that when we print it. */ + if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR + || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF) { fprintf (stream, "("); type_print (VALUE_TYPE (val), "", stream, -1); fprintf (stream, ") "); } return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format); + VALUE_ADDRESS (val), stream, format, 1); } } @@ -110,18 +117,22 @@ value_print (val, stream, format) (a letter or 0 for natural format). If the data are a string pointer, returns the number of - sting characters printed. */ + sting characters printed. + + If DEREF_REF is nonzero, then dereference references, + otherwise just print them like pointers. */ int -val_print (type, valaddr, address, stream, format) +val_print (type, valaddr, address, stream, format, deref_ref) struct type *type; char *valaddr; CORE_ADDR address; FILE *stream; char format; + int deref_ref; { register int i; - int len; + int len, n_baseclasses; struct type *elttype; int eltlen; int val; @@ -158,7 +169,7 @@ val_print (type, valaddr, address, stream, format) { if (i) fprintf (stream, ", "); val_print (elttype, valaddr + i * eltlen, - 0, stream, format); + 0, stream, format, deref_ref); } if (i < len) fprintf (stream, "..."); @@ -174,53 +185,205 @@ val_print (type, valaddr, address, stream, format) print_scalar_formatted (valaddr, type, format, 0, stream); break; } - fprintf (stream, "0x%x", * (int *) valaddr); - /* For a pointer to char or unsigned char, - also print the string pointed to, unless pointer is null. */ - - /* For an array of chars, print with string syntax. */ - elttype = TYPE_TARGET_TYPE (type); - if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT - && format == 0 - && unpack_long (type, valaddr) != 0) + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) { - fputc (' ', stream); - fputc ('"', stream); - for (i = 0; i < print_max; i++) + struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); + struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type)); + struct fn_field *f; + int j, len2; + char *kind = ""; + + val = unpack_long (builtin_type_int, valaddr); + if (TYPE_CODE (target) == TYPE_CODE_FUNC) { - QUIT; - read_memory (unpack_long (type, valaddr) + i, &c, 1); - if (c == 0) - break; - printchar (c, stream, '"'); + if (val < 128) + { + len = TYPE_NFN_FIELDS (domain); + for (i = 0; i < len; i++) + { + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + + for (j = 0; j < len2; j++) + { + QUIT; + if (TYPE_FN_FIELD_VOFFSET (f, j) == val) + { + kind = "virtual"; + goto common; + } + } + } + } + else + { + struct symbol *sym = find_pc_function (val); + if (sym == 0) + error ("invalid pointer to member function"); + len = TYPE_NFN_FIELDS (domain); + for (i = 0; i < len; i++) + { + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + + for (j = 0; j < len2; j++) + { + QUIT; + if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) + goto common; + } + } + } + common: + if (i < len) + { + fputc ('&', stream); + type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); + fprintf (stream, kind); + if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' + && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", + TYPE_FN_FIELDLIST_NAME (domain, i), stream); + else + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j), "", + TYPE_FN_FIELDLIST_NAME (domain, i), stream); + break; + } + } + else + { + /* VAL is a byte offset into the structure type DOMAIN. + Find the name of the field for that offset and + print it. */ + int extra = 0; + int bits = 0; + len = TYPE_NFIELDS (domain); + val <<= 3; /* @@ Make VAL into bit offset */ + for (i = 0; i < len; i++) + { + int bitpos = TYPE_FIELD_BITPOS (domain, i); + QUIT; + if (val == bitpos) + break; + if (val < bitpos && i > 0) + { + int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target)); + /* Somehow pointing into a field. */ + i -= 1; + extra = (val - TYPE_FIELD_BITPOS (domain, i)); + if (extra & 0x3) + bits = 1; + else + extra >>= 3; + break; + } + } + if (i < len) + { + fputc ('&', stream); + type_print_base (domain, stream, 0, 0); + fprintf (stream, "::"); + fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i)); + if (extra) + fprintf (stream, " + %d bytes", extra); + if (bits) + fprintf (stream, " (offset in bits)"); + break; + } + } + fputc ('(', stream); + type_print (type, "", stream, -1); + fprintf (stream, ") %d", val >> 3); + } + else + { + fprintf (stream, "0x%x", * (int *) valaddr); + /* For a pointer to char or unsigned char, + also print the string pointed to, unless pointer is null. */ + + /* For an array of chars, print with string syntax. */ + elttype = TYPE_TARGET_TYPE (type); + if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT + && format == 0 + && unpack_long (type, valaddr) != 0) + { + fputc (' ', stream); + fputc ('"', stream); + for (i = 0; i < print_max; i++) + { + QUIT; + read_memory (unpack_long (type, valaddr) + i, &c, 1); + if (c == 0) + break; + printchar (c, stream, '"'); + } + fputc ('"', stream); + if (i == print_max) + fprintf (stream, "..."); + fflush (stream); + /* Return number of characters printed, plus one for the + terminating null if we have "reached the end". */ + return i + (i != print_max); } - fputc ('"', stream); - if (i == print_max) - fprintf (stream, "..."); - fflush (stream); - /* Return number of characters printed, plus one for the - terminating null if we have "reached the end". */ - return i + (i != print_max); } break; + case TYPE_CODE_MEMBER: + error ("not implemented: member type in val_print"); + break; + + case TYPE_CODE_REF: + fprintf (stream, "0x%x", * (int *) valaddr); + /* De-reference the reference. */ + if (deref_ref) + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) + { + value val = value_at (TYPE_TARGET_TYPE (type), * (int *)valaddr); + fprintf (stream, " = "); + val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), + VALUE_ADDRESS (val), stream, format, deref_ref); + } + else + fprintf (stream, " = ???"); + break; + case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: fprintf (stream, "{"); len = TYPE_NFIELDS (type); - for (i = 0; i < len; i++) + n_baseclasses = TYPE_N_BASECLASSES (type); + for (i = 1; i <= n_baseclasses; i++) { - if (i) fprintf (stream, ", "); + fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_BASECLASS (type, i))); + val_print (TYPE_FIELD_TYPE (type, 0), + valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8, + 0, stream, 0, 0); + } + if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type)); + for (i -= 1; i < len; i++) + { + if (i > n_baseclasses) fprintf (stream, ", "); fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i)); - if (TYPE_FIELD_PACKED (type, i)) + /* check if static field */ + if (TYPE_FIELD_STATIC (type, i)) + { + value v; + + v = value_static_field (type, TYPE_FIELD_NAME (type, i), i); + val_print (TYPE_FIELD_TYPE (type, i), + VALUE_CONTENTS (v), 0, stream, format, deref_ref); + } + else if (TYPE_FIELD_PACKED (type, i)) { val = unpack_field_as_long (type, valaddr, i); - val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format); + val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format, deref_ref); } else val_print (TYPE_FIELD_TYPE (type, i), valaddr + TYPE_FIELD_BITPOS (type, i) / 8, - 0, stream, format); + 0, stream, format, deref_ref); } fprintf (stream, "}"); break; @@ -367,13 +530,96 @@ type_print_1 (type, varstring, stream, show, level) ((show > 0 || TYPE_NAME (type) == 0) && (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC - || code == TYPE_CODE_ARRAY))) + || code == TYPE_CODE_ARRAY + || code == TYPE_CODE_MEMBER + || code == TYPE_CODE_REF))) fprintf (stream, " "); type_print_varspec_prefix (type, stream, show, 0); fprintf (stream, "%s", varstring); type_print_varspec_suffix (type, stream, show, 0); } +/* Print the method arguments ARGS to the file STREAM. */ +static void +type_print_method_args (args, prefix, varstring, stream) + struct type **args; + char *prefix, *varstring; + FILE *stream; +{ + int i; + + fprintf (stream, " %s%s (", prefix, varstring); + if (args[1] && args[1]->code != TYPE_CODE_VOID) + { + i = 1; /* skip the class variable */ + while (1) + { + type_print (args[i++], "", stream, 0); + if (!args[i]) + { + fprintf (stream, " ..."); + break; + } + else if (args[i]->code != TYPE_CODE_VOID) + { + fprintf (stream, ", "); + } + else break; + } + } + fprintf (stream, ")"); +} + +/* If TYPE is a derived type, then print out derivation + information. Print out all layers of the type heirarchy + until we encounter one with multiple inheritance. + At that point, print out that ply, and return. */ +static void +type_print_derivation_info (stream, type) + FILE *stream; + struct type *type; +{ + char *name; + int i, n_baseclasses = TYPE_N_BASECLASSES (type); + struct type *basetype = 0; + + while (type && n_baseclasses == 1) + { + basetype = TYPE_BASECLASS (type, 1); + if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) + { + while (*name != ' ') name++; + fprintf (stream, ": %s%s %s ", + TYPE_VIA_PUBLIC (basetype) ? "public" : "private", + TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", + name + 1); + } + n_baseclasses = TYPE_N_BASECLASSES (basetype); + type = basetype; + } + + if (type) + { + if (n_baseclasses != 0) + fprintf (stream, ": "); + for (i = 1; i <= n_baseclasses; i++) + { + basetype = TYPE_BASECLASS (type, i); + if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) + { + while (*name != ' ') name++; + fprintf (stream, "%s%s %s", + TYPE_VIA_PUBLIC (basetype) ? "public" : "private", + TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "", + name + 1); + } + if (i < n_baseclasses) + fprintf (stream, ", "); + } + putc (' ', stream); + } +} + /* Print any asterisks or open-parentheses needed before the variable name (to describe its type). @@ -404,6 +650,20 @@ type_print_varspec_prefix (type, stream, show, passed_a_ptr) fputc ('*', stream); break; + case TYPE_CODE_MEMBER: + type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, + passed_a_ptr); + fputc (' ', stream); + type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, + passed_a_ptr); + fprintf (stream, "::"); + break; + + case TYPE_CODE_REF: + type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); + fputc ('&', stream); + break; + case TYPE_CODE_FUNC: case TYPE_CODE_ARRAY: type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); @@ -445,7 +705,14 @@ type_print_varspec_suffix (type, stream, show, passed_a_ptr) fprintf (stream, "]"); break; + case TYPE_CODE_MEMBER: + if (passed_a_ptr) + fputc (')', stream); + type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0); + break; + case TYPE_CODE_PTR: + case TYPE_CODE_REF: type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1); break; @@ -501,6 +768,8 @@ type_print_base (type, stream, show, level) { case TYPE_CODE_ARRAY: case TYPE_CODE_PTR: + case TYPE_CODE_MEMBER: + case TYPE_CODE_REF: case TYPE_CODE_FUNC: type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); break; @@ -521,12 +790,23 @@ type_print_base (type, stream, show, level) fprintf (stream, "{...}"); else { + int i; + + type_print_derivation_info (stream, type); + fprintf (stream, "{"); len = TYPE_NFIELDS (type); - fprintf (stream, "\n"); - for (i = 0; i < len; i++) + if (len) fprintf (stream, "\n"); + else fprintf (stream, "\n"); + + for (i = TYPE_N_BASECLASSES (type); i < len; i++) { QUIT; + /* Don't print out virtual function table. */ + if (! strncmp (TYPE_FIELD_NAME (type, i), + "_vptr$", 6)) + continue; + print_spaces (level + 4, stream); /* If this is a bit-field and there is a gap before it, @@ -550,6 +830,10 @@ type_print_base (type, stream, show, level) /* Print the declaration of this field. */ + if (TYPE_FIELD_STATIC (type, i)) + { + fprintf (stream, "static "); + } type_print_1 (TYPE_FIELD_TYPE (type, i), TYPE_FIELD_NAME (type, i), stream, show - 1, level + 4); @@ -561,6 +845,37 @@ type_print_base (type, stream, show, level) fprintf (stream, ";\n"); } + + /* C++: print out the methods */ + len = TYPE_NFN_FIELDS (type); + if (len) fprintf (stream, "\n"); + for (i = 0; i < len; i++) + { + struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); + int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); + + for (j = 0; j < len2; j++) + { + QUIT; + print_spaces (level + 4, stream); + if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + fprintf (stream, "virtual "); + type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0); + if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' + && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", + TYPE_FN_FIELDLIST_NAME (type, i), stream); + else + type_print_method_args + (TYPE_FN_FIELD_ARGS (f, j), "", + TYPE_FN_FIELDLIST_NAME (type, i), stream); + + fprintf (stream, ";\n"); + } + if (len2) fprintf (stream, "\n"); + } + print_spaces (level, stream); fputc ('}', stream); } diff --git a/gdb/value.h b/gdb/value.h index e67f17eb3da..dcaf2456a74 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -56,10 +56,14 @@ typedef struct value *value; #define VALUE_REGNO(val) (val)->regno /* If ARG is an array, convert it to a pointer. - If ARG is an enum, convert it to an integer. */ + If ARG is an enum, convert it to an integer. + + References are dereferenced. */ #define COERCE_ARRAY(arg) \ -{ if (VALUE_REPEATED (arg) \ +{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_REF) \ + arg = value_ind (arg); \ + if (VALUE_REPEATED (arg) \ || TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY) \ arg = value_coerce_array (arg); \ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \ @@ -69,7 +73,9 @@ typedef struct value *value; /* If ARG is an enum, convert it to an integer. */ #define COERCE_ENUM(arg) \ -{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \ +{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_REF) \ + arg = value_ind (arg); \ + if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \ arg = value_cast (builtin_type_unsigned_int, arg); \ } @@ -108,7 +114,7 @@ value value_addr (); value value_assign (); value value_neg (); value value_lognot (); -value value_struct_elt (); +value value_struct_elt (), value_struct_elt_for_address (); value value_field (); value value_cast (); value value_repeat (); @@ -129,3 +135,11 @@ struct internalvar *lookup_internalvar (); int value_equal (); int value_less (); int value_zerop (); + +/* C++ */ +value value_of_this (); +value value_static_field (); +value value_x_binop (); +value value_x_unop (); +int binop_user_defined_p (); +int unop_user_defined_p (); diff --git a/gdb/values.c b/gdb/values.c index b9c55df0ad8..0d5fc278c31 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -425,7 +425,12 @@ value_as_double (val) /* Unpack raw data (copied from debugee) 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. */ + and can convert between fixed and floating point. + + 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. */ long unpack_long (type, valaddr) @@ -474,11 +479,14 @@ unpack_long (type, valaddr) if (len == sizeof (long)) return * (long *) valaddr; } - else if (code == TYPE_CODE_PTR) + else if (code == TYPE_CODE_PTR + || code == TYPE_CODE_REF) { if (len == sizeof (char *)) return (CORE_ADDR) * (char **) valaddr; } + else if (code == TYPE_CODE_MEMBER) + error ("not impelmented: member types in unpack_long"); error ("Value not integer or pointer."); } @@ -543,7 +551,9 @@ unpack_double (type, valaddr) /* Given a value ARG1 of a struct or union type, extract and return the value of one of its fields. - FIELDNO says which field. */ + FIELDNO says which field. + + For C++, must also be able to return values from static fields. */ value value_field (arg1, fieldno) @@ -581,6 +591,138 @@ value_field (arg1, fieldno) return v; } +value +value_fn_field (arg1, fieldno, subfieldno) + register value arg1; + register int fieldno; +{ + 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); + 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. + 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. + TYPE is the basetype which first provides the virtual function table. */ +value +value_virtual_fn_field (arg1, f, j, type) + value arg1; + struct fn_field *f; + int j; + struct type *type; +{ + /* 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 vfn, vtbl; + value vi = value_from_long (builtin_type_int, TYPE_FN_FIELD_VOFFSET (f, j)); + VALUE_TYPE (arg1) = TYPE_VPTR_BASETYPE (type); + + /* 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 (type) < 0) + TYPE_VPTR_FIELDNO (type) + = fill_in_vptr_fieldno (type); + + /* Pretend that this array is just an array of pointers to integers. + This will have to change for multiple inheritance. */ + vtbl = value_copy (value_field (arg1, TYPE_VPTR_FIELDNO (type))); + VALUE_TYPE (vtbl) = lookup_pointer_type (builtin_type_int); + + /* Index into the virtual function table. */ + vfn = value_subscript (vtbl, vi); + + /* 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; + + if (fieldno < 0) + { + register struct type *t = type; + /* Look for static field. */ + while (t) + { + int i; + for (i = TYPE_NFIELDS (t) - 1; i >= 0; 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"); + } + t = TYPE_BASECLASS (t, 1); + } + + t = type; + + if (destructor_name_p (fieldname, t)) + error ("use `info method' command to print out value of destructor"); + + while (t) + { + int i, j; + + for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--) + { + if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname)) + { + error ("use `info method' command to print value of method \"%s\"", fieldname); + } + } + t = TYPE_BASECLASS (t, 1); + } + error("there is no field named %s", fieldname); + } + + found: + + sym = lookup_symbol (TYPE_FIELD_STATIC_PHYSNAME (type, fieldno), + 0, VAR_NAMESPACE); + if (! sym) error ("Internal error: could not find physical static variable named %s", TYPE_FIELD_BITSIZE (type, fieldno)); + + type = TYPE_FIELD_TYPE (type, fieldno); + v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); + return v; +} + long unpack_field_as_long (type, valaddr, fieldno) struct type *type; diff --git a/gdb/version.c b/gdb/version.c index b681739205f..d4bbebeab91 100644 --- a/gdb/version.c +++ b/gdb/version.c @@ -1,3 +1,3 @@ /* Define the current version number of GDB. */ -char *version = "2.8"; +char *version = "2.8.1 (GNU C++ 1.31.0 compatible)"; -- 2.30.2