* configure.in, dbxread.c, hppa-coredep.c, hppa-pinsn.c,
authorStu Grossman <grossman@cygnus>
Fri, 19 Jun 1992 22:43:49 +0000 (22:43 +0000)
committerStu Grossman <grossman@cygnus>
Fri, 19 Jun 1992 22:43:49 +0000 (22:43 +0000)
hppabsd-core.c, hppabsd-tdep.c, hppabsd-xdep.c, hppahpux-tdep.c,
hppahpux-xdep.c, munch, partial-stab.h, tm-hppabsd.h,
tm-hppahpux.h, xm-hppabsd.h, xm-hppahpux.h:  HPPA merge.

16 files changed:
gdb/ChangeLog
gdb/configure.in
gdb/dbxread.c
gdb/hppa-coredep.c [new file with mode: 0644]
gdb/hppa-pinsn.c [new file with mode: 0644]
gdb/hppabsd-core.c [new file with mode: 0644]
gdb/hppabsd-tdep.c [new file with mode: 0644]
gdb/hppabsd-xdep.c [new file with mode: 0644]
gdb/hppahpux-tdep.c [new file with mode: 0644]
gdb/hppahpux-xdep.c [new file with mode: 0644]
gdb/munch
gdb/partial-stab.h
gdb/tm-hppabsd.h [new file with mode: 0644]
gdb/tm-hppahpux.h [new file with mode: 0644]
gdb/xm-hppabsd.h [new file with mode: 0644]
gdb/xm-hppahpux.h [new file with mode: 0644]

index a443329..9b75e68 100644 (file)
@@ -1,5 +1,10 @@
 Fri Jun 19 15:30:15 1992  Stu Grossman  (grossman at cygnus.com)
 
+       * configure.in, dbxread.c, hppa-coredep.c, hppa-pinsn.c,
+       hppabsd-core.c, hppabsd-tdep.c, hppabsd-xdep.c, hppahpux-tdep.c,
+       hppahpux-xdep.c, munch, partial-stab.h, tm-hppabsd.h,
+       tm-hppahpux.h, xm-hppabsd.h, xm-hppahpux.h:  HPPA merge.
+
        * Makefile.in (c-exp.tab.c, m2-exp.tab.c):  Filter out bogus extern
        declarations of malloc/realloc/free that are inserted by some
        versions of yacc.
index 5312f92..ace1ba0 100644 (file)
@@ -155,6 +155,17 @@ arm | merlin | none | np1 | pn | pyramid | tahoe)
        gdb_host=${host_cpu}
        ;;
 
+hppa)
+       case "${host_vendor}" in
+       hp)
+               case "${host_os}" in
+               hpux)   gdb_host=hppahpux ;;
+               bsd)    gdb_host=hppabsd ;;
+               esac
+               ;;
+       esac
+       ;;
+
 ### unhandled hosts
 #altosgas
 #i386v-g
@@ -326,6 +337,17 @@ rs6000)
        gdb_target=rs6000
        ;;
 
+hppa)
+       case "${target_vendor}" in
+       hp)
+               case "${target_os}" in
+               hpux)   gdb_target=hppahpux ;;
+               bsd)    gdb_target=hppabsd ;;
+               esac
+               ;;
+       esac
+       ;;
+
 ### unhandled targets
 # altosgas
 # i386v-g
index add45a9..84e9de8 100644 (file)
@@ -41,6 +41,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define L_INCR 1
 #endif
 
+#ifdef hp9000s800
+/* We don't want to use HP-UX's nlists. */
+#define _NLIST_INCLUDED
+#endif
+
 #include <obstack.h>
 #include <sys/param.h>
 #ifndef        NO_SYS_FILE
@@ -54,7 +59,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "target.h"
 #include "gdbcore.h"           /* for bfd stuff */
 #include "libbfd.h"            /* FIXME Secret internal BFD stuff (bfd_read) */
+#ifdef hp9000s800
+#include "libhppa.h"
+#include "syms.h"
+#else
 #include "libaout.h"           /* FIXME Secret internal BFD stuff for a.out */
+#endif
 #include "symfile.h"
 #include "objfiles.h"
 #include "buildsym.h"
@@ -66,6 +76,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    symbol files.  A pointer to this structure is kept in the sym_private
    field of the objfile struct.  */
  
+#ifdef hp9000s800
+struct dbx_symfile_info {
+  asection *text_sect;         /* Text section accessor */
+  int symcount;                        /* How many symbols are there in the file */
+  char *stringtab;             /* The actual string table */
+  int stringtab_size;          /* Its size */
+  off_t symtab_offset;         /* Offset in file to symbol table */
+  int hp_symcount;
+  char *hp_stringtab;
+  int hp_stringtab_size;
+  off_t hp_symtab_offset;
+};
+#else
 struct dbx_symfile_info {
   asection *text_sect;         /* Text section accessor */
   int symcount;                        /* How many symbols are there in the file */
@@ -74,6 +97,7 @@ struct dbx_symfile_info {
   off_t symtab_offset;         /* Offset in file to symbol table */
   int symbol_size;             /* Bytes in a single symbol */
 };
+#endif
 
 #define DBX_SYMFILE_INFO(o)    ((struct dbx_symfile_info *)((o)->sym_private))
 #define DBX_TEXT_SECT(o)       (DBX_SYMFILE_INFO(o)->text_sect)
@@ -82,6 +106,12 @@ struct dbx_symfile_info {
 #define DBX_STRINGTAB_SIZE(o)  (DBX_SYMFILE_INFO(o)->stringtab_size)
 #define DBX_SYMTAB_OFFSET(o)   (DBX_SYMFILE_INFO(o)->symtab_offset)
 #define DBX_SYMBOL_SIZE(o)     (DBX_SYMFILE_INFO(o)->symbol_size)
+#ifdef hp9000s800
+#define HP_SYMCOUNT(o)         (DBX_SYMFILE_INFO(o)->hp_symcount)
+#define HP_STRINGTAB(o)                (DBX_SYMFILE_INFO(o)->hp_stringtab)
+#define HP_STRINGTAB_SIZE(o)   (DBX_SYMFILE_INFO(o)->hp_stringtab_size)
+#define HP_SYMTAB_OFFSET(o)    (DBX_SYMFILE_INFO(o)->hp_symtab_offset)
+#endif
 
 /* Each partial symbol table entry contains a pointer to private data for the
    read_symtab() function to use when expanding a partial symbol table entry
@@ -470,7 +500,11 @@ dbx_symfile_read (objfile, addr, mainline)
   if (mainline || objfile->global_psymbols.size == 0 || objfile->static_psymbols.size == 0)
     init_psymbol_list (objfile);
 
+#ifdef hp9000s800
+  symbol_size = obj_dbx_symbol_entry_size (sym_bfd);
+#else
   symbol_size = DBX_SYMBOL_SIZE (objfile);
+#endif
   symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
 
   pending_blocks = 0;
@@ -539,8 +573,15 @@ dbx_symfile_init (objfile)
     xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
 
   /* FIXME POKING INSIDE BFD DATA STRUCTURES */
+#ifdef hp9000s800
+#define STRING_TABLE_OFFSET  (sym_bfd->origin + obj_dbx_str_filepos (sym_bfd))
+#define SYMBOL_TABLE_OFFSET  (sym_bfd->origin + obj_dbx_sym_filepos (sym_bfd))
+#define HP_STRING_TABLE_OFFSET  (sym_bfd->origin + obj_hp_str_filepos (sym_bfd))
+#define HP_SYMBOL_TABLE_OFFSET  (sym_bfd->origin + obj_hp_sym_filepos (sym_bfd))
+#else
 #define        STRING_TABLE_OFFSET     (sym_bfd->origin + obj_str_filepos (sym_bfd))
 #define        SYMBOL_TABLE_OFFSET     (sym_bfd->origin + obj_sym_filepos (sym_bfd))
+#endif
   /* FIXME POKING INSIDE BFD DATA STRUCTURES */
 
   DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
@@ -548,7 +589,12 @@ dbx_symfile_init (objfile)
     error ("Can't find .text section in symbol file");
 
   DBX_SYMBOL_SIZE   (objfile) = obj_symbol_entry_size (sym_bfd);
-  DBX_SYMCOUNT      (objfile) = bfd_get_symcount (sym_bfd);
+#ifdef hp9000s800
+  HP_SYMCOUNT (objfile) = obj_hp_sym_count (sym_bfd);
+  DBX_SYMCOUNT (objfile) = obj_dbx_sym_count (sym_bfd);
+#else
+  DBX_SYMCOUNT (objfile) = bfd_get_symcount (sym_bfd);
+#endif
   DBX_SYMTAB_OFFSET (objfile) = SYMBOL_TABLE_OFFSET;
 
   /* Read the string table and stash it away in the psymbol_obstack.  It is
@@ -563,6 +609,10 @@ dbx_symfile_init (objfile)
      however at least check to see if the size is zero or some negative
      value. */
 
+#ifdef hp9000s800
+  DBX_STRINGTAB_SIZE (objfile) = obj_dbx_stringtab_size (sym_bfd);
+  HP_STRINGTAB_SIZE (objfile) = obj_hp_stringtab_size (sym_bfd);
+#else
   val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, L_SET);
   if (val < 0)
     perror_with_name (name);
@@ -572,6 +622,8 @@ dbx_symfile_init (objfile)
     perror_with_name (name);
 
   DBX_STRINGTAB_SIZE (objfile) = bfd_h_get_32 (sym_bfd, size_temp);
+#endif
+
   if (DBX_STRINGTAB_SIZE (objfile) <= 0)
     error ("ridiculous string table size (%d bytes).",
           DBX_STRINGTAB_SIZE (objfile));
@@ -579,6 +631,15 @@ dbx_symfile_init (objfile)
   DBX_STRINGTAB (objfile) =
     (char *) obstack_alloc (&objfile -> psymbol_obstack,
                            DBX_STRINGTAB_SIZE (objfile));
+#ifdef hp9000s800
+  if (HP_STRINGTAB_SIZE (objfile) <= 0)
+    error ("ridiculous string table size (%d bytes).",
+          HP_STRINGTAB_SIZE (objfile));
+
+  HP_STRINGTAB (objfile) =
+    (char *) obstack_alloc (&objfile -> psymbol_obstack,
+                           HP_STRINGTAB_SIZE (objfile));
+#endif
 
   /* Now read in the string table in one big gulp.  */
 
@@ -589,6 +650,18 @@ dbx_symfile_init (objfile)
                  sym_bfd);
   if (val != DBX_STRINGTAB_SIZE (objfile))
     perror_with_name (name);
+#ifdef hp9000s800
+  val = bfd_seek (sym_bfd, HP_STRING_TABLE_OFFSET, L_SET);
+  if (val < 0)
+    perror_with_name (name);
+  val = bfd_read (HP_STRINGTAB (objfile), HP_STRINGTAB_SIZE (objfile), 1,
+                 sym_bfd);
+  if (val != HP_STRINGTAB_SIZE (objfile))
+    perror_with_name (name);
+#endif
+#ifdef hp9000s800
+  HP_SYMTAB_OFFSET (objfile) = HP_SYMBOL_TABLE_OFFSET;
+#endif
 }
 
 /* Perform any local cleanups required when we are done with a particular
@@ -642,6 +715,25 @@ fill_symbuf (sym_bfd)
   symbuf_end = nbytes / symbol_size;
   symbuf_idx = 0;
 }
+#ifdef hp9000s800
+/* same as above for the HP symbol table */
+
+static struct symbol_dictionary_record hp_symbuf[4096];
+static int hp_symbuf_idx;
+static int hp_symbuf_end;
+
+static int
+fill_hp_symbuf (sym_bfd)
+     bfd *sym_bfd;
+{
+  int nbytes = bfd_read ((PTR)hp_symbuf, sizeof (hp_symbuf), 1, sym_bfd);
+  if (nbytes <= 0)
+    error ("error or end of file reading symbol table");
+  hp_symbuf_end = nbytes / sizeof (struct symbol_dictionary_record);
+  hp_symbuf_idx = 0;
+  return 1;
+}
+#endif
 
 #define SWAP_SYMBOL(symp, abfd) \
   { \
@@ -689,8 +781,15 @@ init_psymbol_list (objfile)
   /* Current best guess is that there are approximately a twentieth
      of the total symbols (in a debugging file) are global or static
      oriented symbols */
+#ifdef hp9000s800
+  objfile -> global_psymbols.size = (DBX_SYMCOUNT (objfile) + 
+                                    HP_SYMCOUNT (objfile)) / 10;
+  objfile -> static_psymbols.size = (DBX_SYMCOUNT (objfile) +
+                                    HP_SYMCOUNT (objfile)) / 10;
+#else
   objfile -> global_psymbols.size = DBX_SYMCOUNT (objfile) / 10;
   objfile -> static_psymbols.size = DBX_SYMCOUNT (objfile) / 10;
+#endif
   objfile -> global_psymbols.next = objfile -> global_psymbols.list = (struct partial_symbol *)
     xmmalloc (objfile -> md, objfile -> global_psymbols.size * sizeof (struct partial_symbol));
   objfile -> static_psymbols.next = objfile -> static_psymbols.list = (struct partial_symbol *)
@@ -781,6 +880,14 @@ read_dbx_symtab (addr, objfile, text_addr, text_size)
   CORE_ADDR last_o_file_start = 0;
   struct cleanup *old_chain;
   bfd *abfd;
+#ifdef hp9000s800
+  /* HP stuff */
+  struct symbol_dictionary_record *hp_bufp;
+  int hp_symnum;
+  /* A hack: the first text symbol in the debugging library */
+  int dbsubc_addr = 0;
+#endif
+
 
   /* End of the text segment of the executable file.  */
   CORE_ADDR end_of_text_addr;
@@ -802,7 +909,11 @@ read_dbx_symtab (addr, objfile, text_addr, text_size)
   file_string_table_offset = 0;
   next_file_string_table_offset = 0;
 
+#ifdef hp9000s800
+  stringtab_global = HP_STRINGTAB (objfile);
+#else
   stringtab_global = DBX_STRINGTAB (objfile);
+#endif
   
   pst = (struct partial_symtab *) 0;
 
@@ -836,6 +947,75 @@ read_dbx_symtab (addr, objfile, text_addr, text_size)
   symbuf_end = symbuf_idx = 0;
   next_symbol_text_func = dbx_next_symbol_text;
 
+#ifdef hp9000s800
+  /* On pa machines, the global symbols are all in the regular HP-UX
+     symbol table. Read them in first. */
+
+  hp_symbuf_end = hp_symbuf_idx = 0;
+  bfd_seek (abfd, HP_SYMTAB_OFFSET (objfile), 0);
+
+  for (hp_symnum = 0; hp_symnum < HP_SYMCOUNT (objfile); hp_symnum++)
+    {
+      int dbx_type;
+
+      QUIT;
+      if (hp_symbuf_idx == hp_symbuf_end)
+        fill_hp_symbuf (abfd);
+      hp_bufp = &hp_symbuf[hp_symbuf_idx++];
+      switch (hp_bufp->symbol_type)
+        {
+        case ST_SYM_EXT:
+        case ST_ARG_EXT:
+          continue;
+        case ST_CODE:
+        case ST_PRI_PROG:
+        case ST_SEC_PROG:
+        case ST_ENTRY:
+        case ST_MILLICODE:
+          dbx_type = N_TEXT;
+          hp_bufp->symbol_value &= ~3; /* clear out permission bits */
+          break;
+        case ST_DATA:
+          dbx_type = N_DATA;
+          break;
+#ifdef KERNELDEBUG
+        case ST_ABSOLUTE:
+          {
+            extern int kernel_debugging;
+            if (!kernel_debugging)
+              continue;
+            dbx_type = N_ABS;
+            break;
+          }
+#endif
+        default:
+          continue;
+        }
+      /* Use the address of dbsubc to finish the last psymtab. */
+      if (hp_bufp->symbol_type == ST_CODE &&
+          HP_STRINGTAB (objfile)[hp_bufp->name.n_strx] == '_' &&
+          !strcmp (HP_STRINGTAB (objfile) + hp_bufp->name.n_strx, "_dbsubc"))
+        dbsubc_addr = hp_bufp->symbol_value;
+      if (hp_bufp->symbol_scope == SS_UNIVERSAL)
+        {
+          if (hp_bufp->name.n_strx > HP_STRINGTAB_SIZE (objfile))
+            error ("Invalid symbol data; bad HP string table offset: %d",
+                   hp_bufp->name.n_strx);
+          /* A hack, but gets the job done. */
+          if (!strcmp (hp_bufp->name.n_strx + HP_STRINGTAB (objfile), 
+                      "$START$"))
+           objfile -> ei.entry_file_lowpc = hp_bufp->symbol_value;
+          if (!strcmp (hp_bufp->name.n_strx + HP_STRINGTAB (objfile), 
+                      "_sr4export"))
+           objfile -> ei.entry_file_highpc = hp_bufp->symbol_value;
+          record_minimal_symbol (hp_bufp->name.n_strx + HP_STRINGTAB (objfile),
+                                hp_bufp->symbol_value, dbx_type | N_EXT, 
+                                objfile);
+        }
+    }
+  bfd_seek (abfd, DBX_SYMTAB_OFFSET (objfile), 0);
+#endif
+
   for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
     {
       /* Get the symbol for this run and pull out some info */
@@ -889,6 +1069,7 @@ read_dbx_symtab (addr, objfile, text_addr, text_size)
     }
 
   /* If there's stuff to be cleaned up, clean it up.  */
+#ifndef hp9000s800
   if (DBX_SYMCOUNT (objfile) > 0                       /* We have some syms */
 /*FIXME, does this have a bug at start address 0? */
       && last_o_file_start
@@ -898,12 +1079,19 @@ read_dbx_symtab (addr, objfile, text_addr, text_size)
       objfile -> ei.entry_file_lowpc = last_o_file_start;
       objfile -> ei.entry_file_highpc = bufp->n_value;
     }
+#endif
 
   if (pst)
     {
+#ifdef hp9000s800
+      end_psymtab (pst, psymtab_include_list, includes_used,
+                  symnum * symbol_size, dbsubc_addr,
+                  dependency_list, dependencies_used);
+#else
       end_psymtab (pst, psymtab_include_list, includes_used,
                   symnum * symbol_size, end_of_text_addr,
                   dependency_list, dependencies_used);
+#endif
     }
 
   free_bincl_list (objfile);
@@ -1184,7 +1372,11 @@ dbx_psymtab_to_symtab_1 (pst)
       buildsym_init ();
       old_chain = make_cleanup (really_free_pendings, 0);
       file_string_table_offset = FILE_STRING_OFFSET (pst);
+#ifdef hp9000s800
+      symbol_size = obj_dbx_symbol_entry_size (sym_bfd);
+#else
       symbol_size = SYMBOL_SIZE (pst);
+#endif
 
       /* Read in this file's symbols */
       bfd_seek (pst->objfile->obfd, SYMBOL_OFFSET (pst), L_SET);
@@ -1275,7 +1467,11 @@ read_ofile_symtab (objfile, sym_offset, sym_size, text_offset, text_size,
   current_objfile = objfile;
   subfile_stack = 0;
 
+#ifdef hp9000s800
+  stringtab_global = HP_STRINGTAB (objfile);
+#else
   stringtab_global = DBX_STRINGTAB (objfile);
+#endif
   last_source_file = 0;
 
   abfd = objfile->obfd;
@@ -1890,10 +2086,22 @@ static struct sym_fns bout_sym_fns =
   NULL                 /* next: pointer to next struct sym_fns */
 };
 
+static struct sym_fns hppa_sym_fns =
+{
+  "hppa",              /* sym_name: name or name prefix of BFD target type */
+  4,                   /* sym_namelen: number of significant sym_name chars */
+  dbx_new_init,                /* sym_new_init: init anything gbl to entire symtab */
+  dbx_symfile_init,    /* sym_init: read initial info, setup for sym_read() */
+  dbx_symfile_read,    /* sym_read: read a symbol file into symtab */
+  dbx_symfile_finish,  /* sym_finish: finished with file, cleanup */
+  NULL                 /* next: pointer to next struct sym_fns */
+};
+
 void
 _initialize_dbxread ()
 {
   add_symtab_fns(&sunos_sym_fns);
   add_symtab_fns(&aout_sym_fns);
   add_symtab_fns(&bout_sym_fns);
+  add_symtab_fns(&hppa_sym_fns);
 }
diff --git a/gdb/hppa-coredep.c b/gdb/hppa-coredep.c
new file mode 100644 (file)
index 0000000..7e1031e
--- /dev/null
@@ -0,0 +1,121 @@
+/* Extract registers from a "standard" core file, for GDB.
+   Copyright (C) 1988-1991  Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* core.c is supposed to be the more machine-independent aspects of this;
+   this file is more machine-specific.  */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include <stdio.h>
+
+/* These are needed on various systems to expand REGISTER_U_ADDR.  */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/user.h>
+#ifndef USG
+#include <sys/ptrace.h>
+#endif
+
+
+/* Extract the register values out of the core file and store
+   them where `read_register' will find them.
+
+   CORE_REG_SECT points to the register values themselves, read into memory.
+   CORE_REG_SIZE is the size of that area.
+   WHICH says which set of registers we are handling (0 = int, 2 = float
+         on machines where they are discontiguous).
+   REG_ADDR is the offset from u.u_ar0 to the register values relative to
+            core_reg_sect.  This is used with old-fashioned core files to
+           locate the registers in a large upage-plus-stack ".reg" section.
+           Original upage address X is at location core_reg_sect+x+reg_addr.
+ */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+     char *core_reg_sect;
+     unsigned core_reg_size;
+     int which;
+     unsigned reg_addr;
+{
+  register int regno;
+  register unsigned int addr;
+  int bad_reg = -1;
+  register reg_ptr = -reg_addr;                /* Original u.u_ar0 is -reg_addr. */
+
+  /* If u.u_ar0 was an absolute address in the core file, relativize it now,
+     so we can use it as an offset into core_reg_sect.  When we're done,
+     "register 0" will be at core_reg_sect+reg_ptr, and we can use
+     register_addr to offset to the other registers.  If this is a modern
+     core file without a upage, reg_ptr will be zero and this is all a big
+     NOP.  */
+  if (reg_ptr > core_reg_size)
+    reg_ptr -= KERNEL_U_ADDR;
+  if (reg_ptr > core_reg_size)
+    fprintf (stderr, "Can't find registers in core file\n");
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      addr = register_addr (regno, reg_ptr);
+      if (addr >= core_reg_size) {
+       if (bad_reg < 0)
+         bad_reg = regno;
+      } else {
+       if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+         core_reg_sect[addr +3] &= ~0x3;
+       supply_register (regno, core_reg_sect + addr);
+      }
+    }
+  if (bad_reg > 0)
+    {
+      error ("Register %s not found in core file.", reg_names[bad_reg]);
+    }
+}
+
+
+#ifdef REGISTER_U_ADDR
+
+/* Return the address in the core dump or inferior of register REGNO.
+   BLOCKEND is the address of the end of the user structure.  */
+
+unsigned int
+register_addr (regno, blockend)
+     int regno;
+     int blockend;
+{
+  int addr;
+
+  if (regno < 0 || regno >= NUM_REGS)
+    error ("Invalid register number %d.", regno);
+
+  REGISTER_U_ADDR (addr, blockend, regno);
+
+  return addr;
+}
+
+#endif /* REGISTER_U_ADDR */
+
+
+
+
+
+
+
diff --git a/gdb/hppa-pinsn.c b/gdb/hppa-pinsn.c
new file mode 100644 (file)
index 0000000..5d8df98
--- /dev/null
@@ -0,0 +1,382 @@
+/* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
+   Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB, the GNU disassembler.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+
+#include "defs.h"
+#include "symtab.h"
+#include "opcode/hppa.h"
+
+char *control_reg[] = {"rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+                      "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
+                      "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
+                      "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
+                      "tr4", "tr5", "tr6", "tr7"
+                      };
+
+char *compare_cond_names[] = {"", ",=", ",<", ",<=", ",<<", ",<<=", ",sv",
+                             ",od", ",tr", ",<>", ",>=", ",>", ",>>=",
+                             ",>>", ",nsv", ",ev"
+                             };
+char *add_cond_names[] = {"", ",=", ",<", ",<=", ",nuv", ",znv", ",sv",
+                         ",od", ",tr", ",<>", ",>=", ",>", ",uv",
+                         ",vnz", ",nsv", ",ev"
+                         };
+char *logical_cond_names[] = {"", ",=", ",<", ",<=", 0, 0, 0, ",od",
+                             ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"};
+char *unit_cond_names[] = {"", 0, ",sbz", ",shz", ",sdc", 0, ",sbc", ",shc",
+                          ",tr", 0, ",nbz", ",nhz", ",ndc", 0, ",nbc", ",nhc"
+                          };
+char *shift_cond_names[] = {"", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"};
+
+char *index_compl_names[] = {"", ",m", ",s", ",sm"};
+char *short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
+char *short_bytes_compl_names[] = {"", ",b,m", ",e", ",e,m"};
+char *float_format_names[] = {",sgl", ",dbl", ",quad"};
+char *float_comp_names[] =
+{",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
+ ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
+ ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
+ ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
+ };
+
+/* For a bunch of different instructions form an index into a 
+   completer name table. */
+#define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
+                        GET_FIELD (insn, 18, 18) << 1)
+
+#define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
+                       (GET_FIELD ((insn), 19, 19) ? 8 : 0))
+
+void fput_reg (), fput_const ();
+
+/* Print one instruction from MEMADDR on STREAM.  */
+int
+print_insn (memaddr, stream)
+     CORE_ADDR memaddr;
+     FILE *stream;
+{
+  unsigned int insn, i, op;
+
+  read_memory (memaddr, &insn, sizeof (insn));
+
+  for (i = 0; i < NUMOPCODES; ++i)
+    {
+      const struct pa_opcode *opcode = &pa_opcodes[i];
+      if ((insn & opcode->mask) == opcode->match)
+       {
+         register const char *s;
+         
+         fputs_filtered (opcode->name, stream);
+       
+         if (!index ("cCY<?!@-+&U>~nZFM", opcode->args[0]))
+           fputs_filtered (" ", stream);
+         for (s = opcode->args; *s != '\0'; ++s)
+           {
+             switch (*s)
+               {
+               case 'x':
+                 fput_reg (GET_FIELD (insn, 11, 15), stream);
+                 break;
+               case 'X':
+                  if (GET_FIELD (insn, 25, 25))
+                     fput_reg_r (GET_FIELD (insn, 11, 15), stream);
+                 else
+                     fput_reg (GET_FIELD (insn, 11, 15), stream);
+                 break;
+               case 'b':
+                 fput_reg (GET_FIELD (insn, 6, 10), stream);
+                 break;
+               case '^':
+                 fput_creg (GET_FIELD (insn, 6, 10), stream);
+                 break;
+               case 'E':
+                  if (GET_FIELD (insn, 25, 25))
+                     fput_reg_r (GET_FIELD (insn, 6, 10), stream);
+                 else
+                     fput_reg (GET_FIELD (insn, 6, 10), stream);
+                 break;
+               case 't':
+                 fput_reg (GET_FIELD (insn, 27, 31), stream);
+                 break;
+               case 'v':
+                  if (GET_FIELD (insn, 25, 25))
+                     fput_reg_r (GET_FIELD (insn, 27, 31), stream);
+                 else
+                     fput_reg (GET_FIELD (insn, 27, 31), stream);
+                 break;
+               case '4':
+                 fput_creg (GET_FIELD (insn, 6, 10), stream);
+                 break;
+               case '6':
+                 fput_reg (GET_FIELD (insn, 11, 15), stream);
+                 break;
+               case '7':
+                 fput_reg (GET_FIELD (insn, 27, 31), stream);
+                 break;
+               case '8':
+                 fput_reg (GET_FIELD (insn, 16, 20), stream);
+                 break;
+               case '9':
+                 fput_reg (GET_FIELD (insn, 21, 25), stream);
+                 break;
+               case '5':
+                 fput_const (extract_5_load (insn), stream);
+                 break;
+                 /* case 's': */
+               case 'S':
+                 fprintf_filtered (stream, "sr%d", extract_3 (insn));
+                 break;
+               case 'c':
+                 fprintf_filtered (stream, "%s ",
+                                   index_compl_names[GET_COMPL (insn)]);
+                 break;
+               case 'C':
+                 fprintf_filtered (stream, "%s ",
+                                   short_ldst_compl_names[GET_COMPL (insn)]);
+                 break;
+               case 'Y':
+                 fprintf_filtered (stream, "%s ",
+                                   short_bytes_compl_names[GET_COMPL (insn)]);
+                 break;
+               /* these four conditions are for the set of instructions
+                  which distinguish true/false conditions by opcode rather
+                  than by the 'f' bit (sigh): comb, comib, addb, addib */
+               case '<':
+                 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)],
+                                 stream);
+                 break;
+               case '?':
+                 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18) + 8],
+                                 stream);
+                 break;
+               case '!':
+                 fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18)],
+                                 stream);
+                 break;
+               case '@':
+                 fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18) + 8],
+                                 stream);
+                 break;
+               case '-':
+                 fprintf_filtered (stream, "%s ",
+                                   compare_cond_names[GET_COND (insn)]);
+                 break;
+               case '+':
+                 fprintf_filtered (stream, "%s ",
+                                   add_cond_names[GET_FIELD (insn, 16, 18)]);
+                 break;
+
+               case '&':
+                 fprintf_filtered (stream, "%s ",
+                                   logical_cond_names[GET_COND (insn)]);
+                 break;
+               case 'U':
+                 fprintf_filtered (stream, "%s ",
+                                   unit_cond_names[GET_COND (insn)]);
+                 break;
+               case '>':
+               case '~':
+                 fprintf_filtered (stream, "%s ",
+                                   shift_cond_names[GET_FIELD (insn, 16, 18)]);
+                 break;
+               case 'V':
+                 fput_const (extract_5_store (insn), stream);
+                 break;
+               case 'i':
+                 fput_const (extract_11 (insn), stream);
+                 break;
+               case 'j':
+                 fput_const (extract_14 (insn), stream);
+                 break;
+               case 'k':
+                 fput_const (extract_21 (insn), stream);
+                 break;
+               case 'n':
+                 if (insn & 0x2)
+                   fprintf_filtered (stream, ",n ");
+                 else
+                   fprintf_filtered (stream, " ");
+                 break;
+               case 'w':
+                 print_address (memaddr + 8 + extract_12 (insn), stream);
+                 break;
+               case 'W':
+                 /* don't interpret an address if it's an external branch
+                    instruction. */
+                 op = GET_FIELD (insn, 0, 5);
+                 if (op != 0x38 /* be */ && op != 0x39 /* ble */)
+                   print_address (memaddr + 8 + extract_17 (insn), stream);
+                 else
+                   fput_const (extract_17 (insn), stream);
+                 break;
+               case 'B':
+                 {
+                   int space;
+                   if (space = GET_FIELD (insn, 16, 17))
+                     fprintf_filtered (stream, "sr%d,", space);
+                   fput_reg (GET_FIELD (insn, 6, 10), stream);
+                   break;
+                 }
+               case 'p':
+                 fprintf_filtered (stream, "%d",
+                                   31 - GET_FIELD (insn, 22, 26));
+                 break;
+               case 'P':
+                 fprintf_filtered (stream, "%d",
+                                   GET_FIELD (insn, 22, 26));
+                 break;
+               case 'T':
+                 fprintf_filtered (stream, "%d",
+                                   32 - GET_FIELD (insn, 27, 31));
+                 break;
+               case 'A':
+                 fput_const (GET_FIELD (insn, 6, 18), stream);
+                 break;
+               case 'Z':
+                 if (GET_FIELD (insn, 26, 26))
+                   fprintf_filtered (stream, ",m ");
+                 else
+                   fprintf_filtered (stream, " ");
+                 break;
+               case 'D':
+                 fput_const (GET_FIELD (insn, 6, 31), stream);
+                 break;
+               case 'f':
+                 fprintf_filtered (stream, ",%d", GET_FIELD (insn, 23, 25));
+                 break;
+               case 'O':
+                 fput_const ((GET_FIELD (insn, 6,20) << 5 |
+                              GET_FIELD (insn, 27, 31)), stream);
+                 break;
+               case 'o':
+                 fput_const (GET_FIELD (insn, 6, 20), stream);
+                 break;
+               case '2':
+                 fput_const ((GET_FIELD (insn, 6, 22) << 5 |
+                              GET_FIELD (insn, 27, 31)), stream);
+                 break;
+               case '1':
+                 fput_const ((GET_FIELD (insn, 11, 20) << 5 |
+                              GET_FIELD (insn, 27, 31)), stream);
+                 break;
+               case '0':
+                 fput_const ((GET_FIELD (insn, 16, 20) << 5 |
+                              GET_FIELD (insn, 27, 31)), stream);
+                 break;
+               case 'u':
+                 fprintf_filtered (stream, "%d", GET_FIELD (insn, 23, 25));
+                 break;
+               case 'F':
+                 /* if no destination completer, need a space here */
+                 if (GET_FIELD (insn, 21, 22) == 1)
+                   fputs_filtered (float_format_names[GET_FIELD (insn, 19, 20)],
+                                   stream);
+                 else
+                   fprintf_filtered (stream, "%s ",
+                                     float_format_names[GET_FIELD
+                                                        (insn, 19, 20)]);
+                 break;
+               case 'G':
+                 fprintf_filtered (stream, "%s ",
+                                   float_format_names[GET_FIELD (insn,
+                                                                 17, 18)]);
+                 break;
+               case 'H':
+                   fputs_filtered (float_format_names[GET_FIELD 
+                                                      (insn, 26, 26)], stream);
+                 break;
+               case 'M':
+                 fputs_filtered (float_comp_names[GET_FIELD (insn, 27, 31)],
+                                 stream);
+                 break;
+               case '}':
+                 fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 6, 10));
+                 break;
+               case '|':
+                 fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 11, 15));
+                 break;
+               case '{':
+                 if (GET_FIELD (insn, 23, 25) == 0)
+                   fprintf_filtered (stream, "fp%d",
+                                     GET_FIELD (insn, 27, 31));
+                 else
+                   fprintf_filtered (stream, "cp%d",
+                                     GET_FIELD (insn, 27, 31));
+                 break;
+               default:
+                 fprintf_filtered (stream, "%c", *s);
+                 break;
+               }
+           }
+         return sizeof(insn);
+       }
+    }
+  fprintf_filtered (stream, "%#8x", insn);
+  return sizeof(insn);
+}
+  
+/* Utility function to print registers */
+
+void
+fput_reg (reg, stream)
+     unsigned reg;
+     FILE *stream;
+{
+  if (reg)
+    fputs_filtered (reg_names[reg], stream);
+  else
+    fputs_filtered ("r0", stream);
+}
+
+void
+fput_reg_r (reg, stream)
+     unsigned reg;
+     FILE *stream;
+{
+  if (reg)
+    fputs_filtered (reg_names[reg], stream);
+  else
+    fputs_filtered ("r0", stream);
+  fputs_filtered ("R", stream);
+}
+
+void
+fput_creg (reg, stream)
+     unsigned reg;
+     FILE *stream;
+{
+  fputs_filtered (control_reg[reg], stream);
+}
+
+/* print constants with sign */
+
+void
+fput_const (num, stream)
+     unsigned num;
+     FILE *stream;
+{
+  if ((int)num < 0)
+    fprintf_filtered (stream, "-%x", -(int)num);
+  else
+    fprintf_filtered (stream, "%x", num);
+}
diff --git a/gdb/hppabsd-core.c b/gdb/hppabsd-core.c
new file mode 100644 (file)
index 0000000..0fcc31c
--- /dev/null
@@ -0,0 +1,254 @@
+/* Machine-dependent code which would otherwise be in core.c
+   for GDB, the GNU debugger.  This code is for the HP PA-RISC cpu.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "param.h"
+#include "frame.h"
+#include "inferior.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h>  Can we live without this?  */
+
+#ifndef hpux
+#include <a.out.h>
+#include <machine/pcb.h>
+#include <sys/time.h>
+#include "/usr/src/sys/hpux/hpux.h"
+#define USRSTACK 0x68FF3000
+#else
+#include <sys/user.h>          /* After a.out.h  */
+#endif
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+
+#ifndef hpux
+#undef USIZE
+#undef UPAGES
+
+#define USIZE 3
+#define UPAGES 7
+#endif
+
+extern int errno;
+
+/* File names of core file and executable file.  */
+
+extern char *corefile;
+extern char *execfile;
+
+/* Descriptors on which core file and executable file are open.
+   Note that the execchan is closed when an inferior is created
+   and reopened if the inferior dies or is killed.  */
+
+extern int corechan;
+extern int execchan;
+
+/* Last modification time of executable file.
+   Also used in source.c to compare against mtime of a source file.  */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file.  */
+
+extern CORE_ADDR data_start;
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+   Note that the data area in the exec file is used only when there is no core file.  */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data.  */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data.  */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data.  */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data.  */
+
+extern int stack_offset;
+
+extern struct header file_hdr;
+extern struct som_exec_auxhdr exec_hdr;
+
+extern int (*core_file_hook)();
+
+#ifdef KERNELDEBUG
+
+extern int kernel_debugging;
+extern int kernel_core_file_hook();
+
+#endif
+
+core_file_command (filename, from_tty)
+     char *filename;
+     int from_tty;
+{
+  int val;
+  extern char registers[];
+#ifdef KERNELDEBUG
+  struct stat stb;
+#endif
+
+  /* Discard all vestiges of any previous core file
+     and mark data and stack spaces as empty.  */
+
+  if (corefile)
+    free (corefile);
+  corefile = 0;
+  core_file_hook = 0;
+
+  if (corechan >= 0)
+    close (corechan);
+  corechan = -1;
+
+  data_start = 0;
+  data_end = 0;
+  stack_start = STACK_END_ADDR;
+  stack_end = STACK_END_ADDR;
+
+  /* Now, if a new core file was specified, open it and digest it.  */
+
+  if (filename)
+    {
+      filename = tilde_expand (filename);
+      make_cleanup (free, filename);
+      
+      if (have_inferior_p ())
+       error ("To look at a core file, you must kill the inferior with \"kill\".");
+      corechan = open (filename, O_RDONLY, 0);
+      if (corechan < 0)
+       perror_with_name (filename);
+
+#ifdef KERNELDEBUG
+      fstat(corechan, &stb);
+
+      if (kernel_debugging) {
+             setup_kernel_debugging();
+             core_file_hook = kernel_core_file_hook;
+             set_kernel_boundaries();
+      } else if ((stb.st_mode & S_IFMT) == S_IFCHR &&
+                stb.st_rdev == makedev(2, 1)) {
+             /* looking at /dev/kmem */
+             data_offset = data_start = KERNBASE;
+             data_end = ~0; /* XXX */
+             stack_end = stack_start = data_end;
+             set_kernel_boundaries();
+      } else
+#endif
+      {
+       /* HP PA-RISC style corefile. */
+#ifndef hpux
+       struct hpuxuser u;
+#else
+       struct user u;
+#endif
+
+       unsigned int reg_offset;
+
+       val = myread (corechan, &u, sizeof u);
+       if (val < 0)
+         perror_with_name ("Not a core file: reading upage");
+       if (val != sizeof u)
+         error ("Not a core file: could only read %d bytes", val);
+
+       /* We are depending on exec_file_command having been called
+          previously to set exec_data_start.  Since the executable
+          and the core file share the same text segment, the address
+          of the data segment will be the same in both.  */
+       data_start = exec_data_start;
+
+       data_end = data_start + NBPG * u.u_dsize;
+       stack_start = USRSTACK; /* from sys/param.h */
+       stack_end = stack_start + NBPG * u.u_ssize;
+       data_offset = NBPG * UPAGES;
+       stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+       /* Some machines put an absolute address in here and some put
+          the offset in the upage of the regs.  */
+       reg_offset = NBPG * USIZE;
+       /* Read the register values out of the core file and store
+          them where `read_register' will find them.  */
+
+       {
+         register int regno;
+
+         for (regno = 0; regno < NUM_REGS; regno++)
+           {
+             unsigned char buf[MAX_REGISTER_RAW_SIZE];
+
+             val = lseek (corechan, register_addr (regno, reg_offset), 0);
+             if (val < 0
+                 || (val = myread (corechan, buf, sizeof buf)) < 0)
+               {
+                 char * buffer = (char *) alloca (strlen (reg_names[regno])
+                                                  + 30);
+                 strcpy (buffer, "Reading register ");
+                 strcat (buffer, reg_names[regno]);
+                                                  
+                 perror_with_name (buffer);
+               }
+             if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+               buf[3] &= ~0x3;
+             supply_register (regno, buf);
+           }
+       }
+      }
+      if (filename[0] == '/')
+       corefile = savestring (filename, strlen (filename));
+      else
+       {
+         corefile = concat (current_directory, "/", filename);
+       }
+
+      set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+                                           read_pc ()));
+      select_frame (get_current_frame (), 0);
+      validate_files ();
+    }
+  else if (from_tty)
+    printf ("No core file now.\n");
+}
diff --git a/gdb/hppabsd-tdep.c b/gdb/hppabsd-tdep.c
new file mode 100644 (file)
index 0000000..c9912b0
--- /dev/null
@@ -0,0 +1,1428 @@
+/* Machine-dependent code which would otherwise be in inflow.c and core.c,
+   for GDB, the GNU debugger.  This code is for the HP PA-RISC cpu.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "value.h"
+
+/* For argument passing to the inferior */
+#include "symtab.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h>  Can we live without this?  */
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#include <a.out.h>
+#endif
+#ifndef N_SET_MAGIC
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+
+/*#include <sys/user.h>                After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+#include <machine/psl.h>
+
+#ifdef KERNELDEBUG
+#include <sys/vmmac.h>
+#include <machine/machparam.h>
+#include <machine/vmparam.h>
+#include <machine/pde.h>
+#include <machine/cpu.h>
+#include <machine/iomod.h>
+#include <machine/pcb.h>
+#include <machine/rpb.h>
+#include <ctype.h>
+
+extern int kernel_debugging;
+extern CORE_ADDR startup_file_start;
+extern CORE_ADDR startup_file_end;
+
+#define        KERNOFF         ((unsigned)KERNBASE)
+#define        INKERNEL(x)     ((x) >= KERNOFF && (x) < KERNOFF + ctob(slr))
+
+static int ok_to_cache();
+static void set_kernel_boundaries();
+
+int devmem = 0;
+int vtophys_ready = 0;
+int kerneltype;
+#define        OS_BSD  1
+#define        OS_MACH 2
+#endif
+
+#include "gdbcore.h"
+#include "gdbcmd.h"
+
+extern int errno;
+\f
+
+
+
+
+
+/* Last modification time of executable file.
+   Also used in source.c to compare against mtime of a source file.  */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file.  */
+
+/* extern CORE_ADDR data_start; */
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+   Note that the data area in the exec file is used only when there is no core file.  */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data.  */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data.  */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data.  */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data.  */
+
+extern int stack_offset;
+
+struct header file_hdr;
+struct som_exec_auxhdr exec_hdr;
+\f
+#ifdef KERNELDEBUG
+/*
+ * Kernel debugging routines.
+ */
+
+static struct pcb pcb;
+static struct pde *pdir;
+static struct hte *htbl;
+static u_int npdir, nhtbl;
+
+static CORE_ADDR
+ksym_lookup(name)
+       char *name;
+{
+       struct symbol *sym;
+       int i;
+
+       if ((i = lookup_misc_func(name)) < 0)
+               error("kernel symbol `%s' not found.", name);
+
+       return (misc_function_vector[i].address);
+}
+
+/*
+ * (re-)set the variables that tell "inside_entry_file" where to end
+ * a stack backtrace.
+ */
+void
+set_kernel_boundaries()
+{
+       switch (kerneltype) {
+       case OS_MACH:
+               startup_file_start = ksym_lookup("$syscall");
+               startup_file_end = ksym_lookup("trap");
+               break;
+       case OS_BSD:
+               startup_file_start = ksym_lookup("syscallinit");
+               startup_file_end = ksym_lookup("$syscallexit");
+               break;
+       }
+}
+
+/*
+ * return true if 'len' bytes starting at 'addr' can be read out as
+ * longwords and/or locally cached (this is mostly for memory mapped
+ * i/o register access when debugging remote kernels).
+ */
+static int
+ok_to_cache(addr, len)
+{
+       static CORE_ADDR ioptr;
+
+       if (! ioptr)
+               ioptr = ksym_lookup("ioptr");
+
+       if (addr >= ioptr && addr < SPA_HIGH)
+               return (0);
+
+       return (1);
+}
+
+static
+physrd(addr, dat, len)
+       u_int addr;
+       char *dat;
+{
+       if (lseek(corechan, addr, L_SET) == -1)
+               return (-1);
+       if (read(corechan, dat, len) != len)
+               return (-1);
+
+       return (0);
+}
+
+/*
+ * When looking at kernel data space through /dev/mem or with a core file, do
+ * virtual memory mapping.
+ */
+static CORE_ADDR
+vtophys(space, addr)
+       unsigned space;
+       CORE_ADDR addr;
+{
+       struct pde *pptr;
+       u_int hindx, vpageno, ppageno;
+       CORE_ADDR phys = ~0;
+
+       if (!vtophys_ready) {
+               phys = addr;            /* XXX for kvread */
+       } else if (kerneltype == OS_BSD) {
+               /* make offset into a virtual page no */
+               vpageno = btop(addr);
+               /*
+                *  Determine index into hash table, initialize pptr to this
+                *  entry (since first word of pte & hte are same), and set
+                *  physical page number for first entry in chain.
+                */
+               hindx = pdirhash(space, addr) & (nhtbl-1);
+               pptr = (struct pde *) &htbl[hindx];
+               ppageno = pptr->pde_next;
+               while (1) {
+                       if (pptr->pde_end)
+                               break;
+                       pptr = &pdir[ppageno];
+                       /*
+                        *  If space id & virtual page number match, return
+                        *  "next PDIR entry of previous PDIR entry" as the
+                        *  physical page or'd with offset into page.
+                        */
+                       if (pptr->pde_space == space &&
+                           pptr->pde_page == vpageno) {
+                               phys = (CORE_ADDR) ((u_int)ptob(ppageno) |
+                                                   (addr & PGOFSET));
+                               break;
+                       }
+                       ppageno = pptr->pde_next;
+               }
+       }
+#ifdef MACHKERNELDEBUG
+       else if (kerneltype == OS_MACH) {
+               (void) mach_vtophys(space, addr, &phys);
+       }
+#endif
+#if 0
+       printf("vtophys(%x.%x) -> %x\n", space, addr, phys);
+#endif
+       return (phys);
+}
+
+static
+kvread(addr)
+       CORE_ADDR addr;
+{
+       CORE_ADDR paddr;
+
+       paddr = vtophys(0, addr);
+       if (paddr != ~0)
+               if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0)
+                       return (addr);
+
+       return (~0);
+}
+
+static void
+read_pcb(addr)
+     u_int addr;
+{
+       int i, off;
+       extern char registers[];
+       static int reg2pcb[] = {
+               /* RPB */
+               -1,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
+               18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+               45, 52, 51, 75, 74, 49, 53, 54, 55, 56, -1, 70, 66, 67, 68, 69,
+               71, 72, 73, 34, 42, 43, 44, 46, 47, 58, 59, 60, -1, -1, -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+               -1, -1, -1, -1,
+               /* BSD */
+               -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+               43, 64, 67, 68, 67, 47, 51, 52, 53, 54, -1, 35, 31, 32, 33, 34,
+               36, 37, 38, 39, 40, 41, 42, 44, 45, 56, 57, 58,102,103,104, -1,
+               70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 82, 84, 86, 88, 90, 92,
+               94, 96, 98, 100,
+               /* Mach */
+               -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+               14, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, 18, -1,
+               25, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 20, -1, -1, -1, 19,
+               21, 22, 23, 24, 26, 27, -1, 28, 29, -1, -1, -1, -1, -1, -1, -1,
+               34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, -1, -1, -1, -1, -1,
+               42, 44, 46, 48
+       };
+       static struct rpb *rpbaddr = (struct rpb *) 0;
+       static u_int rpbpcbaddr = 0;
+
+       if (!remote_debugging) {
+               /*
+                * If we are debugging a post-mortem and this is the first
+                * call of read_pcb, read the RPB.  Also assoicate the
+                * thread/proc running at the time with the RPB.
+                */
+               if (!devmem && rpbpcbaddr == 0) {
+                       CORE_ADDR raddr = ksym_lookup("rpb");
+                       int usepcb = 1;
+
+                       if (raddr != ~0) {
+                               rpbaddr = (struct rpb *) malloc(sizeof *rpbaddr);
+                               if (!physrd(raddr, (char *)rpbaddr, sizeof *rpbaddr)) {
+                                       rpbpcbaddr = addr;
+                                       usepcb = 0;
+                               }
+                       }
+                       if (usepcb) {
+                               error("cannot read rpb, using pcb for registers\n");
+                               if (rpbaddr)
+                                       free((char *)rpbaddr);
+                               rpbpcbaddr = ~0;
+                       }
+               }
+               if (physrd (addr, (char *)&pcb, sizeof pcb))
+                       error ("cannot read pcb at %x.\n", addr);
+       } else {
+               if (remote_read_inferior_memory(addr, (char *)&pcb, sizeof pcb))
+                       error ("cannot read pcb at %x.\n", addr);
+       }
+
+       if (kerneltype == OS_BSD) {
+               printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
+                      pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
+               off = NUM_REGS;
+       } else {
+               printf("pcb %lx psw %lx ksp %lx\n",
+                      addr, ((int *)&pcb)[31], ((int *)&pcb)[32]);
+               off = NUM_REGS * 2;
+       }
+       /*
+        * get the register values out of the sys pcb and
+        * store them where `read_register' will find them.
+        */
+       bzero(registers, REGISTER_BYTES);
+       for (i = 0; i < NUM_REGS; ++i)
+               if (reg2pcb[i+off] != -1)
+                       supply_register(i, &((int *)&pcb)[reg2pcb[i+off]]);
+       /*
+        * If the RPB is valid for this thread/proc use the register values
+        * contained there.
+        */
+       if (addr == rpbpcbaddr) {
+               off = 0;
+               for (i = 0; i < NUM_REGS; ++i)
+                       if (reg2pcb[i+off] != -1)
+                               supply_register(i, &((int *)rpbaddr)[reg2pcb[i+off]]);
+       }
+}
+
+void
+setup_kernel_debugging()
+{
+       struct stat stb;
+       CORE_ADDR addr;
+
+       fstat(corechan, &stb);
+       devmem = 0;
+       if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
+               devmem = 1;
+
+       /* XXX */
+       if (lookup_misc_func("Sysmap") < 0)
+               kerneltype = OS_MACH;
+       else
+               kerneltype = OS_BSD;
+
+       if (kerneltype == OS_BSD) {
+               int len, err = 0;
+
+               /*
+                * Hash table and PDIR are equivalently mapped
+                */
+               nhtbl = kvread(ksym_lookup("nhtbl"));
+               if (nhtbl != ~0) {
+                       len = nhtbl * sizeof(*htbl);
+                       htbl = (struct hte *) malloc(len);
+                       if (htbl) {
+                               addr = kvread(ksym_lookup("htbl"));
+                               if (physrd(addr, (char *)htbl, len))
+                                       err++;
+                       } else
+                               err++;
+               } else
+                       err++;
+               npdir = kvread(ksym_lookup("npdir"));
+               if (npdir != ~0) {
+                       len = npdir * sizeof(*pdir);
+                       pdir = (struct pde *) malloc(len);
+                       if (pdir) {
+                               addr = kvread(ksym_lookup("pdir"));
+                               if (physrd(addr, (char *)pdir, len))
+                                       err++;
+                       } else
+                               err++;
+               } else
+                       err++;
+               if (err) {
+                       error("cannot read PDIR/HTBL");
+                       return;
+               }
+               vtophys_ready = 1;
+
+               /*
+                * pcb where "panic" saved registers in first thing in
+                * current u-area.  The current u-area is pointed to by
+                * "uptr".
+                */
+               addr = kvread(ksym_lookup("uptr"));
+               if (addr == ~0) {
+                       error("cannot read current u-area address");
+                       return;
+               }
+               read_pcb(vtophys(0, addr));     /* XXX space */
+               if (!devmem) {
+                       /* find stack frame */
+                       CORE_ADDR panicstr;
+                       char buf[256];
+                       register char *cp;
+                       
+                       panicstr = kvread(ksym_lookup("panicstr"));
+                       if (panicstr == ~0)
+                               return;
+                       (void) kernel_core_file_hook(panicstr, buf, sizeof(buf));
+                       for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
+                               if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+                                       *cp = '?';
+                       if (*cp)
+                               *cp = '\0';
+                       printf("panic: %s\n", buf);
+               }
+       }
+#ifdef MACHKERNELDEBUG
+       else {
+               int *thread;
+
+               /*
+                * Set up address translation
+                */
+               if (mach_vtophys_init() == 0) {
+                       error("cannot initialize vtophys for Mach");
+                       return;
+               }
+               vtophys_ready = 1;
+
+               /*
+                * Locate active thread and read PCB
+                * XXX MAJOR HACK
+                *      - assumes uni-processor
+                *      - assumes position of pcb to avoid mach includes
+                */
+               thread = (int *)kvread(ksym_lookup("active_threads"));
+               addr = kvread(&thread[9]);              /* XXX: pcb addr */
+               read_pcb(vtophys(0, addr));
+       }
+#endif
+}
+
+vtop_command(arg)
+       char *arg;
+{
+       u_int sp, off, pa;
+
+       if (!arg)
+               error_no_arg("kernel virtual address");
+       if (!kernel_debugging)
+               error("not debugging kernel");
+
+       sp = 0;         /* XXX */
+       off = (u_int) parse_and_eval_address(arg);
+       pa = vtophys(sp, off);
+       printf("%lx.%lx -> ", sp, off);
+       if (pa == ~0)
+               printf("<invalid>\n");
+       else
+               printf("%lx\n", pa);
+}
+
+set_paddr_command(arg)
+       char *arg;
+{
+       u_int addr;
+
+       if (!arg) {
+               if (kerneltype == OS_BSD)
+                       error_no_arg("ps-style address for new process");
+               else
+                       error_no_arg("thread structure virtual address");
+       }
+       if (!kernel_debugging)
+               error("not debugging kernel");
+
+       addr = (u_int) parse_and_eval_address(arg);
+       if (kerneltype == OS_BSD)
+               addr = ctob(addr);
+       else {
+               addr = kvread(&(((int *)addr)[9]));     /* XXX: pcb addr */
+               addr = vtophys(0, addr);                /* XXX space */
+       }
+       read_pcb(addr);
+
+       flush_cached_frames();
+       set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
+       select_frame(get_current_frame(), 0);
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local 
+ * buffer 'buf'.  Return 0 if read ok, 1 otherwise.  On read
+ * errors, portion of buffer not read is zeroed.
+ */
+kernel_core_file_hook(addr, buf, len)
+       CORE_ADDR addr;
+       char *buf;
+       int len;
+{
+       int i;
+       CORE_ADDR paddr;
+
+       while (len > 0) {
+               paddr = vtophys(0, addr);       /* XXX space */
+               if (paddr == ~0) {
+                       bzero(buf, len);
+                       return (1);
+               }
+               /* we can't read across a page boundary */
+               i = min(len, NBPG - (addr & PGOFSET));
+               if (physrd(paddr, buf, i)) {
+                       bzero(buf, len);
+                       return (1);
+               }
+               buf += i;
+               addr += i;
+               len -= i;
+       }
+       return (0);
+}
+#endif
+
+
+\f
+
+
+/* Routines to extract various sized constants out of hppa 
+   instructions. */
+
+/* This assumes that no garbage lies outside of the lower bits of 
+   value. */
+
+int
+sign_extend (val, bits)
+     unsigned val, bits;
+{
+  return (int)(val >> bits - 1 ? (-1 << bits) | val : val);
+}
+
+/* For many immediate values the sign bit is the low bit! */
+
+int
+low_sign_extend (val, bits)
+     unsigned val, bits;
+{
+  return (int)((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
+}
+/* extract the immediate field from a ld{bhw}s instruction */
+
+
+
+unsigned
+get_field (val, from, to)
+     unsigned val, from, to;
+{
+  val = val >> 31 - to;
+  return val & ((1 << 32 - from) - 1);
+}
+
+unsigned
+set_field (val, from, to, new_val)
+     unsigned *val, from, to;
+{
+  unsigned mask = ~((1 << (to - from + 1)) << (31 - from));
+  return *val = *val & mask | (new_val << (31 - from));
+}
+
+/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
+
+extract_3 (word)
+     unsigned word;
+{
+  return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
+}
+       
+extract_5_load (word)
+     unsigned word;
+{
+  return low_sign_extend (word >> 16 & MASK_5, 5);
+}
+
+/* extract the immediate field from a st{bhw}s instruction */
+
+int
+extract_5_store (word)
+     unsigned word;
+{
+  return low_sign_extend (word & MASK_5, 5);
+}
+
+/* extract an 11 bit immediate field */
+
+int
+extract_11 (word)
+     unsigned word;
+{
+  return low_sign_extend (word & MASK_11, 11);
+}
+
+/* extract a 14 bit immediate field */
+
+int
+extract_14 (word)
+     unsigned word;
+{
+  return low_sign_extend (word & MASK_14, 14);
+}
+
+/* deposit a 14 bit constant in a word */
+
+unsigned
+deposit_14 (opnd, word)
+     int opnd;
+     unsigned word;
+{
+  unsigned sign = (opnd < 0 ? 1 : 0);
+
+  return word | ((unsigned)opnd << 1 & MASK_14)  | sign;
+}
+
+/* extract a 21 bit constant */
+
+int
+extract_21 (word)
+     unsigned word;
+{
+  int val;
+
+  word &= MASK_21;
+  word <<= 11;
+  val = GET_FIELD (word, 20, 20);
+  val <<= 11;
+  val |= GET_FIELD (word, 9, 19);
+  val <<= 2;
+  val |= GET_FIELD (word, 5, 6);
+  val <<= 5;
+  val |= GET_FIELD (word, 0, 4);
+  val <<= 2;
+  val |= GET_FIELD (word, 7, 8);
+  return sign_extend (val, 21) << 11;
+}
+
+/* deposit a 21 bit constant in a word. Although 21 bit constants are
+   usually the top 21 bits of a 32 bit constant, we assume that only
+   the low 21 bits of opnd are relevant */
+
+unsigned
+deposit_21 (opnd, word)
+     unsigned opnd, word;
+{
+  unsigned val = 0;
+
+  val |= GET_FIELD (opnd, 11 + 14, 11 + 18);
+  val <<= 2;
+  val |= GET_FIELD (opnd, 11 + 12, 11 + 13);
+  val <<= 2;
+  val |= GET_FIELD (opnd, 11 + 19, 11 + 20);
+  val <<= 11;
+  val |= GET_FIELD (opnd, 11 + 1, 11 + 11);
+  val <<= 1;
+  val |= GET_FIELD (opnd, 11 + 0, 11 + 0);
+  return word | val;
+}
+
+/* extract a 12 bit constant from branch instructions */
+
+int
+extract_12 (word)
+     unsigned word;
+{
+  return sign_extend (GET_FIELD (word, 19, 28) |
+                     GET_FIELD (word, 29, 29) << 10 |
+                     (word & 0x1) << 11, 12) << 2;
+}
+
+/* extract a 17 bit constant from branch instructions, returning the
+   19 bit signed value. */
+
+int
+extract_17 (word)
+     unsigned word;
+{
+  return sign_extend (GET_FIELD (word, 19, 28) |
+                     GET_FIELD (word, 29, 29) << 10 |
+                     GET_FIELD (word, 11, 15) << 11 |
+                     (word & 0x1) << 16, 17) << 2;
+}
+
+
+CORE_ADDR
+frame_saved_pc (frame)
+     FRAME frame;
+{
+  if (get_current_frame () == frame)
+    {
+      struct frame_saved_regs saved_regs;
+
+      get_frame_saved_regs (frame, &saved_regs);
+      if (saved_regs.regs[RP_REGNUM])
+       return read_memory_integer (saved_regs.regs[RP_REGNUM], 4);
+      else
+       return read_register (RP_REGNUM);
+    }
+  return read_memory_integer (frame->frame - 20, 4) & ~0x3;
+}
+
+/* To see if a frame chain is valid, see if the caller looks like it
+   was compiled with gcc. */
+
+int frame_chain_valid (chain, thisframe)
+     FRAME_ADDR chain;
+     FRAME thisframe;
+{
+  if (chain && (chain > 0x60000000 
+               /* || remote_debugging   -this is no longer used */
+#ifdef KERNELDEBUG
+               || kernel_debugging
+#endif
+               ))
+    {
+      CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe));
+
+      if (!inside_entry_file (pc))
+       return 0;
+      /* look for stw rp, -20(0,sp); copy 4,1; copy sp, 4 */
+      if (read_memory_integer (pc, 4) == 0x6BC23FD9)                   
+       pc = pc + 4;                                                    
+      
+      if (read_memory_integer (pc, 4) == 0x8040241 &&
+         read_memory_integer (pc + 4, 4) == 0x81E0244)                 
+       return 1;
+      else
+       return 0;
+    }
+  else
+    return 0;
+}
+
+/* Some helper functions. gcc_p returns 1 if the function beginning at 
+   pc appears to have been compiled with gcc. hpux_cc_p returns 1 if
+   fn was compiled with hpux cc. gcc functions look like :
+
+   stw     rp,-0x14(sp) ; optional
+   or      r4,r0,r1
+   or      sp,r0,r4
+   stwm    r1,framesize(sp)
+
+   hpux cc functions look like:
+
+   stw     rp,-0x14(sp) ; optional.
+   stwm    r3,framesiz(sp)
+   */
+
+gcc_p (pc)
+     CORE_ADDR pc;
+{
+  if (read_memory_integer (pc, 4) == 0x6BC23FD9)                       
+    pc = pc + 4;                                                       
+      
+  if (read_memory_integer (pc, 4) == 0x8040241 &&
+      read_memory_integer (pc + 4, 4) == 0x81E0244)                    
+    return 1;
+  return 0;
+}
+
+  
+find_dummy_frame_regs (frame, frame_saved_regs)
+     struct frame_info *frame;
+     struct frame_saved_regs *frame_saved_regs;
+{
+  CORE_ADDR fp = frame->frame;
+  int i;
+  
+  frame_saved_regs->regs[RP_REGNUM] = fp - 20 & ~0x3;
+  frame_saved_regs->regs[FP_REGNUM] = fp;
+  frame_saved_regs->regs[1] = fp + 8;
+  frame_saved_regs->regs[3] = fp + 12;
+  for (fp += 16, i = 3; i < 30; fp += 4, i++)
+    frame_saved_regs->regs[i] = fp;
+  frame_saved_regs->regs[31] = fp;
+  fp += 4;
+  for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8)
+    frame_saved_regs->regs[i] = fp;
+  /* depend on last increment of fp */
+  frame_saved_regs->regs[IPSW_REGNUM] = fp - 4;
+  frame_saved_regs->regs[SAR_REGNUM] = fp;
+  fp += 4;
+  frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp;
+  frame_saved_regs->regs[PCSQ_TAIL_REGNUM] = fp;
+}
+
+CORE_ADDR
+hp_push_arguments (nargs, args, sp, struct_return, struct_addr)
+     int nargs;
+     value *args;
+     CORE_ADDR sp;
+     int struct_return;
+     CORE_ADDR struct_addr;
+{
+  /* array of arguments' offsets */
+  int *offset = (int *)alloca(nargs);
+  int cum = 0;
+  int i, alignment;
+  
+  for (i = 0; i < nargs; i++)
+    {
+      cum += TYPE_LENGTH (VALUE_TYPE (args[i]));
+      /* value must go at proper alignment. Assume alignment is a
+        power of two.*/
+      alignment = hp_alignof (VALUE_TYPE (args[i]));
+      if (cum % alignment)
+       cum = (cum + alignment) & -alignment;
+      offset[i] = -cum;
+    }
+  for (i == 0; i < nargs; i++)
+    {
+      write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), sizeof(int));
+    }
+  sp += min ((cum + 7) & -8, 48);
+  if (struct_return)
+    write_register (28, struct_addr);
+  return sp + 48;
+}
+
+/* return the alignment of a type in bytes. Structures have the maximum
+   alignment required by their fields. */
+
+int
+hp_alignof (arg)
+     struct type *arg;
+{
+  int max_align, align, i;
+  switch (TYPE_CODE (arg))
+    {
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_FLT:
+      return TYPE_LENGTH (arg);
+    case TYPE_CODE_ARRAY:
+      return hp_alignof (TYPE_FIELD_TYPE (arg, 0));
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      max_align = 2;
+      for (i = 0; i < TYPE_NFIELDS (arg); i++)
+       {
+         /* Bit fields have no real alignment. */
+         if (!TYPE_FIELD_BITPOS (arg, i))
+           {
+             align = hp_alignof (TYPE_FIELD_TYPE (arg, i));
+             max_align = max (max_align, align);
+           }
+       }
+      return max_align;
+    default:
+      return 4;
+    }
+}
+
+/* Print the register regnum, or all registers if regnum is -1 */
+
+pa_do_registers_info (regnum, fpregs)
+     int regnum;
+     int fpregs;
+{
+  char raw_regs [REGISTER_BYTES];
+  int i;
+  
+  for (i = 0; i < NUM_REGS; i++)
+    read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+  if (regnum = -1)
+    pa_print_registers (raw_regs, regnum);
+  else if (regnum < FP0_REGNUM)
+    {
+      printf ("%s %x\n", reg_names[regnum], *(long *)(raw_regs +
+                                                     REGISTER_BYTE (regnum)));
+    }
+  else
+    pa_print_fp_reg (regnum);
+}
+
+pa_print_registers (raw_regs, regnum)
+     char *raw_regs;
+     int regnum;
+{
+  int i;
+
+  for (i = 0; i < 18; i++)
+    printf ("%8.8s: %8x  %8.8s: %8x  %8.8s: %8x  %8.8s: %8x\n",
+                    reg_names[i],
+                    *(int *)(raw_regs + REGISTER_BYTE (i)),
+                    reg_names[i + 18],
+                    *(int *)(raw_regs + REGISTER_BYTE (i + 18)),
+                    reg_names[i + 36],
+                    *(int *)(raw_regs + REGISTER_BYTE (i + 36)),
+                    reg_names[i + 54],
+                    *(int *)(raw_regs + REGISTER_BYTE (i + 54)));
+  for (i = 72; i < NUM_REGS; i++)
+    pa_print_fp_reg (i);
+}
+
+pa_print_fp_reg (i)
+     int i;
+{
+  unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+  REGISTER_TYPE val;
+
+  /* Get the data in raw format, then convert also to virtual format.  */
+  read_relative_register_raw_bytes (i, raw_buffer);
+  REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
+
+  fputs_filtered (reg_names[i], stdout);
+  print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
+
+  val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0,
+            1, 0, Val_pretty_default);
+  printf_filtered ("\n");
+
+}
+
+/*
+ * Virtual to physical translation routines for Utah's Mach 3.0
+ */
+#ifdef MACHKERNELDEBUG
+
+#define STATIC
+
+#if 0  /* too many includes to resolve, too much crap */
+#include <kern/queue.h>
+#include <vm/pmap.h>   
+#include <mach/vm_prot.h>
+#else
+/* queue.h */
+struct queue_entry {
+       struct queue_entry      *next;          /* next element */
+       struct queue_entry      *prev;          /* previous element */
+};
+
+typedef struct queue_entry     *queue_t;
+typedef        struct queue_entry      queue_head_t;
+typedef        struct queue_entry      queue_chain_t;
+typedef        struct queue_entry      *queue_entry_t;
+
+/* pmap.h */
+#define HP800_HASHSIZE         1024
+#define HP800_HASHSIZE_LOG2    10
+
+#define pmap_hash(space, offset) \
+       (((unsigned) (space) << 5 ^ \
+         ((unsigned) (offset) >> 19 | (unsigned) (space) << 13) ^ \
+         (unsigned) (offset) >> 11) & (HP800_HASHSIZE-1))
+
+struct mapping {
+       queue_head_t    hash_link;      /* hash table links */
+       queue_head_t    phys_link;      /* for mappings of a given PA */
+       space_t         space;          /* virtual space */
+       unsigned        offset;         /* virtual page number */
+       unsigned        tlbpage;        /* physical page (for TLB load) */
+       unsigned        tlbprot;        /* prot/access rights (for TLB load) */
+       struct pmap     *pmap;          /* pmap mapping belongs to */
+};
+
+struct phys_entry {
+       queue_head_t    phys_link;      /* head of mappings of a given PA */
+       struct mapping  *writer;        /* mapping with R/W access */
+       unsigned        tlbprot;        /* TLB format protection */
+};
+
+#endif
+
+#define atop(a)                ((unsigned)(a) >> 11)
+#define ptoa(p)                ((unsigned)(p) << 11)
+#define trunc_page(a)  ((unsigned)(a) & ~2047)
+
+STATIC long equiv_end;
+STATIC queue_head_t *Ovtop_table, *vtop_table, *Ofree_mapping, free_mapping;
+STATIC struct phys_entry *Ophys_table, *phys_table;
+STATIC long vm_last_phys, vm_first_phys;
+STATIC struct mapping *firstmap, *lastmap, *Omap_table, *map_table;
+STATIC unsigned Omlow, Omhigh, Omhead, Ovlow, Ovhigh, Oplow, Ophigh;
+STATIC unsigned mlow, mhigh, mhead, vlow, vhigh, plow, phigh;
+STATIC int vtopsize, physsize, mapsize;
+STATIC int kmemfd;
+
+#define IS_OVTOPPTR(p) ((unsigned)(p) >= Ovlow && (unsigned)(p) < Ovhigh)
+#define IS_OMAPPTR(p)  ((unsigned)(p) >= Omlow && (unsigned)(p) < Omhigh)
+#define IS_OPHYSPTR(p) ((unsigned)(p) >= Oplow && (unsigned)(p) < Ophigh)
+#define IS_VTOPPTR(p)  ((unsigned)(p) >= vlow && (unsigned)(p) < vhigh)
+#define IS_MAPPTR(p)   ((unsigned)(p) >= mlow && (unsigned)(p) < mhigh)
+#define IS_PHYSPTR(p)  ((unsigned)(p) >= plow && (unsigned)(p) < phigh)
+
+struct mapstate {
+       char    unused;
+       char    flags;
+       short   hashix;
+       short   physix;
+} *mapstate;
+
+/* flags */
+#define M_ISFREE       1
+#define M_ISHASH       2
+#define M_ISPHYS       4
+
+mach_vtophys_init()
+{
+       int errors = 0;
+
+       if (!readdata())
+               errors++;
+       if (!verifydata())
+               errors++;
+       if (!errors)
+               return(1);
+       fflush(stdout);
+       fprintf(stderr,
+               "translate: may not be able to translate all addresses\n");
+       return(0);
+}
+
+mach_vtophys(space, off, pa)
+       unsigned space, off, *pa;
+{
+       register int i;
+       register queue_t qp;
+       register struct mapping *mp;
+       int poff;
+
+       /*
+        * Kernel IO or equivilently mapped, one to one.
+        */
+       if (space == 0 && (long)off < equiv_end) {
+               *pa = off;
+               return(1);
+       }
+       /*
+        * Else look it up in specified space
+        */
+       poff = off - trunc_page(off);
+       off = trunc_page(off);
+       qp = &vtop_table[pmap_hash(space, off)];
+       for (mp = (struct mapping *)qp->next;
+            qp != (queue_entry_t)mp;
+            mp = (struct mapping *)mp->hash_link.next) {
+               if (mp->space == space && mp->offset == off) {
+                       *pa = (mp->tlbpage << 7) | poff;
+                       return(1);
+               }
+       }
+       return(0);
+}
+
+STATIC
+readdata()
+{
+       char *tmp, *mach_malloc();
+       long size;
+
+       /* easy scalars */
+       mach_read("equiv_end", ~0, (char *)&equiv_end, sizeof equiv_end);
+       mach_read("vm_first_phys", ~0,
+                 (char *)&vm_first_phys, sizeof vm_first_phys);
+       mach_read("vm_last_phys", ~0,
+                 (char *)&vm_last_phys, sizeof vm_last_phys);
+       mach_read("firstmap", ~0, (char *)&firstmap, sizeof firstmap);
+       mach_read("lastmap", ~0, (char *)&lastmap, sizeof lastmap);
+
+       /* virtual to physical hash table */
+       vtopsize = HP800_HASHSIZE;
+       size = vtopsize * sizeof(queue_head_t);
+       tmp = mach_malloc("vtop table", size);
+       mach_read("vtop_table", ~0, (char *)&Ovtop_table, sizeof Ovtop_table);
+       mach_read("vtop table", (CORE_ADDR)Ovtop_table, tmp, size);
+       vtop_table = (queue_head_t *) tmp;
+
+       /* inverted page table */
+       physsize = atop(vm_last_phys - vm_first_phys);
+       size = physsize * sizeof(struct phys_entry);
+       tmp = mach_malloc("phys table", size);
+       mach_read("phys_table", ~0, (char *)&Ophys_table, sizeof Ophys_table);
+       mach_read("phys table", (CORE_ADDR)Ophys_table, tmp, size);
+       phys_table = (struct phys_entry *) tmp;
+
+       /* mapping structures */
+       Ofree_mapping = (queue_head_t *) ksym_lookup("free_mapping");
+       mach_read("free mapping", (CORE_ADDR)Ofree_mapping,
+                 (char *) &free_mapping, sizeof free_mapping);
+       Omap_table = firstmap;
+       mapsize = lastmap - firstmap;
+       size = mapsize * sizeof(struct mapping);
+       tmp = mach_malloc("mapping table", size);
+       mach_read("mapping table", (CORE_ADDR)Omap_table, tmp, size);
+       map_table = (struct mapping *) tmp;
+
+       /* set limits */
+       Ovlow = (unsigned) Ovtop_table;
+       Ovhigh = (unsigned) &Ovtop_table[vtopsize];
+       Oplow = (unsigned) Ophys_table;
+       Ophigh = (unsigned) &Ophys_table[physsize];
+       Omhead = (unsigned) Ofree_mapping;
+       Omlow = (unsigned) firstmap;
+       Omhigh = (unsigned) lastmap;
+       mlow = (unsigned) map_table;
+       mhigh = (unsigned) &map_table[mapsize];
+       mhead = (unsigned) &free_mapping;
+       vlow = (unsigned) vtop_table;
+       vhigh = (unsigned) &vtop_table[vtopsize];
+       plow = (unsigned) phys_table;
+       phigh = (unsigned) &phys_table[physsize];
+
+#if 0
+       fprintf(stderr, "Ovtop [%#x-%#x) Ophys [%#x-%#x) Omap %#x [%#x-%#x)\n",
+               Ovlow, Ovhigh, Oplow, Ophigh, Omhead, Omlow, Omhigh);
+       fprintf(stderr, "vtop [%#x-%#x) phys [%#x-%#x) map %#x [%#x-%#x)\n",
+               vlow, vhigh, plow, phigh, mhead, mlow, mhigh);
+#endif
+       return(adjustdata());
+}
+
+STATIC unsigned
+ptrcvt(ptr)
+       unsigned ptr;
+{
+       unsigned ret;
+       char *str;
+
+       if (ptr == 0) {
+               ret = ptr;
+               str = "null";
+       } else if (IS_OVTOPPTR(ptr)) {
+               ret = vlow + (ptr - Ovlow);
+               str = "vtop";
+       } else if (IS_OPHYSPTR(ptr)) {
+               ret = plow + (ptr - Oplow);
+               str = "phys";
+       } else if (IS_OMAPPTR(ptr)) {
+               ret = mlow + (ptr - Omlow);
+               str = "map";
+       } else if (ptr == Omhead) {
+               ret = mhead;
+               str = "maphead";
+       } else {
+               error("bogus pointer %#x", ptr);
+               str = "wild";
+               ret = ptr;
+       }
+#if 0
+       fprintf(stderr, "%x (%s) -> %x\n", ptr, str, ret);
+#endif
+       return(ret);
+}
+
+STATIC int
+adjustdata()
+{
+       register int i, lim;
+       queue_head_t *nq;
+       struct phys_entry *np;
+       struct mapping *nm;
+
+       /* hash table */
+       lim = vtopsize;
+       for (nq = vtop_table; nq < &vtop_table[lim]; nq++) {
+               nq->next = (queue_entry_t) ptrcvt((unsigned)nq->next);
+               nq->prev = (queue_entry_t) ptrcvt((unsigned)nq->prev);
+       }
+
+       /* IPT */
+       lim = physsize;
+       for (np = phys_table; np < &phys_table[lim]; np++) {
+               np->phys_link.next = (queue_entry_t)
+                       ptrcvt((unsigned)np->phys_link.next);
+               np->phys_link.prev = (queue_entry_t)
+                       ptrcvt((unsigned)np->phys_link.prev);
+               np->writer = (struct mapping *) ptrcvt((unsigned)np->writer);
+       }
+
+       /* mapping table */
+       free_mapping.next = (queue_entry_t)ptrcvt((unsigned)free_mapping.next);
+       free_mapping.prev = (queue_entry_t)ptrcvt((unsigned)free_mapping.prev);
+       lim = mapsize;
+       for (nm = map_table; nm < &map_table[lim]; nm++) {
+               nm->hash_link.next = (queue_entry_t)
+                       ptrcvt((unsigned)nm->hash_link.next);
+               nm->hash_link.prev = (queue_entry_t)
+                       ptrcvt((unsigned)nm->hash_link.prev);
+               nm->phys_link.next = (queue_entry_t)
+                       ptrcvt((unsigned)nm->phys_link.next);
+               nm->phys_link.prev = (queue_entry_t)
+                       ptrcvt((unsigned)nm->phys_link.prev);
+       }
+       return(1);
+}
+
+/*
+ * Consistency checks, make sure:
+ *
+ *     1. all mappings are accounted for
+ *     2. no cycles
+ *     3. no wild pointers
+ *     4. consisent TLB state
+ */
+STATIC int
+verifydata()
+{
+       register struct mapstate *ms;
+       register int i;
+       int errors = 0;
+
+       mapstate = (struct mapstate *)
+               mach_malloc("map state", mapsize * sizeof(struct mapstate));
+       for (ms = mapstate; ms < &mapstate[mapsize]; ms++) {
+               ms->flags = 0;
+               ms->hashix = ms->physix = -2;
+       }
+
+       /*
+        * Check the free list
+        */
+       checkhashchain(&free_mapping, M_ISFREE, -1);
+       /*
+        * Check every hash chain
+        */
+       for (i = 0; i < vtopsize; i++)
+               checkhashchain(&vtop_table[i], M_ISHASH, i);
+       /*
+        * Check every phys chain
+        */
+       for (i = 0; i < physsize; i++)
+               checkphyschain(&phys_table[i].phys_link, M_ISPHYS, i);
+       /*
+        * Cycle through mapstate looking for anomolies
+        */
+       ms = mapstate;
+       for (i = 0; i < mapsize; i++) {
+               switch (ms->flags) {
+               case M_ISFREE:
+               case M_ISHASH|M_ISPHYS:
+                       break;
+               case 0:
+                       merror(ms, "not found");
+                       errors++;
+                       break;
+               case M_ISHASH:
+                       merror(ms, "in vtop but not phys");
+                       errors++;
+                       break;
+               case M_ISPHYS:
+                       merror(ms, "in phys but not vtop");
+                       errors++;
+                       break;
+               default:
+                       merror(ms, "totally bogus");
+                       errors++;
+                       break;
+               }
+               ms++;
+       }
+       return(errors ? 0 : 1);
+}
+
+STATIC void
+checkhashchain(qhp, flag, ix)
+       queue_entry_t qhp;
+{
+       register queue_entry_t qp, pqp;
+       register struct mapping *mp;
+       struct mapstate *ms;
+
+       qp = qhp->next;
+       /*
+        * First element is not a mapping structure,
+        * chain must be empty.
+        */
+       if (!IS_MAPPTR(qp)) {
+               if (qp != qhp || qp != qhp->prev)
+                       fatal("bad vtop_table header pointer");
+       } else {
+               pqp = qhp;
+               do {
+                       mp = (struct mapping *) qp;
+                       qp = &mp->hash_link;
+                       if (qp->prev != pqp)
+                               fatal("bad hash_link prev pointer");
+                       ms = &mapstate[mp-map_table];
+                       ms->flags |= flag;
+                       ms->hashix = ix;
+                       pqp = (queue_entry_t) mp;
+                       qp = qp->next;
+               } while (IS_MAPPTR(qp));
+               if (qp != qhp)
+                       fatal("bad hash_link next pointer");
+       }
+}
+
+STATIC void
+checkphyschain(qhp, flag, ix)
+       queue_entry_t qhp;
+{
+       register queue_entry_t qp, pqp;
+       register struct mapping *mp;
+       struct mapstate *ms;
+
+       qp = qhp->next;
+       /*
+        * First element is not a mapping structure,
+        * chain must be empty.
+        */
+       if (!IS_MAPPTR(qp)) {
+               if (qp != qhp || qp != qhp->prev)
+                       fatal("bad phys_table header pointer");
+       } else {
+               pqp = qhp;
+               do {
+                       mp = (struct mapping *) qp;
+                       qp = &mp->phys_link;
+                       if (qp->prev != pqp)
+                               fatal("bad phys_link prev pointer");
+                       ms = &mapstate[mp-map_table];
+                       ms->flags |= flag;
+                       ms->physix = ix;
+                       pqp = (queue_entry_t) mp;
+                       qp = qp->next;
+               } while (IS_MAPPTR(qp));
+               if (qp != qhp)
+                       fatal("bad phys_link next pointer");
+       }
+}
+
+STATIC void
+merror(ms, str)
+       struct mapstate *ms;
+       char *str;
+{
+       terminal_ours();
+       fflush(stdout);
+       fprintf(stderr,
+               "vtophys: %s: %c%c%c, hashix %d, physix %d, mapping %x\n",
+               str,
+               (ms->flags & M_ISFREE) ? 'F' : '-',
+               (ms->flags & M_ISHASH) ? 'H' : '-',
+               (ms->flags & M_ISPHYS) ? 'P' : '-',
+               ms->hashix, ms->physix, &map_table[ms-mapstate]);
+       return_to_top_level();
+}
+
+STATIC int
+mach_read(str, from, top, size)
+       char *str;
+       CORE_ADDR from;
+       char *top;
+       int size;
+{
+       CORE_ADDR paddr;
+
+       if (from == ~0)
+               from = ksym_lookup(str);
+       paddr = vtophys(0, from);
+       if (paddr == ~0 || physrd(paddr, top, size) != 0)
+               fatal("cannot read %s", str);
+}
+
+STATIC char *
+mach_malloc(str, size)
+       char *str;
+       int size;
+{
+       char *ptr = (char *) malloc(size);
+
+       if (ptr == 0)
+               fatal("no memory for %s", str);
+       return(ptr);
+}
+#endif
+
+#ifdef KERNELDEBUG
+void
+_initialize_hp9k8_dep()
+{
+       add_com ("process-address", class_obscure, set_paddr_command,
+"The process identified by (ps-style) ADDR becomes the\n\
+\"current\" process context for kernel debugging.");
+       add_com_alias ("paddr", "process-address", class_obscure, 0);
+       add_com ("virtual-to-physical", class_obscure, vtop_command,
+"Translates the kernel virtual address ADDR into a physical address.");
+       add_com_alias ("vtop", "virtual-to-physical", class_obscure, 0);
+}
+#endif
+
+
+
+
diff --git a/gdb/hppabsd-xdep.c b/gdb/hppabsd-xdep.c
new file mode 100644 (file)
index 0000000..ca3d10e
--- /dev/null
@@ -0,0 +1,417 @@
+/* Machine-dependent code which would otherwise be in infptrace.c,
+   for GDB, the GNU debugger.  This code is for the HP PA-RISC cpu.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+/* Low level Unix child interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#ifndef USG
+#include <sys/ptrace.h>
+#endif
+
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#include "gdbcore.h"
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+/* This function simply calls ptrace with the given arguments.  
+   It exists so that all calls to ptrace are isolated in this 
+   machine-dependent file. */
+int
+call_ptrace (request, pid, addr, data)
+     int request, pid, *addr, data;
+{
+  return ptrace (request, pid, addr, data);
+}
+
+#ifdef DEBUG_PTRACE
+/* For the rest of the file, use an extra level of indirection */
+/* This lets us breakpoint usefully on call_ptrace. */
+#define ptrace call_ptrace
+#endif
+
+/* This is used when GDB is exiting.  It gives less chance of error.*/
+
+void
+kill_inferior_fast ()
+{
+  if (inferior_pid == 0)
+    return;
+  ptrace (PT_KILL, inferior_pid, 0, 0);
+  wait ((int *)0);
+}
+
+void
+kill_inferior ()
+{
+  kill_inferior_fast ();
+  target_mourn_inferior ();
+}
+
+/* Resume execution of the inferior process.
+   If STEP is nonzero, single-step it.
+   If SIGNAL is nonzero, give it that signal.  */
+
+void
+child_resume (step, signal)
+     int step;
+     int signal;
+{
+  errno = 0;
+
+  /* An address of (int *)1 tells ptrace to continue from where it was. 
+     (If GDB wanted it to start some other way, we have already written
+     a new PC value to the child.)  */
+
+  if (step)
+    ptrace (PT_STEP, inferior_pid, (int *)1, signal);
+  else
+    ptrace (PT_CONTINUE, inferior_pid, (int *)1, signal);
+
+  if (errno)
+    perror_with_name ("ptrace");
+}
+\f
+#ifdef ATTACH_DETACH
+/* Nonzero if we are debugging an attached process rather than
+   an inferior.  */
+extern int attach_flag;
+
+/* Start debugging the process whose number is PID.  */
+int
+attach (pid)
+     int pid;
+{
+  errno = 0;
+  ptrace (PT_ATTACH, pid, 0, 0);
+  if (errno)
+    perror_with_name ("ptrace");
+  attach_flag = 1;
+  return pid;
+}
+
+/* Stop debugging the process whose number is PID
+   and continue it with signal number SIGNAL.
+   SIGNAL = 0 means just continue it.  */
+
+void
+detach (signal)
+     int signal;
+{
+  errno = 0;
+  ptrace (PT_DETACH, inferior_pid, 1, signal);
+  if (errno)
+    perror_with_name ("ptrace");
+  attach_flag = 0;
+}
+#endif /* ATTACH_DETACH */
+\f
+#if !defined (FETCH_INFERIOR_REGISTERS)
+
+/* KERNEL_U_ADDR is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+#if defined (KERNEL_U_ADDR_BSD)
+/* Get kernel_u_addr using BSD-style nlist().  */
+CORE_ADDR kernel_u_addr;
+
+#include <a.out.gnu.h>         /* For struct nlist */
+
+void
+_initialize_kernel_u_addr ()
+{
+  struct nlist names[2];
+
+  names[0].n_un.n_name = "_u";
+  names[1].n_un.n_name = NULL;
+  if (nlist ("/vmunix", names) == 0)
+    kernel_u_addr = names[0].n_value;
+  else
+    fatal ("Unable to get kernel u area address.");
+}
+#endif /* KERNEL_U_ADDR_BSD.  */
+
+#if defined (KERNEL_U_ADDR_HPUX)
+/* Get kernel_u_addr using HPUX-style nlist().  */
+CORE_ADDR kernel_u_addr;
+
+struct hpnlist {      
+        char *          n_name;
+        long            n_value;  
+        unsigned char   n_type;   
+        unsigned char   n_length;  
+        short           n_almod;   
+        short           n_unused;
+};
+static struct hpnlist nl[] = {{ "_u", -1, }, { (char *) 0, }};
+
+/* read the value of the u area from the hp-ux kernel */
+void _initialize_kernel_u_addr ()
+{
+    struct user u;
+    nlist ("/hp-ux", &nl);
+    kernel_u_addr = nl[0].n_value;
+}
+#endif /* KERNEL_U_ADDR_HPUX.  */
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area.  */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+  ptrace (PT_READ_U, inferior_pid, \
+          (int *)(offsetof (struct user, u_ar0)), 0) - KERNEL_U_ADDR
+#endif
+
+/* Registers we shouldn't try to fetch.  */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) 0
+#endif
+
+/* Fetch one register.  */
+
+static void
+fetch_register (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[MAX_REGISTER_RAW_SIZE];
+  char mess[128];                              /* For messages */
+  register int i;
+
+  /* Offset of registers within the u area.  */
+  unsigned int offset;
+
+  if (CANNOT_FETCH_REGISTER (regno))
+    {
+      bzero (buf, REGISTER_RAW_SIZE (regno));  /* Supply zeroes */
+      supply_register (regno, buf);
+      return;
+    }
+
+  offset = U_REGS_OFFSET;
+
+  regaddr = register_addr (regno, offset);
+  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+    {
+      errno = 0;
+      *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid, (int *)regaddr, 0);
+      regaddr += sizeof (int);
+      if (errno != 0)
+       {
+         sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
+         perror_with_name (mess);
+       }
+    }
+  if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+    buf[3] &= ~0x3;
+  supply_register (regno, buf);
+}
+
+
+/* Fetch all registers, or just one, from the child process.  */
+
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+  if (regno == -1)
+    for (regno = 0; regno < NUM_REGS; regno++)
+      fetch_register (regno);
+  else
+    fetch_register (regno);
+}
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+void
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+  extern char registers[];
+  register int i;
+
+  unsigned int offset = U_REGS_OFFSET;
+
+  if (regno >= 0)
+    {
+      regaddr = register_addr (regno, offset);
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+       {
+         errno = 0;
+         ptrace (PT_WRITE_U, inferior_pid, (int *)regaddr,
+                 *(int *) &registers[REGISTER_BYTE (regno) + i]);
+         if (errno != 0)
+           {
+             sprintf (buf, "writing register number %d(%d)", regno, i);
+             perror_with_name (buf);
+           }
+         regaddr += sizeof(int);
+       }
+    }
+  else
+    {
+      for (regno = 0; regno < NUM_REGS; regno++)
+       {
+         if (CANNOT_STORE_REGISTER (regno))
+           continue;
+         regaddr = register_addr (regno, offset);
+         for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+           {
+             errno = 0;
+             ptrace (PT_WRITE_U, inferior_pid, (int *)regaddr,
+                     *(int *) &registers[REGISTER_BYTE (regno) + i]);
+             if (errno != 0)
+               {
+                 sprintf (buf, "writing register number %d(%d)", regno, i);
+                 perror_with_name (buf);
+               }
+             regaddr += sizeof(int);
+           }
+       }
+    }
+  return;
+}
+#endif /* !defined (FETCH_INFERIOR_REGISTERS).  */
+\f
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+   in the NEW_SUN_PTRACE case.
+   It ought to be straightforward.  But it appears that writing did
+   not write the data that I specified.  I cannot understand where
+   it got the data that it actually did write.  */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.   Copy to inferior if
+   WRITE is nonzero.
+  
+   Returns the length copied, which is either the LEN argument or zero.
+   This xfer function does not do partial moves, since child_ops
+   doesn't allow memory operations to cross below us in the target stack
+   anyway.  */
+
+int
+child_xfer_memory (memaddr, myaddr, len, write, target)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+     struct target_ops *target;                /* ignored */
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+
+  if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory data.  */
+
+      if (addr != memaddr || len < (int)sizeof (int)) {
+       /* Need part of initial word -- fetch it.  */
+        buffer[0] = ptrace (PT_READ_I, inferior_pid, (int *)addr, 0);
+      }
+
+      if (count > 1)           /* FIXME, avoid if even boundary */
+       {
+         buffer[count - 1]
+           = ptrace (PT_READ_I, inferior_pid,
+                     (int *)(addr + (count - 1) * sizeof (int)), 0);
+       }
+
+      /* Copy data to be written over corresponding part of buffer */
+
+      bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+      /* Write the entire buffer.  */
+
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         ptrace (PT_WRITE_D, inferior_pid, (int *)addr, buffer[i]);
+         if (errno)
+           {
+             /* Using the appropriate one (I or D) is necessary for
+                Gould NP1, at least.  */
+             errno = 0;
+             ptrace (PT_WRITE_I, inferior_pid, (int *)addr, buffer[i]);
+           }
+         if (errno)
+           return 0;
+       }
+    }
+  else
+    {
+      /* Read all the longwords */
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         buffer[i] = ptrace (PT_READ_I, inferior_pid, (int *)addr, 0);
+         if (errno)
+           return 0;
+         QUIT;
+       }
+
+      /* Copy appropriate bytes out of the buffer.  */
+      bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+    }
+  return len;
+}
+
+
+
+
diff --git a/gdb/hppahpux-tdep.c b/gdb/hppahpux-tdep.c
new file mode 100644 (file)
index 0000000..0567945
--- /dev/null
@@ -0,0 +1,1432 @@
+/* Machine-dependent code which would otherwise be in inflow.c and core.c,
+   for GDB, the GNU debugger.  This code is for the HP PA-RISC cpu.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "value.h"
+
+/* For argument passing to the inferior */
+#include "symtab.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h>  Can we live without this?  */
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+#include <a.out.h>
+#endif
+#ifndef N_SET_MAGIC
+#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
+#endif
+
+/*#include <sys/user.h>                After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+#include <machine/psl.h>
+
+#ifdef KERNELDEBUG
+#include <sys/vmmac.h>
+#include <machine/machparam.h>
+#include <machine/vmparam.h>
+#include <machine/pde.h>
+#include <machine/cpu.h>
+#include <machine/iomod.h>
+#include <machine/pcb.h>
+#include <machine/rpb.h>
+#include <ctype.h>
+
+extern int kernel_debugging;
+extern CORE_ADDR startup_file_start;
+extern CORE_ADDR startup_file_end;
+
+#define        KERNOFF         ((unsigned)KERNBASE)
+#define        INKERNEL(x)     ((x) >= KERNOFF && (x) < KERNOFF + ctob(slr))
+
+static int ok_to_cache();
+static void set_kernel_boundaries();
+
+int devmem = 0;
+int vtophys_ready = 0;
+int kerneltype;
+#define        OS_BSD  1
+#define        OS_MACH 2
+#endif
+
+#include "gdbcore.h"
+#include "gdbcmd.h"
+
+extern int errno;
+\f
+
+
+
+
+
+/* Last modification time of executable file.
+   Also used in source.c to compare against mtime of a source file.  */
+
+extern int exec_mtime;
+
+/* Virtual addresses of bounds of the two areas of memory in the core file.  */
+
+/* extern CORE_ADDR data_start; */
+extern CORE_ADDR data_end;
+extern CORE_ADDR stack_start;
+extern CORE_ADDR stack_end;
+
+/* Virtual addresses of bounds of two areas of memory in the exec file.
+   Note that the data area in the exec file is used only when there is no core file.  */
+
+extern CORE_ADDR text_start;
+extern CORE_ADDR text_end;
+
+extern CORE_ADDR exec_data_start;
+extern CORE_ADDR exec_data_end;
+
+/* Address in executable file of start of text area data.  */
+
+extern int text_offset;
+
+/* Address in executable file of start of data area data.  */
+
+extern int exec_data_offset;
+
+/* Address in core file of start of data area data.  */
+
+extern int data_offset;
+
+/* Address in core file of start of stack area data.  */
+
+extern int stack_offset;
+
+struct header file_hdr;
+struct som_exec_auxhdr exec_hdr;
+\f
+#ifdef KERNELDEBUG
+/*
+ * Kernel debugging routines.
+ */
+
+static struct pcb pcb;
+static struct pde *pdir;
+static struct hte *htbl;
+static u_int npdir, nhtbl;
+
+static CORE_ADDR
+ksym_lookup(name)
+       char *name;
+{
+       struct symbol *sym;
+       int i;
+
+       if ((i = lookup_misc_func(name)) < 0)
+               error("kernel symbol `%s' not found.", name);
+
+       return (misc_function_vector[i].address);
+}
+
+/*
+ * (re-)set the variables that tell "inside_entry_file" where to end
+ * a stack backtrace.
+ */
+void
+set_kernel_boundaries()
+{
+       switch (kerneltype) {
+       case OS_MACH:
+               startup_file_start = ksym_lookup("$syscall");
+               startup_file_end = ksym_lookup("trap");
+               break;
+       case OS_BSD:
+               startup_file_start = ksym_lookup("syscallinit");
+               startup_file_end = ksym_lookup("$syscallexit");
+               break;
+       }
+}
+
+/*
+ * return true if 'len' bytes starting at 'addr' can be read out as
+ * longwords and/or locally cached (this is mostly for memory mapped
+ * i/o register access when debugging remote kernels).
+ */
+static int
+ok_to_cache(addr, len)
+{
+       static CORE_ADDR ioptr;
+
+       if (! ioptr)
+               ioptr = ksym_lookup("ioptr");
+
+       if (addr >= ioptr && addr < SPA_HIGH)
+               return (0);
+
+       return (1);
+}
+
+static
+physrd(addr, dat, len)
+       u_int addr;
+       char *dat;
+{
+       if (lseek(corechan, addr, L_SET) == -1)
+               return (-1);
+       if (read(corechan, dat, len) != len)
+               return (-1);
+
+       return (0);
+}
+
+/*
+ * When looking at kernel data space through /dev/mem or with a core file, do
+ * virtual memory mapping.
+ */
+static CORE_ADDR
+vtophys(space, addr)
+       unsigned space;
+       CORE_ADDR addr;
+{
+       struct pde *pptr;
+       u_int hindx, vpageno, ppageno;
+       CORE_ADDR phys = ~0;
+
+       if (!vtophys_ready) {
+               phys = addr;            /* XXX for kvread */
+       } else if (kerneltype == OS_BSD) {
+               /* make offset into a virtual page no */
+               vpageno = btop(addr);
+               /*
+                *  Determine index into hash table, initialize pptr to this
+                *  entry (since first word of pte & hte are same), and set
+                *  physical page number for first entry in chain.
+                */
+               hindx = pdirhash(space, addr) & (nhtbl-1);
+               pptr = (struct pde *) &htbl[hindx];
+               ppageno = pptr->pde_next;
+               while (1) {
+                       if (pptr->pde_end)
+                               break;
+                       pptr = &pdir[ppageno];
+                       /*
+                        *  If space id & virtual page number match, return
+                        *  "next PDIR entry of previous PDIR entry" as the
+                        *  physical page or'd with offset into page.
+                        */
+                       if (pptr->pde_space == space &&
+                           pptr->pde_page == vpageno) {
+                               phys = (CORE_ADDR) ((u_int)ptob(ppageno) |
+                                                   (addr & PGOFSET));
+                               break;
+                       }
+                       ppageno = pptr->pde_next;
+               }
+       }
+#ifdef MACHKERNELDEBUG
+       else if (kerneltype == OS_MACH) {
+               (void) mach_vtophys(space, addr, &phys);
+       }
+#endif
+#if 0
+       printf("vtophys(%x.%x) -> %x\n", space, addr, phys);
+#endif
+       return (phys);
+}
+
+static
+kvread(addr)
+       CORE_ADDR addr;
+{
+       CORE_ADDR paddr;
+
+       paddr = vtophys(0, addr);
+       if (paddr != ~0)
+               if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0)
+                       return (addr);
+
+       return (~0);
+}
+
+static void
+read_pcb(addr)
+     u_int addr;
+{
+       int i, off;
+       extern char registers[];
+       static int reg2pcb[] = {
+               /* RPB */
+               -1,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
+               18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+               45, 52, 51, 75, 74, 49, 53, 54, 55, 56, -1, 70, 66, 67, 68, 69,
+               71, 72, 73, 34, 42, 43, 44, 46, 47, 58, 59, 60, -1, -1, -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+               -1, -1, -1, -1,
+               /* BSD */
+               -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+               43, 64, 67, 68, 67, 47, 51, 52, 53, 54, -1, 35, 31, 32, 33, 34,
+               36, 37, 38, 39, 40, 41, 42, 44, 45, 56, 57, 58,102,103,104, -1,
+               70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 82, 84, 86, 88, 90, 92,
+               94, 96, 98, 100,
+               /* Mach */
+               -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+               14, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, 18, -1,
+               25, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 20, -1, -1, -1, 19,
+               21, 22, 23, 24, 26, 27, -1, 28, 29, -1, -1, -1, -1, -1, -1, -1,
+               34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, -1, -1, -1, -1, -1,
+               42, 44, 46, 48
+       };
+       static struct rpb *rpbaddr = (struct rpb *) 0;
+       static u_int rpbpcbaddr = 0;
+
+       if (!remote_debugging) {
+               /*
+                * If we are debugging a post-mortem and this is the first
+                * call of read_pcb, read the RPB.  Also assoicate the
+                * thread/proc running at the time with the RPB.
+                */
+               if (!devmem && rpbpcbaddr == 0) {
+                       CORE_ADDR raddr = ksym_lookup("rpb");
+                       int usepcb = 1;
+
+                       if (raddr != ~0) {
+                               rpbaddr = (struct rpb *) malloc(sizeof *rpbaddr);
+                               if (!physrd(raddr, (char *)rpbaddr, sizeof *rpbaddr)) {
+                                       rpbpcbaddr = addr;
+                                       usepcb = 0;
+                               }
+                       }
+                       if (usepcb) {
+                               error("cannot read rpb, using pcb for registers\n");
+                               if (rpbaddr)
+                                       free((char *)rpbaddr);
+                               rpbpcbaddr = ~0;
+                       }
+               }
+               if (physrd (addr, (char *)&pcb, sizeof pcb))
+                       error ("cannot read pcb at %x.\n", addr);
+       } else {
+               if (remote_read_inferior_memory(addr, (char *)&pcb, sizeof pcb))
+                       error ("cannot read pcb at %x.\n", addr);
+       }
+
+       if (kerneltype == OS_BSD) {
+               printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
+                      pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
+               off = NUM_REGS;
+       } else {
+               printf("pcb %lx psw %lx ksp %lx\n",
+                      addr, ((int *)&pcb)[31], ((int *)&pcb)[32]);
+               off = NUM_REGS * 2;
+       }
+       /*
+        * get the register values out of the sys pcb and
+        * store them where `read_register' will find them.
+        */
+       bzero(registers, REGISTER_BYTES);
+       for (i = 0; i < NUM_REGS; ++i)
+               if (reg2pcb[i+off] != -1)
+                       supply_register(i, &((int *)&pcb)[reg2pcb[i+off]]);
+       /*
+        * If the RPB is valid for this thread/proc use the register values
+        * contained there.
+        */
+       if (addr == rpbpcbaddr) {
+               off = 0;
+               for (i = 0; i < NUM_REGS; ++i)
+                       if (reg2pcb[i+off] != -1)
+                               supply_register(i, &((int *)rpbaddr)[reg2pcb[i+off]]);
+       }
+}
+
+void
+setup_kernel_debugging()
+{
+       struct stat stb;
+       CORE_ADDR addr;
+
+       fstat(corechan, &stb);
+       devmem = 0;
+       if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
+               devmem = 1;
+
+       /* XXX */
+       if (lookup_misc_func("Sysmap") < 0)
+               kerneltype = OS_MACH;
+       else
+               kerneltype = OS_BSD;
+
+       if (kerneltype == OS_BSD) {
+               int len, err = 0;
+
+               /*
+                * Hash table and PDIR are equivalently mapped
+                */
+               nhtbl = kvread(ksym_lookup("nhtbl"));
+               if (nhtbl != ~0) {
+                       len = nhtbl * sizeof(*htbl);
+                       htbl = (struct hte *) malloc(len);
+                       if (htbl) {
+                               addr = kvread(ksym_lookup("htbl"));
+                               if (physrd(addr, (char *)htbl, len))
+                                       err++;
+                       } else
+                               err++;
+               } else
+                       err++;
+               npdir = kvread(ksym_lookup("npdir"));
+               if (npdir != ~0) {
+                       len = npdir * sizeof(*pdir);
+                       pdir = (struct pde *) malloc(len);
+                       if (pdir) {
+                               addr = kvread(ksym_lookup("pdir"));
+                               if (physrd(addr, (char *)pdir, len))
+                                       err++;
+                       } else
+                               err++;
+               } else
+                       err++;
+               if (err) {
+                       error("cannot read PDIR/HTBL");
+                       return;
+               }
+               vtophys_ready = 1;
+
+               /*
+                * pcb where "panic" saved registers in first thing in
+                * current u-area.  The current u-area is pointed to by
+                * "uptr".
+                */
+               addr = kvread(ksym_lookup("uptr"));
+               if (addr == ~0) {
+                       error("cannot read current u-area address");
+                       return;
+               }
+               read_pcb(vtophys(0, addr));     /* XXX space */
+               if (!devmem) {
+                       /* find stack frame */
+                       CORE_ADDR panicstr;
+                       char buf[256];
+                       register char *cp;
+                       
+                       panicstr = kvread(ksym_lookup("panicstr"));
+                       if (panicstr == ~0)
+                               return;
+                       (void) kernel_core_file_hook(panicstr, buf, sizeof(buf));
+                       for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
+                               if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+                                       *cp = '?';
+                       if (*cp)
+                               *cp = '\0';
+                       printf("panic: %s\n", buf);
+               }
+       }
+#ifdef MACHKERNELDEBUG
+       else {
+               int *thread;
+
+               /*
+                * Set up address translation
+                */
+               if (mach_vtophys_init() == 0) {
+                       error("cannot initialize vtophys for Mach");
+                       return;
+               }
+               vtophys_ready = 1;
+
+               /*
+                * Locate active thread and read PCB
+                * XXX MAJOR HACK
+                *      - assumes uni-processor
+                *      - assumes position of pcb to avoid mach includes
+                */
+               thread = (int *)kvread(ksym_lookup("active_threads"));
+               addr = kvread(&thread[9]);              /* XXX: pcb addr */
+               read_pcb(vtophys(0, addr));
+       }
+#endif
+}
+
+vtop_command(arg)
+       char *arg;
+{
+       u_int sp, off, pa;
+
+       if (!arg)
+               error_no_arg("kernel virtual address");
+       if (!kernel_debugging)
+               error("not debugging kernel");
+
+       sp = 0;         /* XXX */
+       off = (u_int) parse_and_eval_address(arg);
+       pa = vtophys(sp, off);
+       printf("%lx.%lx -> ", sp, off);
+       if (pa == ~0)
+               printf("<invalid>\n");
+       else
+               printf("%lx\n", pa);
+}
+
+set_paddr_command(arg)
+       char *arg;
+{
+       u_int addr;
+
+       if (!arg) {
+               if (kerneltype == OS_BSD)
+                       error_no_arg("ps-style address for new process");
+               else
+                       error_no_arg("thread structure virtual address");
+       }
+       if (!kernel_debugging)
+               error("not debugging kernel");
+
+       addr = (u_int) parse_and_eval_address(arg);
+       if (kerneltype == OS_BSD)
+               addr = ctob(addr);
+       else {
+               addr = kvread(&(((int *)addr)[9]));     /* XXX: pcb addr */
+               addr = vtophys(0, addr);                /* XXX space */
+       }
+       read_pcb(addr);
+
+       flush_cached_frames();
+       set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
+       select_frame(get_current_frame(), 0);
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local 
+ * buffer 'buf'.  Return 0 if read ok, 1 otherwise.  On read
+ * errors, portion of buffer not read is zeroed.
+ */
+kernel_core_file_hook(addr, buf, len)
+       CORE_ADDR addr;
+       char *buf;
+       int len;
+{
+       int i;
+       CORE_ADDR paddr;
+
+       while (len > 0) {
+               paddr = vtophys(0, addr);       /* XXX space */
+               if (paddr == ~0) {
+                       bzero(buf, len);
+                       return (1);
+               }
+               /* we can't read across a page boundary */
+               i = min(len, NBPG - (addr & PGOFSET));
+               if (physrd(paddr, buf, i)) {
+                       bzero(buf, len);
+                       return (1);
+               }
+               buf += i;
+               addr += i;
+               len -= i;
+       }
+       return (0);
+}
+#endif
+
+
+\f
+
+
+
+/* Routines to extract various sized constants out of hppa 
+   instructions. */
+
+/* This assumes that no garbage lies outside of the lower bits of 
+   value. */
+
+int
+sign_extend (val, bits)
+     unsigned val, bits;
+{
+  return (int)(val >> bits - 1 ? (-1 << bits) | val : val);
+}
+
+/* For many immediate values the sign bit is the low bit! */
+
+int
+low_sign_extend (val, bits)
+     unsigned val, bits;
+{
+  return (int)((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
+}
+/* extract the immediate field from a ld{bhw}s instruction */
+
+
+
+unsigned
+get_field (val, from, to)
+     unsigned val, from, to;
+{
+  val = val >> 31 - to;
+  return val & ((1 << 32 - from) - 1);
+}
+
+unsigned
+set_field (val, from, to, new_val)
+     unsigned *val, from, to;
+{
+  unsigned mask = ~((1 << (to - from + 1)) << (31 - from));
+  return *val = *val & mask | (new_val << (31 - from));
+}
+
+/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
+
+extract_3 (word)
+     unsigned word;
+{
+  return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
+}
+       
+extract_5_load (word)
+     unsigned word;
+{
+  return low_sign_extend (word >> 16 & MASK_5, 5);
+}
+
+/* extract the immediate field from a st{bhw}s instruction */
+
+int
+extract_5_store (word)
+     unsigned word;
+{
+  return low_sign_extend (word & MASK_5, 5);
+}
+
+/* extract an 11 bit immediate field */
+
+int
+extract_11 (word)
+     unsigned word;
+{
+  return low_sign_extend (word & MASK_11, 11);
+}
+
+/* extract a 14 bit immediate field */
+
+int
+extract_14 (word)
+     unsigned word;
+{
+  return low_sign_extend (word & MASK_14, 14);
+}
+
+/* deposit a 14 bit constant in a word */
+
+unsigned
+deposit_14 (opnd, word)
+     int opnd;
+     unsigned word;
+{
+  unsigned sign = (opnd < 0 ? 1 : 0);
+
+  return word | ((unsigned)opnd << 1 & MASK_14)  | sign;
+}
+
+/* extract a 21 bit constant */
+
+int
+extract_21 (word)
+     unsigned word;
+{
+  int val;
+
+  word &= MASK_21;
+  word <<= 11;
+  val = GET_FIELD (word, 20, 20);
+  val <<= 11;
+  val |= GET_FIELD (word, 9, 19);
+  val <<= 2;
+  val |= GET_FIELD (word, 5, 6);
+  val <<= 5;
+  val |= GET_FIELD (word, 0, 4);
+  val <<= 2;
+  val |= GET_FIELD (word, 7, 8);
+  return sign_extend (val, 21) << 11;
+}
+
+/* deposit a 21 bit constant in a word. Although 21 bit constants are
+   usually the top 21 bits of a 32 bit constant, we assume that only
+   the low 21 bits of opnd are relevant */
+
+unsigned
+deposit_21 (opnd, word)
+     unsigned opnd, word;
+{
+  unsigned val = 0;
+
+  val |= GET_FIELD (opnd, 11 + 14, 11 + 18);
+  val <<= 2;
+  val |= GET_FIELD (opnd, 11 + 12, 11 + 13);
+  val <<= 2;
+  val |= GET_FIELD (opnd, 11 + 19, 11 + 20);
+  val <<= 11;
+  val |= GET_FIELD (opnd, 11 + 1, 11 + 11);
+  val <<= 1;
+  val |= GET_FIELD (opnd, 11 + 0, 11 + 0);
+  return word | val;
+}
+
+/* extract a 12 bit constant from branch instructions */
+
+int
+extract_12 (word)
+     unsigned word;
+{
+  return sign_extend (GET_FIELD (word, 19, 28) |
+                     GET_FIELD (word, 29, 29) << 10 |
+                     (word & 0x1) << 11, 12) << 2;
+}
+
+/* extract a 17 bit constant from branch instructions, returning the
+   19 bit signed value. */
+
+int
+extract_17 (word)
+     unsigned word;
+{
+  return sign_extend (GET_FIELD (word, 19, 28) |
+                     GET_FIELD (word, 29, 29) << 10 |
+                     GET_FIELD (word, 11, 15) << 11 |
+                     (word & 0x1) << 16, 17) << 2;
+}
+
+
+CORE_ADDR
+frame_saved_pc (frame)
+     FRAME frame;
+{
+  if (get_current_frame () == frame)
+    {
+      struct frame_saved_regs saved_regs;
+      CORE_ADDR pc = get_frame_pc (frame);
+
+      get_frame_saved_regs (frame, &saved_regs);
+      if (pc >= millicode_start && pc < millicode_end)
+       return read_register (31);
+      else if (saved_regs.regs[RP_REGNUM])
+       return read_memory_integer (saved_regs.regs[RP_REGNUM], 4);
+      else
+       return read_register (RP_REGNUM);
+    }
+  return read_memory_integer (frame->frame - 20, 4) & ~0x3;
+}
+
+
+/* To see if a frame chain is valid, see if the caller looks like it
+   was compiled with gcc. */
+
+int frame_chain_valid (chain, thisframe)
+     FRAME_ADDR chain;
+     FRAME thisframe;
+{
+  if (chain && (chain > 0x60000000 
+               /* || remote_debugging   -this is no longer used */
+#ifdef KERNELDEBUG
+               || kernel_debugging
+#endif
+               ))
+    {
+      CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe));
+
+      if (!inside_entry_file (pc))
+       return 0;
+      /* look for stw rp, -20(0,sp); copy 4,1; copy sp, 4 */
+      if (read_memory_integer (pc, 4) == 0x6BC23FD9)                   
+       pc = pc + 4;                                                    
+      
+      if (read_memory_integer (pc, 4) == 0x8040241 &&
+         read_memory_integer (pc + 4, 4) == 0x81E0244)                 
+       return 1;
+      else
+       return 0;
+    }
+  else
+    return 0;
+}
+
+/* Some helper functions. gcc_p returns 1 if the function beginning at 
+   pc appears to have been compiled with gcc. hpux_cc_p returns 1 if
+   fn was compiled with hpux cc. gcc functions look like :
+
+   stw     rp,-0x14(sp) ; optional
+   or      r4,r0,r1
+   or      sp,r0,r4
+   stwm    r1,framesize(sp)
+
+   hpux cc functions look like:
+
+   stw     rp,-0x14(sp) ; optional.
+   stwm    r3,framesiz(sp)
+   */
+
+gcc_p (pc)
+     CORE_ADDR pc;
+{
+  if (read_memory_integer (pc, 4) == 0x6BC23FD9)                       
+    pc = pc + 4;                                                       
+      
+  if (read_memory_integer (pc, 4) == 0x8040241 &&
+      read_memory_integer (pc + 4, 4) == 0x81E0244)                    
+    return 1;
+  return 0;
+}
+
+  
+find_dummy_frame_regs (frame, frame_saved_regs)
+     struct frame_info *frame;
+     struct frame_saved_regs *frame_saved_regs;
+{
+  CORE_ADDR fp = frame->frame;
+  int i;
+  
+  frame_saved_regs->regs[RP_REGNUM] = fp - 20 & ~0x3;
+  frame_saved_regs->regs[FP_REGNUM] = fp;
+  frame_saved_regs->regs[1] = fp + 8;
+  frame_saved_regs->regs[3] = fp + 12;
+  for (fp += 16, i = 3; i < 30; fp += 4, i++)
+    frame_saved_regs->regs[i] = fp;
+  frame_saved_regs->regs[31] = fp;
+  fp += 4;
+  for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8)
+    frame_saved_regs->regs[i] = fp;
+  /* depend on last increment of fp */
+  frame_saved_regs->regs[IPSW_REGNUM] = fp - 4;
+  frame_saved_regs->regs[SAR_REGNUM] = fp;
+  fp += 4;
+  frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp;
+  frame_saved_regs->regs[PCSQ_TAIL_REGNUM] = fp;
+}
+
+CORE_ADDR
+hp_push_arguments (nargs, args, sp, struct_return, struct_addr)
+     int nargs;
+     value *args;
+     CORE_ADDR sp;
+     int struct_return;
+     CORE_ADDR struct_addr;
+{
+  /* array of arguments' offsets */
+  int *offset = (int *)alloca(nargs);
+  int cum = 0;
+  int i, alignment;
+  
+  for (i = 0; i < nargs; i++)
+    {
+      cum += TYPE_LENGTH (VALUE_TYPE (args[i]));
+      /* value must go at proper alignment. Assume alignment is a
+        power of two.*/
+      alignment = hp_alignof (VALUE_TYPE (args[i]));
+      if (cum % alignment)
+       cum = (cum + alignment) & -alignment;
+      offset[i] = -cum;
+    }
+  for (i == 0; i < nargs; i++)
+    {
+      write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), sizeof(int));
+    }
+  sp += min ((cum + 7) & -8, 48);
+  if (struct_return)
+    write_register (28, struct_addr);
+  return sp + 48;
+}
+
+/* return the alignment of a type in bytes. Structures have the maximum
+   alignment required by their fields. */
+
+int
+hp_alignof (arg)
+     struct type *arg;
+{
+  int max_align, align, i;
+  switch (TYPE_CODE (arg))
+    {
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_FLT:
+      return TYPE_LENGTH (arg);
+    case TYPE_CODE_ARRAY:
+      return hp_alignof (TYPE_FIELD_TYPE (arg, 0));
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      max_align = 2;
+      for (i = 0; i < TYPE_NFIELDS (arg); i++)
+       {
+         /* Bit fields have no real alignment. */
+         if (!TYPE_FIELD_BITPOS (arg, i))
+           {
+             align = hp_alignof (TYPE_FIELD_TYPE (arg, i));
+             max_align = max (max_align, align);
+           }
+       }
+      return max_align;
+    default:
+      return 4;
+    }
+}
+
+/* Print the register regnum, or all registers if regnum is -1 */
+
+pa_do_registers_info (regnum, fpregs)
+     int regnum;
+     int fpregs;
+{
+  char raw_regs [REGISTER_BYTES];
+  int i;
+  
+  for (i = 0; i < NUM_REGS; i++)
+    read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+  if (regnum = -1)
+    pa_print_registers (raw_regs, regnum);
+  else if (regnum < FP0_REGNUM)
+    {
+      printf ("%s %x\n", reg_names[regnum], *(long *)(raw_regs +
+                                                     REGISTER_BYTE (regnum)));
+    }
+  else
+    pa_print_fp_reg (regnum);
+}
+
+pa_print_registers (raw_regs, regnum)
+     char *raw_regs;
+     int regnum;
+{
+  int i;
+
+  for (i = 0; i < 18; i++)
+    printf ("%8.8s: %8x  %8.8s: %8x  %8.8s: %8x  %8.8s: %8x\n",
+                    reg_names[i],
+                    *(int *)(raw_regs + REGISTER_BYTE (i)),
+                    reg_names[i + 18],
+                    *(int *)(raw_regs + REGISTER_BYTE (i + 18)),
+                    reg_names[i + 36],
+                    *(int *)(raw_regs + REGISTER_BYTE (i + 36)),
+                    reg_names[i + 54],
+                    *(int *)(raw_regs + REGISTER_BYTE (i + 54)));
+  for (i = 72; i < NUM_REGS; i++)
+    pa_print_fp_reg (i);
+}
+
+pa_print_fp_reg (i)
+     int i;
+{
+  unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
+  unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+  REGISTER_TYPE val;
+
+  /* Get the data in raw format, then convert also to virtual format.  */
+  read_relative_register_raw_bytes (i, raw_buffer);
+  REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
+
+  fputs_filtered (reg_names[i], stdout);
+  print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
+
+  val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, stdout, 0,
+            1, 0, Val_pretty_default);
+  printf_filtered ("\n");
+
+}
+
+/*
+ * Virtual to physical translation routines for Utah's Mach 3.0
+ */
+#ifdef MACHKERNELDEBUG
+
+#define STATIC
+
+#if 0  /* too many includes to resolve, too much crap */
+#include <kern/queue.h>
+#include <vm/pmap.h>   
+#include <mach/vm_prot.h>
+#else
+/* queue.h */
+struct queue_entry {
+       struct queue_entry      *next;          /* next element */
+       struct queue_entry      *prev;          /* previous element */
+};
+
+typedef struct queue_entry     *queue_t;
+typedef        struct queue_entry      queue_head_t;
+typedef        struct queue_entry      queue_chain_t;
+typedef        struct queue_entry      *queue_entry_t;
+
+/* pmap.h */
+#define HP800_HASHSIZE         1024
+#define HP800_HASHSIZE_LOG2    10
+
+#define pmap_hash(space, offset) \
+       (((unsigned) (space) << 5 ^ \
+         ((unsigned) (offset) >> 19 | (unsigned) (space) << 13) ^ \
+         (unsigned) (offset) >> 11) & (HP800_HASHSIZE-1))
+
+struct mapping {
+       queue_head_t    hash_link;      /* hash table links */
+       queue_head_t    phys_link;      /* for mappings of a given PA */
+       space_t         space;          /* virtual space */
+       unsigned        offset;         /* virtual page number */
+       unsigned        tlbpage;        /* physical page (for TLB load) */
+       unsigned        tlbprot;        /* prot/access rights (for TLB load) */
+       struct pmap     *pmap;          /* pmap mapping belongs to */
+};
+
+struct phys_entry {
+       queue_head_t    phys_link;      /* head of mappings of a given PA */
+       struct mapping  *writer;        /* mapping with R/W access */
+       unsigned        tlbprot;        /* TLB format protection */
+};
+
+#endif
+
+#define atop(a)                ((unsigned)(a) >> 11)
+#define ptoa(p)                ((unsigned)(p) << 11)
+#define trunc_page(a)  ((unsigned)(a) & ~2047)
+
+STATIC long equiv_end;
+STATIC queue_head_t *Ovtop_table, *vtop_table, *Ofree_mapping, free_mapping;
+STATIC struct phys_entry *Ophys_table, *phys_table;
+STATIC long vm_last_phys, vm_first_phys;
+STATIC struct mapping *firstmap, *lastmap, *Omap_table, *map_table;
+STATIC unsigned Omlow, Omhigh, Omhead, Ovlow, Ovhigh, Oplow, Ophigh;
+STATIC unsigned mlow, mhigh, mhead, vlow, vhigh, plow, phigh;
+STATIC int vtopsize, physsize, mapsize;
+STATIC int kmemfd;
+
+#define IS_OVTOPPTR(p) ((unsigned)(p) >= Ovlow && (unsigned)(p) < Ovhigh)
+#define IS_OMAPPTR(p)  ((unsigned)(p) >= Omlow && (unsigned)(p) < Omhigh)
+#define IS_OPHYSPTR(p) ((unsigned)(p) >= Oplow && (unsigned)(p) < Ophigh)
+#define IS_VTOPPTR(p)  ((unsigned)(p) >= vlow && (unsigned)(p) < vhigh)
+#define IS_MAPPTR(p)   ((unsigned)(p) >= mlow && (unsigned)(p) < mhigh)
+#define IS_PHYSPTR(p)  ((unsigned)(p) >= plow && (unsigned)(p) < phigh)
+
+struct mapstate {
+       char    unused;
+       char    flags;
+       short   hashix;
+       short   physix;
+} *mapstate;
+
+/* flags */
+#define M_ISFREE       1
+#define M_ISHASH       2
+#define M_ISPHYS       4
+
+mach_vtophys_init()
+{
+       int errors = 0;
+
+       if (!readdata())
+               errors++;
+       if (!verifydata())
+               errors++;
+       if (!errors)
+               return(1);
+       fflush(stdout);
+       fprintf(stderr,
+               "translate: may not be able to translate all addresses\n");
+       return(0);
+}
+
+mach_vtophys(space, off, pa)
+       unsigned space, off, *pa;
+{
+       register int i;
+       register queue_t qp;
+       register struct mapping *mp;
+       int poff;
+
+       /*
+        * Kernel IO or equivilently mapped, one to one.
+        */
+       if (space == 0 && (long)off < equiv_end) {
+               *pa = off;
+               return(1);
+       }
+       /*
+        * Else look it up in specified space
+        */
+       poff = off - trunc_page(off);
+       off = trunc_page(off);
+       qp = &vtop_table[pmap_hash(space, off)];
+       for (mp = (struct mapping *)qp->next;
+            qp != (queue_entry_t)mp;
+            mp = (struct mapping *)mp->hash_link.next) {
+               if (mp->space == space && mp->offset == off) {
+                       *pa = (mp->tlbpage << 7) | poff;
+                       return(1);
+               }
+       }
+       return(0);
+}
+
+STATIC
+readdata()
+{
+       char *tmp, *mach_malloc();
+       long size;
+
+       /* easy scalars */
+       mach_read("equiv_end", ~0, (char *)&equiv_end, sizeof equiv_end);
+       mach_read("vm_first_phys", ~0,
+                 (char *)&vm_first_phys, sizeof vm_first_phys);
+       mach_read("vm_last_phys", ~0,
+                 (char *)&vm_last_phys, sizeof vm_last_phys);
+       mach_read("firstmap", ~0, (char *)&firstmap, sizeof firstmap);
+       mach_read("lastmap", ~0, (char *)&lastmap, sizeof lastmap);
+
+       /* virtual to physical hash table */
+       vtopsize = HP800_HASHSIZE;
+       size = vtopsize * sizeof(queue_head_t);
+       tmp = mach_malloc("vtop table", size);
+       mach_read("vtop_table", ~0, (char *)&Ovtop_table, sizeof Ovtop_table);
+       mach_read("vtop table", (CORE_ADDR)Ovtop_table, tmp, size);
+       vtop_table = (queue_head_t *) tmp;
+
+       /* inverted page table */
+       physsize = atop(vm_last_phys - vm_first_phys);
+       size = physsize * sizeof(struct phys_entry);
+       tmp = mach_malloc("phys table", size);
+       mach_read("phys_table", ~0, (char *)&Ophys_table, sizeof Ophys_table);
+       mach_read("phys table", (CORE_ADDR)Ophys_table, tmp, size);
+       phys_table = (struct phys_entry *) tmp;
+
+       /* mapping structures */
+       Ofree_mapping = (queue_head_t *) ksym_lookup("free_mapping");
+       mach_read("free mapping", (CORE_ADDR)Ofree_mapping,
+                 (char *) &free_mapping, sizeof free_mapping);
+       Omap_table = firstmap;
+       mapsize = lastmap - firstmap;
+       size = mapsize * sizeof(struct mapping);
+       tmp = mach_malloc("mapping table", size);
+       mach_read("mapping table", (CORE_ADDR)Omap_table, tmp, size);
+       map_table = (struct mapping *) tmp;
+
+       /* set limits */
+       Ovlow = (unsigned) Ovtop_table;
+       Ovhigh = (unsigned) &Ovtop_table[vtopsize];
+       Oplow = (unsigned) Ophys_table;
+       Ophigh = (unsigned) &Ophys_table[physsize];
+       Omhead = (unsigned) Ofree_mapping;
+       Omlow = (unsigned) firstmap;
+       Omhigh = (unsigned) lastmap;
+       mlow = (unsigned) map_table;
+       mhigh = (unsigned) &map_table[mapsize];
+       mhead = (unsigned) &free_mapping;
+       vlow = (unsigned) vtop_table;
+       vhigh = (unsigned) &vtop_table[vtopsize];
+       plow = (unsigned) phys_table;
+       phigh = (unsigned) &phys_table[physsize];
+
+#if 0
+       fprintf(stderr, "Ovtop [%#x-%#x) Ophys [%#x-%#x) Omap %#x [%#x-%#x)\n",
+               Ovlow, Ovhigh, Oplow, Ophigh, Omhead, Omlow, Omhigh);
+       fprintf(stderr, "vtop [%#x-%#x) phys [%#x-%#x) map %#x [%#x-%#x)\n",
+               vlow, vhigh, plow, phigh, mhead, mlow, mhigh);
+#endif
+       return(adjustdata());
+}
+
+STATIC unsigned
+ptrcvt(ptr)
+       unsigned ptr;
+{
+       unsigned ret;
+       char *str;
+
+       if (ptr == 0) {
+               ret = ptr;
+               str = "null";
+       } else if (IS_OVTOPPTR(ptr)) {
+               ret = vlow + (ptr - Ovlow);
+               str = "vtop";
+       } else if (IS_OPHYSPTR(ptr)) {
+               ret = plow + (ptr - Oplow);
+               str = "phys";
+       } else if (IS_OMAPPTR(ptr)) {
+               ret = mlow + (ptr - Omlow);
+               str = "map";
+       } else if (ptr == Omhead) {
+               ret = mhead;
+               str = "maphead";
+       } else {
+               error("bogus pointer %#x", ptr);
+               str = "wild";
+               ret = ptr;
+       }
+#if 0
+       fprintf(stderr, "%x (%s) -> %x\n", ptr, str, ret);
+#endif
+       return(ret);
+}
+
+STATIC int
+adjustdata()
+{
+       register int i, lim;
+       queue_head_t *nq;
+       struct phys_entry *np;
+       struct mapping *nm;
+
+       /* hash table */
+       lim = vtopsize;
+       for (nq = vtop_table; nq < &vtop_table[lim]; nq++) {
+               nq->next = (queue_entry_t) ptrcvt((unsigned)nq->next);
+               nq->prev = (queue_entry_t) ptrcvt((unsigned)nq->prev);
+       }
+
+       /* IPT */
+       lim = physsize;
+       for (np = phys_table; np < &phys_table[lim]; np++) {
+               np->phys_link.next = (queue_entry_t)
+                       ptrcvt((unsigned)np->phys_link.next);
+               np->phys_link.prev = (queue_entry_t)
+                       ptrcvt((unsigned)np->phys_link.prev);
+               np->writer = (struct mapping *) ptrcvt((unsigned)np->writer);
+       }
+
+       /* mapping table */
+       free_mapping.next = (queue_entry_t)ptrcvt((unsigned)free_mapping.next);
+       free_mapping.prev = (queue_entry_t)ptrcvt((unsigned)free_mapping.prev);
+       lim = mapsize;
+       for (nm = map_table; nm < &map_table[lim]; nm++) {
+               nm->hash_link.next = (queue_entry_t)
+                       ptrcvt((unsigned)nm->hash_link.next);
+               nm->hash_link.prev = (queue_entry_t)
+                       ptrcvt((unsigned)nm->hash_link.prev);
+               nm->phys_link.next = (queue_entry_t)
+                       ptrcvt((unsigned)nm->phys_link.next);
+               nm->phys_link.prev = (queue_entry_t)
+                       ptrcvt((unsigned)nm->phys_link.prev);
+       }
+       return(1);
+}
+
+/*
+ * Consistency checks, make sure:
+ *
+ *     1. all mappings are accounted for
+ *     2. no cycles
+ *     3. no wild pointers
+ *     4. consisent TLB state
+ */
+STATIC int
+verifydata()
+{
+       register struct mapstate *ms;
+       register int i;
+       int errors = 0;
+
+       mapstate = (struct mapstate *)
+               mach_malloc("map state", mapsize * sizeof(struct mapstate));
+       for (ms = mapstate; ms < &mapstate[mapsize]; ms++) {
+               ms->flags = 0;
+               ms->hashix = ms->physix = -2;
+       }
+
+       /*
+        * Check the free list
+        */
+       checkhashchain(&free_mapping, M_ISFREE, -1);
+       /*
+        * Check every hash chain
+        */
+       for (i = 0; i < vtopsize; i++)
+               checkhashchain(&vtop_table[i], M_ISHASH, i);
+       /*
+        * Check every phys chain
+        */
+       for (i = 0; i < physsize; i++)
+               checkphyschain(&phys_table[i].phys_link, M_ISPHYS, i);
+       /*
+        * Cycle through mapstate looking for anomolies
+        */
+       ms = mapstate;
+       for (i = 0; i < mapsize; i++) {
+               switch (ms->flags) {
+               case M_ISFREE:
+               case M_ISHASH|M_ISPHYS:
+                       break;
+               case 0:
+                       merror(ms, "not found");
+                       errors++;
+                       break;
+               case M_ISHASH:
+                       merror(ms, "in vtop but not phys");
+                       errors++;
+                       break;
+               case M_ISPHYS:
+                       merror(ms, "in phys but not vtop");
+                       errors++;
+                       break;
+               default:
+                       merror(ms, "totally bogus");
+                       errors++;
+                       break;
+               }
+               ms++;
+       }
+       return(errors ? 0 : 1);
+}
+
+STATIC void
+checkhashchain(qhp, flag, ix)
+       queue_entry_t qhp;
+{
+       register queue_entry_t qp, pqp;
+       register struct mapping *mp;
+       struct mapstate *ms;
+
+       qp = qhp->next;
+       /*
+        * First element is not a mapping structure,
+        * chain must be empty.
+        */
+       if (!IS_MAPPTR(qp)) {
+               if (qp != qhp || qp != qhp->prev)
+                       fatal("bad vtop_table header pointer");
+       } else {
+               pqp = qhp;
+               do {
+                       mp = (struct mapping *) qp;
+                       qp = &mp->hash_link;
+                       if (qp->prev != pqp)
+                               fatal("bad hash_link prev pointer");
+                       ms = &mapstate[mp-map_table];
+                       ms->flags |= flag;
+                       ms->hashix = ix;
+                       pqp = (queue_entry_t) mp;
+                       qp = qp->next;
+               } while (IS_MAPPTR(qp));
+               if (qp != qhp)
+                       fatal("bad hash_link next pointer");
+       }
+}
+
+STATIC void
+checkphyschain(qhp, flag, ix)
+       queue_entry_t qhp;
+{
+       register queue_entry_t qp, pqp;
+       register struct mapping *mp;
+       struct mapstate *ms;
+
+       qp = qhp->next;
+       /*
+        * First element is not a mapping structure,
+        * chain must be empty.
+        */
+       if (!IS_MAPPTR(qp)) {
+               if (qp != qhp || qp != qhp->prev)
+                       fatal("bad phys_table header pointer");
+       } else {
+               pqp = qhp;
+               do {
+                       mp = (struct mapping *) qp;
+                       qp = &mp->phys_link;
+                       if (qp->prev != pqp)
+                               fatal("bad phys_link prev pointer");
+                       ms = &mapstate[mp-map_table];
+                       ms->flags |= flag;
+                       ms->physix = ix;
+                       pqp = (queue_entry_t) mp;
+                       qp = qp->next;
+               } while (IS_MAPPTR(qp));
+               if (qp != qhp)
+                       fatal("bad phys_link next pointer");
+       }
+}
+
+STATIC void
+merror(ms, str)
+       struct mapstate *ms;
+       char *str;
+{
+       terminal_ours();
+       fflush(stdout);
+       fprintf(stderr,
+               "vtophys: %s: %c%c%c, hashix %d, physix %d, mapping %x\n",
+               str,
+               (ms->flags & M_ISFREE) ? 'F' : '-',
+               (ms->flags & M_ISHASH) ? 'H' : '-',
+               (ms->flags & M_ISPHYS) ? 'P' : '-',
+               ms->hashix, ms->physix, &map_table[ms-mapstate]);
+       return_to_top_level();
+}
+
+STATIC int
+mach_read(str, from, top, size)
+       char *str;
+       CORE_ADDR from;
+       char *top;
+       int size;
+{
+       CORE_ADDR paddr;
+
+       if (from == ~0)
+               from = ksym_lookup(str);
+       paddr = vtophys(0, from);
+       if (paddr == ~0 || physrd(paddr, top, size) != 0)
+               fatal("cannot read %s", str);
+}
+
+STATIC char *
+mach_malloc(str, size)
+       char *str;
+       int size;
+{
+       char *ptr = (char *) malloc(size);
+
+       if (ptr == 0)
+               fatal("no memory for %s", str);
+       return(ptr);
+}
+#endif
+
+#ifdef KERNELDEBUG
+void
+_initialize_hp9k8_dep()
+{
+       add_com ("process-address", class_obscure, set_paddr_command,
+"The process identified by (ps-style) ADDR becomes the\n\
+\"current\" process context for kernel debugging.");
+       add_com_alias ("paddr", "process-address", class_obscure, 0);
+       add_com ("virtual-to-physical", class_obscure, vtop_command,
+"Translates the kernel virtual address ADDR into a physical address.");
+       add_com_alias ("vtop", "virtual-to-physical", class_obscure, 0);
+}
+#endif
+
+
+
diff --git a/gdb/hppahpux-xdep.c b/gdb/hppahpux-xdep.c
new file mode 100644 (file)
index 0000000..d5fa3c4
--- /dev/null
@@ -0,0 +1,421 @@
+/* Machine-dependent code which would otherwise be in infptrace.c,
+   for GDB, the GNU debugger.  This code is for the HP PA-RISC cpu.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+/* Low level Unix child interface to ptrace, for GDB when running under Unix.
+   Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#include <sys/ptrace.h>
+
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#include "gdbcore.h"
+#include <sys/user.h>          /* After a.out.h  */
+#include <sys/file.h>
+#include <sys/stat.h>
+\f
+/* This function simply calls ptrace with the given arguments.  
+   It exists so that all calls to ptrace are isolated in this 
+   machine-dependent file. */
+int
+call_ptrace (request, pid, addr, data)
+     int request, pid, *addr, data;
+{
+  return ptrace (request, pid, addr, data, 0);
+}
+
+#ifdef DEBUG_PTRACE
+/* For the rest of the file, use an extra level of indirection */
+/* This lets us breakpoint usefully on call_ptrace. */
+#define ptrace call_ptrace
+#endif
+
+/* This is used when GDB is exiting.  It gives less chance of error.*/
+
+void
+kill_inferior_fast ()
+{
+  if (inferior_pid == 0)
+    return;
+  ptrace (PT_EXIT, inferior_pid, 0, 0, 0); /* PT_EXIT = PT_KILL ? */
+  wait ((int *)0);
+}
+
+void
+kill_inferior ()
+{
+  kill_inferior_fast ();
+  target_mourn_inferior ();
+}
+
+/* Resume execution of the inferior process.
+   If STEP is nonzero, single-step it.
+   If SIGNAL is nonzero, give it that signal.  */
+
+void
+child_resume (step, signal)
+     int step;
+     int signal;
+{
+  errno = 0;
+
+  /* An address of (int *)1 tells ptrace to continue from where it was. 
+     (If GDB wanted it to start some other way, we have already written
+     a new PC value to the child.)  */
+
+  if (step)
+    ptrace (PT_SINGLE, inferior_pid, (int *)1, signal, 0);
+  else
+    ptrace (PT_CONTIN, inferior_pid, (int *)1, signal, 0);
+
+  if (errno)
+    perror_with_name ("ptrace");
+}
+\f
+#ifdef ATTACH_DETACH
+/* Nonzero if we are debugging an attached process rather than
+   an inferior.  */
+extern int attach_flag;
+
+/* Start debugging the process whose number is PID.  */
+int
+attach (pid)
+     int pid;
+{
+  errno = 0;
+  ptrace (PT_ATTACH, pid, 0, 0, 0);
+  if (errno)
+    perror_with_name ("ptrace");
+  attach_flag = 1;
+  return pid;
+}
+
+/* Stop debugging the process whose number is PID
+   and continue it with signal number SIGNAL.
+   SIGNAL = 0 means just continue it.  */
+
+void
+detach (signal)
+     int signal;
+{
+  errno = 0;
+  ptrace (PT_DETACH, inferior_pid, 1, signal, 0);
+  if (errno)
+    perror_with_name ("ptrace");
+  attach_flag = 0;
+}
+#endif /* ATTACH_DETACH */
+\f
+#if !defined (FETCH_INFERIOR_REGISTERS)
+
+/* KERNEL_U_ADDR is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+#if defined (KERNEL_U_ADDR_BSD)
+/* Get kernel_u_addr using BSD-style nlist().  */
+CORE_ADDR kernel_u_addr;
+
+#include <a.out.gnu.h>         /* For struct nlist */
+
+void
+_initialize_kernel_u_addr ()
+{
+  struct nlist names[2];
+
+  names[0].n_un.n_name = "_u";
+  names[1].n_un.n_name = NULL;
+  if (nlist ("/vmunix", names) == 0)
+    kernel_u_addr = names[0].n_value;
+  else
+    fatal ("Unable to get kernel u area address.");
+}
+#endif /* KERNEL_U_ADDR_BSD.  */
+
+#if defined (KERNEL_U_ADDR_HPUX)
+/* Get kernel_u_addr using HPUX-style nlist().  */
+CORE_ADDR kernel_u_addr;
+
+struct hpnlist {      
+        char *          n_name;
+        long            n_value;  
+        unsigned char   n_type;   
+        unsigned char   n_length;  
+        short           n_almod;   
+        short           n_unused;
+};
+static struct hpnlist nl[] = {{ "_u", -1, }, { (char *) 0, }};
+
+/* read the value of the u area from the hp-ux kernel */
+void _initialize_kernel_u_addr ()
+{
+    struct user u;
+    nlist ("/hp-ux", &nl);
+    kernel_u_addr = nl[0].n_value;
+}
+#endif /* KERNEL_U_ADDR_HPUX.  */
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area.  */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+  ptrace (PT_READ_U, inferior_pid, \
+          (int *)(offsetof (struct user, u_ar0)), 0, 0) - KERNEL_U_ADDR
+#endif
+
+/* Registers we shouldn't try to fetch.  */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) 0
+#endif
+
+/* Fetch one register.  */
+
+static void
+fetch_register (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[MAX_REGISTER_RAW_SIZE];
+  char mess[128];                              /* For messages */
+  register int i;
+
+  /* Offset of registers within the u area.  */
+  unsigned int offset;
+
+  if (CANNOT_FETCH_REGISTER (regno))
+    {
+      bzero (buf, REGISTER_RAW_SIZE (regno));  /* Supply zeroes */
+      supply_register (regno, buf);
+      return;
+    }
+
+  offset = U_REGS_OFFSET;
+
+  regaddr = register_addr (regno, offset);
+  for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+    {
+      errno = 0;
+      *(int *) &buf[i] = ptrace (PT_RUREGS, inferior_pid, (int *)regaddr, 0, 0);
+      regaddr += sizeof (int);
+      if (errno != 0)
+       {
+         sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
+         perror_with_name (mess);
+       }
+    }
+  if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+    buf[3] &= ~0x3;
+  supply_register (regno, buf);
+}
+
+
+/* Fetch all registers, or just one, from the child process.  */
+
+void
+fetch_inferior_registers (regno)
+     int regno;
+{
+  if (regno == -1)
+    for (regno = 0; regno < NUM_REGS; regno++)
+      fetch_register (regno);
+  else
+    fetch_register (regno);
+}
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+
+void
+store_inferior_registers (regno)
+     int regno;
+{
+  register unsigned int regaddr;
+  char buf[80];
+  extern char registers[];
+  register int i;
+
+  unsigned int offset = U_REGS_OFFSET;
+
+  if (regno >= 0)
+    {
+      regaddr = register_addr (regno, offset);
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+       {
+         errno = 0;
+         ptrace (PT_WUAREA, inferior_pid, (int *)regaddr,
+                 *(int *) &registers[REGISTER_BYTE (regno) + i], 0);
+         if (errno != 0)
+           {
+             sprintf (buf, "writing register number %d(%d)", regno, i);
+             perror_with_name (buf);
+           }
+         regaddr += sizeof(int);
+       }
+    }
+  else
+    {
+      for (regno = 0; regno < NUM_REGS; regno++)
+       {
+         if (CANNOT_STORE_REGISTER (regno))
+           continue;
+         regaddr = register_addr (regno, offset);
+         for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+           {
+             errno = 0;
+             ptrace (PT_WUAREA, inferior_pid, (int *)regaddr,
+                     *(int *) &registers[REGISTER_BYTE (regno) + i], 0);
+             if (errno != 0)
+               {
+                 sprintf (buf, "writing register number %d(%d)", regno, i);
+                 perror_with_name (buf);
+               }
+             regaddr += sizeof(int);
+           }
+       }
+    }
+  return;
+}
+#endif /* !defined (FETCH_INFERIOR_REGISTERS).  */
+\f
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+   in the NEW_SUN_PTRACE case.
+   It ought to be straightforward.  But it appears that writing did
+   not write the data that I specified.  I cannot understand where
+   it got the data that it actually did write.  */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+   to debugger memory starting at MYADDR.   Copy to inferior if
+   WRITE is nonzero.
+  
+   Returns the length copied, which is either the LEN argument or zero.
+   This xfer function does not do partial moves, since child_ops
+   doesn't allow memory operations to cross below us in the target stack
+   anyway.  */
+
+int
+child_xfer_memory (memaddr, myaddr, len, write, target)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+     struct target_ops *target;                /* ignored */
+{
+  register int i;
+  /* Round starting address down to longword boundary.  */
+  register CORE_ADDR addr = memaddr & - sizeof (int);
+  /* Round ending address up; get number of longwords that makes.  */
+  register int count
+    = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+  /* Allocate buffer of that many longwords.  */
+  register int *buffer = (int *) alloca (count * sizeof (int));
+
+  if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory data.  */
+
+      if (addr != memaddr || len < (int)sizeof (int)) {
+       /* Need part of initial word -- fetch it.  */
+        buffer[0] = ptrace (PT_RIUSER, inferior_pid, (int *)addr, 0, 0);
+      }
+
+      if (count > 1)           /* FIXME, avoid if even boundary */
+       {
+         buffer[count - 1]
+           = ptrace (PT_RIUSER, inferior_pid,
+                     (int *)(addr + (count - 1) * sizeof (int)), 0, 0);
+       }
+
+      /* Copy data to be written over corresponding part of buffer */
+
+      bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+      /* Write the entire buffer.  */
+
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         ptrace (PT_WDUSER, inferior_pid, (int *)addr, buffer[i], 0);
+         if (errno)
+           {
+             /* Using the appropriate one (I or D) is necessary for
+                Gould NP1, at least.  */
+             errno = 0;
+             ptrace (PT_WIUSER, inferior_pid, (int *)addr, buffer[i], 0);
+           }
+         if (errno)
+           return 0;
+       }
+    }
+  else
+    {
+      /* Read all the longwords */
+      for (i = 0; i < count; i++, addr += sizeof (int))
+       {
+         errno = 0;
+         buffer[i] = ptrace (PT_RIUSER, inferior_pid, (int *)addr, 0, 0);
+         if (errno)
+           return 0;
+         QUIT;
+       }
+
+      /* Copy appropriate bytes out of the buffer.  */
+      bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+    }
+  return len;
+}
+
+
+
+
+int
+getpagesize()
+{
+  return(4096);
+}
index 6d8a656..62c4cd3 100755 (executable)
--- a/gdb/munch
+++ b/gdb/munch
@@ -23,12 +23,21 @@ if test "`$MUNCH_NM main.o | egrep main | egrep FUNC | egrep GLOB`" != "" ; then
         's/^.*\(_initialize_[a-zA-Z0-9_]*\).*$/  {extern void \1 (); \1 ();}/'\
       | sort -u
 elif test "`$MUNCH_NM main.o | egrep '[TD] _?main$'`" = "" ; then
-    # System V style nm
-    shift;
-    $MUNCH_NM $* | egrep '_initialize_.*' | egrep '\.text'|\
-     sed -e \
-       's/^.*\(_initialize_[a-zA-Z0-9_]*\).*/  {extern void \1 (); \1 ();}/' \
-     | sort -u
+     if test "`$MUNCH_NM main.o | head -6 | egrep 'Subspace$'`" != "" ; then
+       # HP PA RISC compilers don't prepend underscores
+       shift;
+       $MUNCH_NM $* | egrep '_initialize_.*' | \
+         sed -e \
+           's/^.*\(_initialize_[a-zA-Z0-9_]*\).*/   {extern void \1 (); \1 ();}/' \
+           | sort -u
+     else
+       # System V style nm
+       shift;
+       $MUNCH_NM $* | egrep '_initialize_.*' | egrep '\.text'|\
+         sed -e \
+           's/^.*\(_initialize_[a-zA-Z0-9_]*\).*/  {extern void \1 (); \1 ();}/' \
+           | sort -u
+     fi
 else
     # BSD style nm
     # We now accept either text or data symbols, since the RT/PC uses data.
index 6b6e3de..e064aeb 100644 (file)
@@ -70,8 +70,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
          SET_NAMESTRING();
          if ((namestring[0] == '-' && namestring[1] == 'l')
              || (namestring [(nsl = strlen (namestring)) - 1] == 'o'
-                 && namestring [nsl - 2] == '.'))
+                 && namestring [nsl - 2] == '.')
+#ifdef hp9000s800
+              /* some cooperation from gcc to get around ld stupidity */
+              || (namestring[0] == 'e' && !strcmp (namestring, "end_file."))
+#endif
+             )
            {
+#ifndef hp9000s800
              if (objfile -> ei.entry_point <  CUR_SYMBOL_VALUE &&
                  objfile -> ei.entry_point >= last_o_file_start &&
                  addr == 0)            /* FIXME nogood nomore */
@@ -79,6 +85,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                  objfile -> ei.entry_file_lowpc = last_o_file_start;
                  objfile -> ei.entry_file_highpc = CUR_SYMBOL_VALUE;
                }
+#endif
              if (past_first_source_file && pst
                  /* The gould NP1 uses low values for .o and -l symbols
                     which are not the address.  */
diff --git a/gdb/tm-hppabsd.h b/gdb/tm-hppabsd.h
new file mode 100644 (file)
index 0000000..c1bb513
--- /dev/null
@@ -0,0 +1,570 @@
+/* Parameters for execution on a Hewlett-Packard PA-RISC machine, running 
+   HPUX or BSD.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc. 
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Get at various relevent fields of an instruction word. */
+
+#define MASK_5 0x1f
+#define MASK_11 0x7ff
+#define MASK_14 0x3fff
+#define MASK_21 0x1fffff
+
+/* This macro gets bit fields using HP's numbering (MSB = 0) */
+
+#define GET_FIELD(X, FROM, TO) \
+  ((X) >> 31 - (TO) & (1 << ((TO) - (FROM) + 1)) - 1)
+
+/* Watch out for NaNs */
+
+#define IEEE_FLOAT
+
+/* Groan */
+
+#define        ARGS_GROW_DOWN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+
+
+/* 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.  */
+
+/* skip (stw rp, -20(0,sp)); copy 4,1; copy sp, 4; stwm 1,framesize(sp) 
+   for gcc, or (stw rp, -20(0,sp); stwm 1, framesize(sp) for hcc */
+
+#define SKIP_PROLOGUE(pc) \
+{ if (read_memory_integer ((pc), 4) == 0x6BC23FD9)                     \
+    { if (read_memory_integer ((pc) + 4, 4) == 0x8040241)              \
+       (pc) += 16;                                                     \
+      else if ((read_memory_integer (pc + 4, 4) & ~MASK_14) == 0x68810000) \
+       (pc) += 8;}                                                     \
+  else if (read_memory_integer ((pc), 4) == 0x8040241)                 \
+    (pc) += 12;                                                                \
+  else if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000)     \
+    (pc) += 4;}
+
+/* Immediately after a function call, return the saved pc.
+   Can't go through the frames for this because on some machines
+   the new frame is not set up until the new function executes
+   some instructions.  */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_register (RP_REGNUM) & ~3)
+
+/* Address of end of stack space. Who knows.  */
+
+#define STACK_END_ADDR 0x80000000
+
+/* Stack grows upward */
+
+#define INNER_THAN >
+
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+/*#define BREAKPOINT {0x00, 0x00, 0x00, 0x00}*/
+#ifdef KERNELDEBUG     /* XXX */
+#define BREAKPOINT {0x00, 0x00, 0xa0, 0x00}
+#else
+#define BREAKPOINT {0x00, 0x01, 0x00, 0x04}
+#endif
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.
+
+   Not on the PA-RISC */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* return instruction is bv r0(rp) */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0xE840C000)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Largest integer type */
+#define LONGEST long
+
+/* Name of the builtin type for the LONGEST type above. */
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 100
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES \
+ {"flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",       \
+  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",        \
+  "r20", "r21", "r22", "arg3", "arg2", "arg1", "arg0", "dp", "ret0", "ret1", \
+  "sp", "r31", "sar", "pcoqh", "pcsqh", "pcoqt", "pcsqt", \
+  "eiem", "iir", "isr", "ior", "ipsw", "goto", "sr4", "sr0", "sr1", "sr2", \
+  "sr3", "sr5", "sr6", "sr7", "cr0", "cr8", "cr9", "ccr", "cr12", "cr13", \
+  "cr24", "cr25", "cr26", "mpsfu_high", "mpsfu_low", "mpsfu_ovflo", "pad", \
+  "fpsr", "fpe1", "fpe2", "fpe3", "fpe4", "fpe5", "fpe6", "fpe7", \
+  "fp4", "fp5", "fp6", "fp7", "fp8", \
+  "fp9", "fp10", "fp11", "fp12", "fp13", "fp14", "fp15", \
+  "fp16", "fp17", "fp18", "fp19", "fp20", "fp21", "fp22", "fp23", \
+  "fp24", "fp25", "fp26", "fp27", "fp28", "fp29", "fp30", "fp31"}
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define RP_REGNUM 2            /* return pointer */
+#define FP_REGNUM 4            /* Contains address of executing stack */
+                               /* frame */
+#define SP_REGNUM 30           /* Contains address of top of stack */
+#define SAR_REGNUM 32          /* shift amount register */
+#define IPSW_REGNUM 41         /* processor status word. ? */
+#define PCOQ_HEAD_REGNUM 33    /* instruction offset queue head */
+#define PCSQ_HEAD_REGNUM 34    /* instruction space queue head */
+#define PCOQ_TAIL_REGNUM 35    /* instruction offset queue tail */
+#define PCSQ_TAIL_REGNUM 36    /* instruction space queue tail */
+#define FP0_REGNUM 64          /* floating point reg. 0 */
+#define FP4_REGNUM 72
+
+/* compatibility with the rest of gdb. */
+#define PC_REGNUM PCOQ_HEAD_REGNUM
+#define NPC_REGNUM PCOQ_TAIL_REGNUM
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+   of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum, fp) pa_do_registers_info (_regnum, fp)
+
+/* PA specific macro to see if the current instruction is nullified. */
+#define INSTRUCTION_NULLIFIED ((int)read_register (IPSW_REGNUM) & 0x00200000)
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (32 * 4 + 11 * 4 + 8 * 4 + 12 * 4 + 4 + 32 * 8)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) \
+ ((N) >= FP4_REGNUM ? ((N) - FP4_REGNUM) * 8 + 288 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the PA-RISC, all regs are 4 bytes
+   except the floating point regs which are 8 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) ((N) < FP4_REGNUM ? 4 : 8)
+
+/* Number of bytes of storage in the program's representation
+   for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); }
+
+/* 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), (REGNUM) < FP4_REGNUM ? 4 : 8); }
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < FP4_REGNUM ? builtin_type_int : builtin_type_double)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) {write_register (28, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy ((REGBUF) + REGISTER_BYTE(TYPE_LENGTH(TYPE) > 4 ? \
+        FP4_REGNUM :28), 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 (TYPE_LENGTH(TYPE) > 4 ? FP4_REGNUM :28,                \
+                       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) + 28))
+
+/* This is a piece of magic that is given a register number REGNO
+   and as BLOCKEND the address in the system of the end of the user structure
+   and stores in ADDR the address in the kernel or core dump
+   of that register.  */
+
+
+/* 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 PA-RISC, the frame's nominal address
+   is the address of a 4-byte word containing the calling frame's
+   address (previous FP).  */
+
+#define FRAME_CHAIN(thisframe)  \
+  (inside_entry_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  frame_chain_valid (chain, thisframe)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+/* Set VAL to the number of args passed to frame described by FI.
+   Can set VAL to -1, meaning no way to tell.  */
+
+/* We can't tell how many args there are
+   now that the C compiler delays popping them.  */
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+/* Deal with dummy functions later. */
+
+#define STW_P(INSN) (((INSN) & 0xfc000000) == 0x68000000)
+#define ADDIL_P(INSN) (((INSN) & 0xfc000000) == 0x28000000)
+#define LDO_P(INSN) (((INSN) & 0xfc00c000) == 0x34000000)
+
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{ register int regnum;                                                 \
+  register CORE_ADDR next_addr;                                                \
+  register CORE_ADDR pc;                                               \
+  unsigned this_insn;                                                  \
+  unsigned address;                                                    \
+                                                                       \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  if ((frame_info)->pc <= ((frame_info)->frame - CALL_DUMMY_LENGTH -   \
+                          FP_REGNUM * 4 - 16 * 8)                      \
+      && (frame_info)->pc > (frame_info)->frame)                       \
+    find_dummy_frame_regs ((frame_info), &(frame_saved_regs));         \
+  else                                                                 \
+    { pc = get_pc_function_start ((frame_info)->pc);                   \
+      if (read_memory_integer (pc, 4) == 0x6BC23FD9)                   \
+       { (frame_saved_regs).regs[RP_REGNUM] = (frame_info)->frame - 20;\
+         pc = pc + 4;                                                  \
+       }                                                               \
+      if (read_memory_integer (pc, 4) != 0x8040241) goto lose;         \
+      pc += 8;                 /* skip "copy 4,1; copy 30, 4" */       \
+      /* skip either "stw 1,0(4);addil L'fsize,30;ldo R'fsize(1),30"   \
+        or "stwm 1,fsize(30)" */                                       \
+      if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000)      \
+       pc += 12;                                                       \
+      else                                                             \
+       pc += 4;                                                        \
+      while (1)                                                                \
+       { this_insn = read_memory_integer(pc, 4);                       \
+         if (STW_P (this_insn)) /* stw */                              \
+           { regnum = GET_FIELD (this_insn, 11, 15);                   \
+             if (!regnum) goto lose;                                   \
+             (frame_saved_regs).regs[regnum] = (frame_info)->frame +   \
+               extract_14 (this_insn);                                 \
+             pc += 4;                                                  \
+           }                                                           \
+         else if (ADDIL_P (this_insn)) /* addil */                     \
+           { int next_insn;                                            \
+             next_insn = read_memory_integer(pc + 4, 4);               \
+             if (STW_P (next_insn)) /* stw */                          \
+               { regnum = GET_FIELD (this_insn, 6, 10);                \
+                 if (!regnum) goto lose;                               \
+                 (frame_saved_regs).regs[regnum] = (frame_info)->frame +\
+                   (extract_21 (this_insn) << 11) + extract_14 (next_insn);\
+                 pc += 8;                                              \
+               }                                                       \
+             else                                                      \
+               break;                                                  \
+           }                                                           \
+         else                                                          \
+           { pc += 4;                                                  \
+             break;                                                    \
+           }                                                           \
+       }                                                               \
+      this_insn = read_memory_integer (pc, 4);                         \
+      if (LDO_P (this_insn))                                           \
+       { next_addr = (frame_info)->frame + extract_14 (this_insn);     \
+         pc += 4;                                                      \
+       }                                                               \
+      else if (ADDIL_P (this_insn))                                    \
+       { next_addr = (frame_info)->frame + (extract_21 (this_insn) << 11)\
+           + extract_14 (read_memory_integer (pc + 4, 4));             \
+           pc += 8;                                                    \
+         }                                                             \
+      while (1)                                                                \
+       { this_insn = read_memory_integer (pc, 4);                      \
+         if ((this_insn & 0xfc001fe0) == 0x2c001220) /* fstds,ma */    \
+           { regnum = GET_FIELD (this_insn, 27, 31);                   \
+             (frame_saved_regs).regs[regnum + FP0_REGNUM] = next_addr; \
+             next_addr += 8;                                           \
+           }                                                           \
+         else                                                          \
+           break;                                                      \
+       }                                                               \
+    lose:                                                              \
+      (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame;                \
+      (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame -4;     \
+    }}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  int int_buffer;                                                      \
+  double freg_buffer;                                                  \
+  /* Space for "arguments"; the RP goes in here. */                    \
+  sp += 48;                                                            \
+  int_buffer = read_register (RP_REGNUM) | 0x3;                                \
+  write_memory (sp - 20, &int_buffer, 4);                              \
+  int_buffer = read_register (FP_REGNUM);                              \
+  write_memory (sp, &int_buffer, 4);                                   \
+  write_register (FP_REGNUM, sp);                                      \
+  sp += 4;                                                             \
+  for (regnum = 1; regnum < 31; regnum++)                              \
+    if (regnum != RP_REGNUM && regnum != FP_REGNUM)                    \
+      sp = push_word (sp, read_register (regnum));                     \
+  for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++)               \
+    { read_register_bytes (REGISTER_BYTE (regnum), &freg_buffer, 8);   \
+      sp = push_bytes (sp, &freg_buffer, 8);}                          \
+  sp = push_word (sp, read_register (IPSW_REGNUM));                    \
+  sp = push_word (sp, read_register (SAR_REGNUM));                     \
+  sp = push_word (sp, read_register (PCOQ_TAIL_REGNUM));               \
+  sp = push_word (sp, read_register (PCSQ_TAIL_REGNUM));               \
+  write_register (SP_REGNUM, sp);}
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                         \
+  register CORE_ADDR fp;                                               \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info *fi;                                               \
+  double freg_buffer;                                                  \
+  fi = get_frame_info (frame);                                         \
+  fp = fi->frame;                                                      \
+  get_frame_saved_regs (fi, &fsr);                                     \
+  for (regnum = 31; regnum > 0; regnum--)                              \
+    if (fsr.regs[regnum])                                              \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--)                 \
+    if (fsr.regs[regnum])                                              \
+      { read_memory (fsr.regs[regnum], &freg_buffer, 8);               \
+        write_register_bytes (REGISTER_BYTE (regnum), &freg_buffer, 8); }\
+  if (fsr.regs[IPSW_REGNUM])                                           \
+    write_register (IPSW_REGNUM,                                       \
+                   read_memory_integer (fsr.regs[IPSW_REGNUM], 4));    \
+  if (fsr.regs[SAR_REGNUM])                                            \
+    write_register (SAR_REGNUM,                                                \
+                   read_memory_integer (fsr.regs[SAR_REGNUM], 4));     \
+  if (fsr.regs[PCOQ_TAIL_REGNUM])                                      \
+    write_register (PCOQ_TAIL_REGNUM,                                  \
+                   read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4));\
+  if (fsr.regs[PCSQ_TAIL_REGNUM])                                      \
+    write_register (PCSQ_TAIL_REGNUM,                                  \
+                   read_memory_integer (fsr.regs[PCSQ_TAIL_REGNUM], 4));\
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+
+; Call stack frame has already been built by gdb. Since we could be calling 
+; a varargs function, and we do not have the benefit of a stub to put things in
+; the right place, we load the first 4 word of arguments into both the general
+; and fp registers.
+call_dummy
+       ldw -36(sp), arg0
+       ldw -40(sp), arg1
+       ldw -44(sp), arg2
+       ldw -48(sp), arg3
+       ldo -36(sp), r1
+       fldws 0(0, r1), fr4
+       fldds -4(0, r1), fr5
+       fldws -8(0, r1), fr6
+       fldds -12(0, r1), fr7
+       ldil 0, r22                     ; target will be placed here.
+       ldo 0(r22), r22
+       ldsid (0,r22), r3
+       ldil 0, r1                      ; _sr4export will be placed here.
+       ldo 0(r1), r1
+       ldsid (0,r1), r4
+       combt,=,n r3, r4, text_space    ; If target is in data space, do a
+       ble 0(sr5, r22)                 ; "normal" procedure call
+       copy r31, r2
+       break 4, 8 
+text_space                             ; Otherwise, go through _sr4export,
+       ble (sr4, r1)                   ; which will return back here.
+       stw 31,-24(r30)
+       break 4, 8
+
+   The dummy decides if the target is in text space or data space. If
+   it's in data space, there's no problem because the target can
+   return back to the dummy. However, if the target is in text space,
+   the dummy calls the secret, undocumented routine _sr4export, which
+   calls a function in text space and can return to any space. Instead
+   of including fake instructions to represent saved registers, we
+   know that the frame is associated with the call dummy and treat it
+   specially. */ 
+
+#define CALL_DUMMY { 0x4bda3fb9, 0x4bd93fb1, 0x4bd83fa9, 0x4bd73fa1,   \
+                    0x37c13fb9, 0x24201004, 0x2c391005, 0x24311006,    \
+                    0x2c291007, 0x22c00000, 0x36d60000, 0x02c010a3,    \
+                    0x20200000, 0x34210000, 0x002010a4, 0x80832012,    \
+                    0xe6c06000, 0x081f0242, 0x00010004, 0xe4202000,    \
+                    0x6bdf3fd1, 0x00010004}
+
+#define CALL_DUMMY_LENGTH 88
+#define CALL_DUMMY_START_OFFSET 0
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ static CORE_ADDR sr4export_address = 0;                              \
+                                                                       \
+  if (!sr4export_address)                                              \
+    {                                                                  \
+      struct minimal_symbol *msymbol;                                   \
+      msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL);\
+      if (msymbol = NULL)                                               \
+       error ("Can't find an address for _sr4export trampoline");      \
+      else                                                             \
+       sr4export_address = msymbol -> address;                         \
+    }                                                                  \
+  dummyname[9] = deposit_21 (fun >> 11, dummyname[9]);                 \
+  dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]);           \
+  dummyname[12] = deposit_21 (sr4export_address >> 11, dummyname[12]); \
+  dummyname[13] = deposit_14 (sr4export_address & MASK_11, dummyname[13]);\
+}
+
+/* Write the PC to a random value.
+   On PA-RISC, we need to be sure that the PC space queue is correct. */
+
+#define WRITE_PC(addr) \
+{ int space_reg, space = ((addr) >> 30);               \
+  int space_val;                                       \
+  if (space == 0)                                      \
+    space_reg = 43;            /* Space reg sr4 */     \
+  else if (space == 1)                                 \
+    space_reg = 48;            /* Space reg sr5*/      \
+  else                                                 \
+    error ("pc = %x is in illegal space.", addr);      \
+  space_val = read_register (space_reg);               \
+  write_register (PCOQ_HEAD_REGNUM, addr);             \
+  write_register (PCSQ_HEAD_REGNUM, space_val);                \
+  write_register (PCOQ_TAIL_REGNUM, addr);             \
+  write_register (PCSQ_TAIL_REGNUM, space_val);}
+
+
+#  ifndef SEEK_SET
+#    define SEEK_SET    0       /* Set file pointer to "offset" */
+#    define SEEK_CUR    1       /* Set file pointer to current plus "offset" */
+#    define SEEK_END    2       /* Set file pointer to EOF plus "offset" */
+#  endif /* SEEK_SET */
+
+
diff --git a/gdb/tm-hppahpux.h b/gdb/tm-hppahpux.h
new file mode 100644 (file)
index 0000000..bf1662f
--- /dev/null
@@ -0,0 +1,576 @@
+/* Parameters for execution on a Hewlett-Packard PA-RISC machine, running 
+   HPUX or BSD.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc. 
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Get at various relevent fields of an instruction word. */
+
+#define MASK_5 0x1f
+#define MASK_11 0x7ff
+#define MASK_14 0x3fff
+#define MASK_21 0x1fffff
+
+/* This macro gets bit fields using HP's numbering (MSB = 0) */
+
+#define GET_FIELD(X, FROM, TO) \
+  ((X) >> 31 - (TO) & (1 << ((TO) - (FROM) + 1)) - 1)
+
+/* Watch out for NaNs */
+
+#define IEEE_FLOAT
+
+/* Groan */
+
+#define        ARGS_GROW_DOWN
+
+/* Get rid of any system-imposed stack limit if possible.  */
+
+
+
+/* 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.  */
+
+/* skip (stw rp, -20(0,sp)); copy 4,1; copy sp, 4; stwm 1,framesize(sp) 
+   for gcc, or (stw rp, -20(0,sp); stwm 1, framesize(sp) for hcc */
+
+#define SKIP_PROLOGUE(pc) \
+{ if (read_memory_integer ((pc), 4) == 0x6BC23FD9)                     \
+    { if (read_memory_integer ((pc) + 4, 4) == 0x8040241)              \
+       (pc) += 16;                                                     \
+      else if ((read_memory_integer (pc + 4, 4) & ~MASK_14) == 0x68810000) \
+       (pc) += 8;}                                                     \
+  else if (read_memory_integer ((pc), 4) == 0x8040241)                 \
+    (pc) += 12;                                                                \
+  else if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000)     \
+    (pc) += 4;}
+
+/* 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)              \
+  ((get_frame_pc (frame) >= millicode_start     \
+    && get_frame_pc (frame) < millicode_end) ?  \
+   read_register (31) & ~3                      \
+   : read_register (RP_REGNUM) & ~3)
+
+/* Address of end of stack space. Who knows.  */
+
+#define STACK_END_ADDR 0x80000000
+
+/* Stack grows upward */
+
+#define INNER_THAN >
+
+
+/* Sequence of bytes for breakpoint instruction.  */
+
+/*#define BREAKPOINT {0x00, 0x00, 0x00, 0x00}*/
+#ifdef KERNELDEBUG     /* XXX */
+#define BREAKPOINT {0x00, 0x00, 0xa0, 0x00}
+#else
+#define BREAKPOINT {0x00, 0x01, 0x00, 0x04}
+#endif
+
+/* Amount PC must be decremented by after a breakpoint.
+   This is often the number of bytes in BREAKPOINT
+   but not always.
+
+   Not on the PA-RISC */
+
+#define DECR_PC_AFTER_BREAK 0
+
+/* return instruction is bv r0(rp) */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer (pc, 4) == 0xE840C000)
+
+/* Return 1 if P points to an invalid floating point value.  */
+
+#define INVALID_FLOAT(p, len) 0   /* Just a first guess; not checked */
+
+/* Largest integer type */
+#define LONGEST long
+
+/* Name of the builtin type for the LONGEST type above. */
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+
+/* Say how long (ordinary) registers are.  */
+
+#define REGISTER_TYPE long
+
+/* Number of machine registers */
+
+#define NUM_REGS 100
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+#define REGISTER_NAMES \
+ {"flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",       \
+  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",        \
+  "r20", "r21", "r22", "arg3", "arg2", "arg1", "arg0", "dp", "ret0", "ret1", \
+  "sp", "r31", "sar", "pcoqh", "pcsqh", "pcoqt", "pcsqt", \
+  "eiem", "iir", "isr", "ior", "ipsw", "goto", "sr4", "sr0", "sr1", "sr2", \
+  "sr3", "sr5", "sr6", "sr7", "cr0", "cr8", "cr9", "ccr", "cr12", "cr13", \
+  "cr24", "cr25", "cr26", "mpsfu_high", "mpsfu_low", "mpsfu_ovflo", "pad", \
+  "fpsr", "fpe1", "fpe2", "fpe3", "fpe4", "fpe5", "fpe6", "fpe7", \
+  "fp4", "fp5", "fp6", "fp7", "fp8", \
+  "fp9", "fp10", "fp11", "fp12", "fp13", "fp14", "fp15", \
+  "fp16", "fp17", "fp18", "fp19", "fp20", "fp21", "fp22", "fp23", \
+  "fp24", "fp25", "fp26", "fp27", "fp28", "fp29", "fp30", "fp31"}
+
+
+
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+#define RP_REGNUM 2            /* return pointer */
+#define FP_REGNUM 4            /* Contains address of executing stack */
+                               /* frame */
+#define SP_REGNUM 30           /* Contains address of top of stack */
+#define SAR_REGNUM 32          /* shift amount register */
+#define IPSW_REGNUM 41         /* processor status word. ? */
+#define PCOQ_HEAD_REGNUM 33    /* instruction offset queue head */
+#define PCSQ_HEAD_REGNUM 34    /* instruction space queue head */
+#define PCOQ_TAIL_REGNUM 35    /* instruction offset queue tail */
+#define PCSQ_TAIL_REGNUM 36    /* instruction space queue tail */
+#define FP0_REGNUM 64          /* floating point reg. 0 */
+#define FP4_REGNUM 72
+
+/* compatibility with the rest of gdb. */
+#define PC_REGNUM PCOQ_HEAD_REGNUM
+#define NPC_REGNUM PCOQ_TAIL_REGNUM
+
+/* Define DO_REGISTERS_INFO() to do machine-specific formatting
+   of register dumps. */
+
+#define DO_REGISTERS_INFO(_regnum, fp) pa_do_registers_info (_regnum, fp)
+
+/* PA specific macro to see if the current instruction is nullified. */
+#define INSTRUCTION_NULLIFIED ((int)read_register (IPSW_REGNUM) & 0x00200000)
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+#define REGISTER_BYTES (32 * 4 + 11 * 4 + 8 * 4 + 12 * 4 + 4 + 32 * 8)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) \
+ ((N) >= FP4_REGNUM ? ((N) - FP4_REGNUM) * 8 + 288 : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  On the PA-RISC, all regs are 4 bytes
+   except the floating point regs which are 8 bytes.  */
+
+#define REGISTER_RAW_SIZE(N) ((N) < FP4_REGNUM ? 4 : 8)
+
+/* Number of bytes of storage in the program's representation
+   for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) 0
+
+/* Convert data from raw format for register REGNUM
+   to virtual format for register REGNUM.  */
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); }
+
+/* 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), (REGNUM) < FP4_REGNUM ? 4 : 8); }
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) < FP4_REGNUM ? builtin_type_int : builtin_type_double)
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) {write_register (28, (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+   a function return value of type TYPE, and copy that, in virtual format,
+   into VALBUF.  */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+  bcopy ((REGBUF) + REGISTER_BYTE(TYPE_LENGTH(TYPE) > 4 ? \
+        FP4_REGNUM :28), 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 (TYPE_LENGTH(TYPE) > 4 ? FP4_REGNUM :28,                \
+                       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) + 28))
+
+/* This is a piece of magic that is given a register number REGNO
+   and as BLOCKEND the address in the system of the end of the user structure
+   and stores in ADDR the address in the kernel or core dump
+   of that register.  */
+
+
+/* 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 PA-RISC, the frame's nominal address
+   is the address of a 4-byte word containing the calling frame's
+   address (previous FP).  */
+
+#define FRAME_CHAIN(thisframe)  \
+  (inside_entry_file ((thisframe)->pc) ? \
+   read_memory_integer ((thisframe)->frame, 4) :\
+   0)
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+  frame_chain_valid (chain, thisframe)
+
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+
+/* Define other aspects of the stack frame.  */
+
+/* A macro that tells us whether the function invocation represented
+   by FI does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+  (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#define FRAME_SAVED_PC(FRAME) frame_saved_pc (FRAME)
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+/* Set VAL to the number of args passed to frame described by FI.
+   Can set VAL to -1, meaning no way to tell.  */
+
+/* We can't tell how many args there are
+   now that the C compiler delays popping them.  */
+#define FRAME_NUM_ARGS(val,fi) (val = -1)
+
+/* Return number of bytes at start of arglist that are not really args.  */
+
+#define FRAME_ARGS_SKIP 0
+
+/* Put here the code to store, into a struct frame_saved_regs,
+   the addresses of the saved registers of frame described by FRAME_INFO.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
+/* Deal with dummy functions later. */
+
+#define STW_P(INSN) (((INSN) & 0xfc000000) == 0x68000000)
+#define ADDIL_P(INSN) (((INSN) & 0xfc000000) == 0x28000000)
+#define LDO_P(INSN) (((INSN) & 0xfc00c000) == 0x34000000)
+
+int millicode_start, millicode_end;
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs)            \
+{ register int regnum;                                                 \
+  register CORE_ADDR next_addr;                                                \
+  register CORE_ADDR pc;                                               \
+  unsigned this_insn;                                                  \
+  unsigned address;                                                    \
+                                                                       \
+  bzero (&frame_saved_regs, sizeof frame_saved_regs);                  \
+  if ((frame_info)->pc <= ((frame_info)->frame - CALL_DUMMY_LENGTH -   \
+                          FP_REGNUM * 4 - 16 * 8)                      \
+      && (frame_info)->pc > (frame_info)->frame)                       \
+    find_dummy_frame_regs ((frame_info), &(frame_saved_regs));         \
+  else                                                                 \
+    { pc = get_pc_function_start ((frame_info)->pc);                   \
+      if (read_memory_integer (pc, 4) == 0x6BC23FD9)                   \
+       { (frame_saved_regs).regs[RP_REGNUM] = (frame_info)->frame - 20;\
+         pc = pc + 4;                                                  \
+       }                                                               \
+      if (read_memory_integer (pc, 4) != 0x8040241) goto lose;         \
+      pc += 8;                 /* skip "copy 4,1; copy 30, 4" */       \
+      /* skip either "stw 1,0(4);addil L'fsize,30;ldo R'fsize(1),30"   \
+        or "stwm 1,fsize(30)" */                                       \
+      if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000)      \
+       pc += 12;                                                       \
+      else                                                             \
+       pc += 4;                                                        \
+      while (1)                                                                \
+       { this_insn = read_memory_integer(pc, 4);                       \
+         if (STW_P (this_insn)) /* stw */                              \
+           { regnum = GET_FIELD (this_insn, 11, 15);                   \
+             if (!regnum) goto lose;                                   \
+             (frame_saved_regs).regs[regnum] = (frame_info)->frame +   \
+               extract_14 (this_insn);                                 \
+             pc += 4;                                                  \
+           }                                                           \
+         else if (ADDIL_P (this_insn)) /* addil */                     \
+           { int next_insn;                                            \
+             next_insn = read_memory_integer(pc + 4, 4);               \
+             if (STW_P (next_insn)) /* stw */                          \
+               { regnum = GET_FIELD (this_insn, 6, 10);                \
+                 if (!regnum) goto lose;                               \
+                 (frame_saved_regs).regs[regnum] = (frame_info)->frame +\
+                   (extract_21 (this_insn) << 11) + extract_14 (next_insn);\
+                 pc += 8;                                              \
+               }                                                       \
+             else                                                      \
+               break;                                                  \
+           }                                                           \
+         else                                                          \
+           { pc += 4;                                                  \
+             break;                                                    \
+           }                                                           \
+       }                                                               \
+      this_insn = read_memory_integer (pc, 4);                         \
+      if (LDO_P (this_insn))                                           \
+       { next_addr = (frame_info)->frame + extract_14 (this_insn);     \
+         pc += 4;                                                      \
+       }                                                               \
+      else if (ADDIL_P (this_insn))                                    \
+       { next_addr = (frame_info)->frame + (extract_21 (this_insn) << 11)\
+           + extract_14 (read_memory_integer (pc + 4, 4));             \
+           pc += 8;                                                    \
+         }                                                             \
+      while (1)                                                                \
+       { this_insn = read_memory_integer (pc, 4);                      \
+         if ((this_insn & 0xfc001fe0) == 0x2c001220) /* fstds,ma */    \
+           { regnum = GET_FIELD (this_insn, 27, 31);                   \
+             (frame_saved_regs).regs[regnum + FP0_REGNUM] = next_addr; \
+             next_addr += 8;                                           \
+           }                                                           \
+         else                                                          \
+           break;                                                      \
+       }                                                               \
+    lose:                                                              \
+      (frame_saved_regs).regs[FP_REGNUM] = (frame_info)->frame;                \
+      (frame_saved_regs).regs[SP_REGNUM] = (frame_info)->frame -4;     \
+    }}
+\f
+/* Things needed for making the inferior call functions.  */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME \
+{ register CORE_ADDR sp = read_register (SP_REGNUM);                   \
+  register int regnum;                                                 \
+  int int_buffer;                                                      \
+  double freg_buffer;                                                  \
+  /* Space for "arguments"; the RP goes in here. */                    \
+  sp += 48;                                                            \
+  int_buffer = read_register (RP_REGNUM) | 0x3;                                \
+  write_memory (sp - 20, &int_buffer, 4);                              \
+  int_buffer = read_register (FP_REGNUM);                              \
+  write_memory (sp, &int_buffer, 4);                                   \
+  write_register (FP_REGNUM, sp);                                      \
+  sp += 4;                                                             \
+  for (regnum = 1; regnum < 31; regnum++)                              \
+    if (regnum != RP_REGNUM && regnum != FP_REGNUM)                    \
+      sp = push_word (sp, read_register (regnum));                     \
+  for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++)               \
+    { read_register_bytes (REGISTER_BYTE (regnum), &freg_buffer, 8);   \
+      sp = push_bytes (sp, &freg_buffer, 8);}                          \
+  sp = push_word (sp, read_register (IPSW_REGNUM));                    \
+  sp = push_word (sp, read_register (SAR_REGNUM));                     \
+  sp = push_word (sp, read_register (PCOQ_TAIL_REGNUM));               \
+  sp = push_word (sp, read_register (PCSQ_TAIL_REGNUM));               \
+  write_register (SP_REGNUM, sp);}
+
+/* Discard from the stack the innermost frame, 
+   restoring all saved registers.  */
+#define POP_FRAME  \
+{ register FRAME frame = get_current_frame ();                         \
+  register CORE_ADDR fp;                                               \
+  register int regnum;                                                 \
+  struct frame_saved_regs fsr;                                         \
+  struct frame_info *fi;                                               \
+  double freg_buffer;                                                  \
+  fi = get_frame_info (frame);                                         \
+  fp = fi->frame;                                                      \
+  get_frame_saved_regs (fi, &fsr);                                     \
+  for (regnum = 31; regnum > 0; regnum--)                              \
+    if (fsr.regs[regnum])                                              \
+      write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
+  for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--)                 \
+    if (fsr.regs[regnum])                                              \
+      { read_memory (fsr.regs[regnum], &freg_buffer, 8);               \
+        write_register_bytes (REGISTER_BYTE (regnum), &freg_buffer, 8); }\
+  if (fsr.regs[IPSW_REGNUM])                                           \
+    write_register (IPSW_REGNUM,                                       \
+                   read_memory_integer (fsr.regs[IPSW_REGNUM], 4));    \
+  if (fsr.regs[SAR_REGNUM])                                            \
+    write_register (SAR_REGNUM,                                                \
+                   read_memory_integer (fsr.regs[SAR_REGNUM], 4));     \
+  if (fsr.regs[PCOQ_TAIL_REGNUM])                                      \
+    write_register (PCOQ_TAIL_REGNUM,                                  \
+                   read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4));\
+  if (fsr.regs[PCSQ_TAIL_REGNUM])                                      \
+    write_register (PCSQ_TAIL_REGNUM,                                  \
+                   read_memory_integer (fsr.regs[PCSQ_TAIL_REGNUM], 4));\
+  write_register (FP_REGNUM, read_memory_integer (fp, 4));      \
+  write_register (SP_REGNUM, fp + 8);                           \
+  flush_cached_frames ();                                       \
+  set_current_frame (create_new_frame (read_register (FP_REGNUM),\
+                                       read_pc ())); }
+
+/* This sequence of words is the instructions
+
+; Call stack frame has already been built by gdb. Since we could be calling 
+; a varargs function, and we do not have the benefit of a stub to put things in
+; the right place, we load the first 4 word of arguments into both the general
+; and fp registers.
+call_dummy
+       ldw -36(sp), arg0
+       ldw -40(sp), arg1
+       ldw -44(sp), arg2
+       ldw -48(sp), arg3
+       ldo -36(sp), r1
+       fldws 0(0, r1), fr4
+       fldds -4(0, r1), fr5
+       fldws -8(0, r1), fr6
+       fldds -12(0, r1), fr7
+       ldil 0, r22                     ; target will be placed here.
+       ldo 0(r22), r22
+       ldsid (0,r22), r3
+       ldil 0, r1                      ; _sr4export will be placed here.
+       ldo 0(r1), r1
+       ldsid (0,r1), r4
+       combt,=,n r3, r4, text_space    ; If target is in data space, do a
+       ble 0(sr5, r22)                 ; "normal" procedure call
+       copy r31, r2
+       break 4, 8 
+text_space                             ; Otherwise, go through _sr4export,
+       ble (sr4, r1)                   ; which will return back here.
+       stw 31,-24(r30)
+       break 4, 8
+
+   The dummy decides if the target is in text space or data space. If
+   it's in data space, there's no problem because the target can
+   return back to the dummy. However, if the target is in text space,
+   the dummy calls the secret, undocumented routine _sr4export, which
+   calls a function in text space and can return to any space. Instead
+   of including fake instructions to represent saved registers, we
+   know that the frame is associated with the call dummy and treat it
+   specially. */ 
+   
+#define CALL_DUMMY { 0x4bda3fb9, 0x4bd93fb1, 0x4bd83fa9, 0x4bd73fa1,   \
+                    0x37c13fb9, 0x24201004, 0x2c391005, 0x24311006,    \
+                    0x2c291007, 0x22c00000, 0x36d60000, 0x02c010a3,    \
+                    0x20200000, 0x34210000, 0x002010a4, 0x80832012,    \
+                    0xe6c06000, 0x081f0242, 0x00010004, 0xe4202000,    \
+                    0x6bdf3fd1, 0x00010004}
+
+#define CALL_DUMMY_LENGTH 88
+#define CALL_DUMMY_START_OFFSET 0
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.  */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ static CORE_ADDR sr4export_address = 0;                              \
+                                                                       \
+  if (!sr4export_address)                                              \
+    {                                                                  \
+      struct minimal_symbol *msymbol;                                   \
+      msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL);\
+      if (msymbol = NULL)                                               \
+       error ("Can't find an address for _sr4export trampoline");      \
+      else                                                             \
+       sr4export_address = msymbol -> address;                         \
+    }                                                                  \
+  dummyname[9] = deposit_21 (fun >> 11, dummyname[9]);                 \
+  dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]);           \
+  dummyname[12] = deposit_21 (sr4export_address >> 11, dummyname[12]); \
+  dummyname[13] = deposit_14 (sr4export_address & MASK_11, dummyname[13]);\
+}
+
+/* Write the PC to a random value.
+   On PA-RISC, we need to be sure that the PC space queue is correct. */
+
+#define WRITE_PC(addr) \
+{ int space_reg, space = ((addr) >> 30);               \
+  int space_val;                                       \
+  if (space == 0)                                      \
+    space_reg = 43;            /* Space reg sr4 */     \
+  else if (space == 1)                                 \
+    space_reg = 48;            /* Space reg sr5*/      \
+  else                                                 \
+    error ("pc = %x is in illegal space.", addr);      \
+  space_val = read_register (space_reg);               \
+  write_register (PCOQ_HEAD_REGNUM, addr);             \
+  write_register (PCSQ_HEAD_REGNUM, space_val);                \
+  write_register (PCOQ_TAIL_REGNUM, addr);             \
+  write_register (PCSQ_TAIL_REGNUM, space_val);}
+
+
+
+
+
+
diff --git a/gdb/xm-hppabsd.h b/gdb/xm-hppabsd.h
new file mode 100644 (file)
index 0000000..08ff507
--- /dev/null
@@ -0,0 +1,49 @@
+/* Parameters for execution on a Hewlett-Packard PA-RISC machine, running 
+   HPUX or BSD.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc. 
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Describe the endian nature of this machine.  */
+#define BITS_BIG_ENDIAN 1
+#define BYTES_BIG_ENDIAN 1
+#define WORDS_BIG_ENDIAN 1
+
+/* Avoid "INT_MIN redefined" warnings -- by defining it here, exactly
+   the same as in the system <machine/machtypes.h> file.  */
+#undef  INT_MIN
+#define INT_MIN         0x80000000
+
+#ifndef hp800
+#define USG
+#endif
+
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+    sp = hp_push_arguments(nargs, args, sp, struct_return, struct_addr)
+
+#define KERNEL_U_ADDR 0
+
+/* What a coincidence! */
+#define REGISTER_U_ADDR(addr, blockend, regno)                         \
+{ addr = (int)(blockend) + REGISTER_BYTE (regno);}
+
+
+#define U_REGS_OFFSET 0
diff --git a/gdb/xm-hppahpux.h b/gdb/xm-hppahpux.h
new file mode 100644 (file)
index 0000000..5dce560
--- /dev/null
@@ -0,0 +1,50 @@
+/* Parameters for execution on a Hewlett-Packard PA-RISC machine, running 
+   HPUX or BSD.
+   Copyright (C) 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc. 
+
+   Contributed by the Center for Software Science at the
+   University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Describe the endian nature of this machine.  */
+#define BITS_BIG_ENDIAN 1
+#define BYTES_BIG_ENDIAN 1
+#define WORDS_BIG_ENDIAN 1
+
+/* Avoid "INT_MIN redefined" warnings -- by defining it here, exactly
+   the same as in the system <machine/machtypes.h> file.  */
+#undef  INT_MIN
+#define INT_MIN         0x80000000
+
+#ifndef hp800
+#define USG
+#endif
+
+#define HAVE_TERMIO
+
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+    sp = hp_push_arguments(nargs, args, sp, struct_return, struct_addr)
+
+#define KERNEL_U_ADDR 0
+
+/* What a coincidence! */
+#define REGISTER_U_ADDR(addr, blockend, regno)                         \
+{ addr = (int)(blockend) + REGISTER_BYTE (regno);}
+
+
+#define U_REGS_OFFSET 0