Initial versions of sparc64 port.
authorDavid Edelsohn <dje.gcc@gmail.com>
Thu, 8 Jul 1993 03:19:46 +0000 (03:19 +0000)
committerDavid Edelsohn <dje.gcc@gmail.com>
Thu, 8 Jul 1993 03:19:46 +0000 (03:19 +0000)
Some stuff can be removed when sparc-tdep.c is upgraded.

gdb/.Sanitize
gdb/remote-sp64sim.c [new file with mode: 0644]
gdb/sp64-tdep.c [new file with mode: 0644]

index a770ebf9ec780bb1160b425fbadf29f8bca9cd5f..206e31483b3aca77ed4c2da6aca83d62c9bbdb8e 100644 (file)
 
 Do-first:
 
+if ( echo $* | grep keep\-v9 > /dev/null ) ; then
+       keep_these_too="sp64-tdep.c remote-sp64sim.c"
+fi
+
 # All files listed between the "Things-to-keep:" line and the
 # "Files-to-sed:" line will be kept.  All other files will be removed.
 # Directories listed in this section will have their own Sanitize
diff --git a/gdb/remote-sp64sim.c b/gdb/remote-sp64sim.c
new file mode 100644 (file)
index 0000000..2c15272
--- /dev/null
@@ -0,0 +1,420 @@
+/* Remote debugging interface for SPARC64 Simulator.
+   Copyright 1992 Free Software Foundation, Inc.
+   Contributed by Cygnus Support.  Hacked from Steve Chamberlain's Z8000 work
+   by Doug Evans. (dje@cygnus.com).
+
+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 "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "sp64sim.h"
+
+/* Naming conventions:
+
+   simif_xxx are internal objects that describe top level interfaces to the
+   simulator (simif for SIMulator InterFace).
+
+   sim_xxx are external counterparts to the simif_xxx objects that must be
+   provided by the simulator.  */
+
+/* Forward data declarations */
+extern struct target_ops simif_ops;
+
+int simif_verbose = 0; /* available to the simulator to use */
+
+static int program_loaded = 0;
+
+static void dump_mem ();
+
+static void
+simif_fetch_register (regno)
+int regno;
+{
+  if (regno == -1) 
+    {
+      if (simif_verbose)
+       printf_filtered ("simif_fetch_register: %d\n", regno);
+      for (regno = 0; regno < 16; regno++)
+       simif_fetch_register (regno);
+    }
+  else
+    {
+      char buf[MAX_REGISTER_RAW_SIZE];
+
+      sim_fetch_register (regno, buf);
+      supply_register (regno, buf);
+      if (simif_verbose)
+       {
+         printf_filtered ("simif_fetch_register: %d", regno);
+         dump_mem (buf, sizeof (REGISTER_TYPE));
+       }
+    }
+}
+
+static void
+simif_store_register (regno)
+int regno;
+{
+  if (regno  == -1) 
+    {
+      if (simif_verbose)
+       printf_filtered ("simif_store_register: %d\n", regno);
+      for (regno = 0; regno < 16; regno++)
+       simif_store_register (regno);
+    }
+  else 
+    {
+      char value[sizeof (REGISTER_TYPE)];
+
+      read_register_gen (regno, value);
+      SWAP_TARGET_AND_HOST (value, sizeof (REGISTER_TYPE));
+      sim_store_register (regno, value);
+      if (simif_verbose)
+       {
+         printf_filtered ("simif_store_register: %d", regno);
+         dump_mem (value, sizeof (REGISTER_TYPE));
+       }
+    }
+}
+
+static void
+simif_kill (arg,from_tty)
+char   *arg;
+int    from_tty;
+{
+  if (simif_verbose)
+    printf_filtered ("simif_kill: arg \"%s\"\n", arg);
+
+  sim_kill (); /* close fd's, remove mappings */
+  inferior_pid = 0;
+}
+
+/* Download a file specified in 'args', to the sim. */
+
+static void
+simif_load (args, fromtty)
+     char *args;
+     int fromtty;
+{
+  bfd  *abfd;
+
+  if (simif_verbose)
+    printf_filtered ("simif_load: args \"%s\"\n", args);
+
+  inferior_pid = 0;  
+  program_loaded = 0;
+  /* FIXME: a.out should be a config parm and/or an arg.  */
+  abfd = bfd_openr (args,"a.out-sunos-big");
+
+  if (!abfd) 
+    error ("Unable to open file %s.", args);
+
+  if (bfd_check_format (abfd, bfd_object) ==0) 
+    error ("File is not an object file.");
+
+  if (sim_load (abfd, args) != 0)
+    return;
+
+  program_loaded = 1;
+
+  /* It is sim_load()'s job to set this.  */
+  /*sim_set_pc (abfd->start_address); - can't do 'cus we use RMTVaddr */
+}
+
+/* This is called not only when we first attach, but also when the
+   user types "run" after having attached.  */
+
+static void
+simif_create_inferior (exec_file, args, env)
+     char *exec_file;
+     char *args;
+     char **env;
+{
+  int len,entry_pt;
+  char *arg_buf,**argv;
+
+  if (! program_loaded)
+    error ("No program loaded.");
+
+  if (simif_verbose)
+    printf_filtered ("simif_create_inferior: exec_file \"%s\", args \"%s\"\n",
+      exec_file, args);
+
+  if (exec_file == 0 || exec_bfd == 0)
+   error ("No exec file specified.");
+
+  entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+  simif_kill (NULL, NULL);      
+  remove_breakpoints ();
+  init_wait_for_inferior ();
+
+  len = 5 + strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10;
+  arg_buf = (char *) alloca (len);
+  arg_buf[0] = '\0';
+  strcat (arg_buf, exec_file);
+  strcat (arg_buf, " ");
+  strcat (arg_buf, args);
+  argv = buildargv (arg_buf);
+  make_cleanup (freeargv, (char *) argv);
+  sim_set_args (argv, env);
+
+  inferior_pid = 42;
+  insert_breakpoints ();       /* Needed to get correct instruction in cache */
+  proceed (entry_pt, -1, 0);
+}
+
+/* Called when selecting the simulator. EG: (gdb) target sim name.
+   NAME unused at present. */
+
+static void
+simif_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  if (simif_verbose)
+    printf_filtered ("simif_open: name \"%s\"\n", name);
+
+  if (sim_init (name) != 0)
+    {
+      error ("Unable to initialize simulator (insufficient memory?).");
+      return;
+    }
+
+  push_target (&simif_ops);
+  target_fetch_registers (-1);
+
+  printf_filtered ("Connected to the simulator.\n");
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+simif_close (quitting)
+     int quitting;
+{
+  if (simif_verbose)
+    printf_filtered ("simif_close: quitting %d\n", quitting);
+
+  program_loaded = 0;
+
+  /* FIXME: Need to call sim_close() to close all files and
+     delete all mappings. */
+}
+
+/* Terminate the open connection to the remote debugger.
+   Use this when you want to detach and do something else
+   with your gdb.  */
+
+static void
+simif_detach (args,from_tty)
+     char *args;
+     int from_tty;
+{
+  if (simif_verbose)
+    printf_filtered ("simif_detach: args \"%s\"\n", args);
+
+  pop_target ();               /* calls simif_close to do the real work */
+  if (from_tty)
+    printf_filtered ("Ending simulator %s debugging\n", target_shortname);
+}
+/* Tell the remote machine to resume.  */
+/* FIXME: What are A and B?  */
+
+static void
+simif_resume (a,b)
+{
+  if (simif_verbose)
+    printf_filtered ("simif_resume: %d/%d\n", a, b);
+
+  sim_resume (a, b);
+}
+
+/* Wait until the remote machine stops, then return,
+   storing status in STATUS just as `wait' would.  */
+
+static int
+simif_wait (status)
+     WAITTYPE *status;
+{
+  if (simif_verbose)
+    printf_filtered ("simif_wait: ");
+#if 1
+  *status = sim_stop_signal ();
+#else
+  WSETSTOP (*status, sim_stop_signal ());
+#endif
+  if (simif_verbose)
+    printf_filtered ("status %d\n", *status);
+  return 0;
+}
+
+/* Get ready to modify the registers array.  On machines which store
+   individual registers, this doesn't need to do anything.  On machines
+   which store all the registers in one fell swoop, this makes sure
+   that registers contains all the registers from the program being
+   debugged.  */
+
+static void
+simif_prepare_to_store ()
+{
+  /* Do nothing, since we can store individual regs */
+}
+
+static int
+simif_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+     int write;
+     struct target_ops *target;                        /* ignored */
+{
+  if (simif_verbose)
+  {
+    printf_filtered ("simif_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n",
+      myaddr, memaddr, len, write);
+    if (simif_verbose && write)
+      dump_mem(myaddr, len);
+  }
+
+  if (! program_loaded)
+    error ("No program loaded.");
+
+  if (write)
+  {
+    len = sim_write (memaddr, myaddr, len);
+  }
+  else 
+  {
+    len = sim_read (memaddr, myaddr, len);
+    if (simif_verbose && len  > 0)
+      dump_mem(myaddr, len);
+  } 
+  return len;
+}
+
+static void
+simif_files_info ()
+{
+  char *file = "nothing";
+
+  if (exec_bfd)
+    file = bfd_get_filename (exec_bfd);
+
+  if (simif_verbose)
+    printf_filtered ("simif_files_info: file \"%s\"\n", file);
+
+  if (exec_bfd)
+    printf_filtered ("\tAttached to %s running program %s\n",
+      target_shortname, file);
+}
+
+/* Clear the sims notion of what the break points are */
+static void
+simif_mourn () 
+{ 
+  if (simif_verbose)
+    printf_filtered ("simif_mourn:\n");
+
+  remove_breakpoints ();
+  generic_mourn_inferior ();
+}
+
+/* Define the target subroutine names */
+
+struct target_ops simif_ops = 
+{
+  "sim", "SPARC64 Simulator",
+  "Use the SPARC64 Simulator",
+  simif_open, simif_close, 
+  0, simif_detach, simif_resume, simif_wait, /* attach */
+  simif_fetch_register, simif_store_register,
+  simif_prepare_to_store,
+  simif_xfer_inferior_memory, 
+  simif_files_info,
+  0, 0,                                /* Breakpoints */
+  0, 0, 0, 0, 0,               /* Terminal handling */
+  simif_kill,                  /* FIXME, kill */
+  simif_load, 
+  0,                           /* lookup_symbol */
+  simif_create_inferior,       /* create_inferior */ 
+  simif_mourn,                 /* mourn_inferior FIXME */
+  0,                           /* can_run */
+  0,                           /* notice_signals */
+  process_stratum, 0,          /* next */
+  1, 1, 1, 1, 1,               /* all mem, mem, stack, regs, exec */
+  0, 0,                                /* Section pointers */
+  OPS_MAGIC,                   /* Always the last thing */
+};
+
+static void
+simif_snoop ()
+{
+  simif_verbose = ! simif_verbose;  
+  if (simif_verbose)
+    printf_filtered ("Snoop enabled\n");
+  else
+    printf_filtered ("Snoop disabled\n");
+
+}
+
+/***********************************************************************/
+
+void
+_initialize_remote_sim ()
+{
+  add_target (&simif_ops);
+  add_com ("snoop", class_obscure, simif_snoop,
+          "Show what commands are going to the simulator");
+}
+
+static void
+dump_mem (buf, len)
+     char *buf;
+     int len;
+{
+  if (len <= 8)
+  {
+    if (len == 8 || len == 4)
+    {
+      long l[2];
+      memcpy (l, buf, len);
+      printf_filtered ("\t0x%x", l[0]);
+      printf_filtered (len == 8 ? " 0x%x\n" : "\n", l[1]);
+    }
+    else
+    {
+      int i;
+      printf_filtered ("\t");
+      for (i = 0; i < len; i++)
+       printf_filtered ("0x%x ", buf[i]);
+      printf_filtered ("\n");
+    }
+  }
+}
diff --git a/gdb/sp64-tdep.c b/gdb/sp64-tdep.c
new file mode 100644 (file)
index 0000000..d202e25
--- /dev/null
@@ -0,0 +1,314 @@
+/* Target-dependent code for the SPARC 64 for GDB, the GNU debugger.
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Contributed by Doug Evans (dje@cygnus.com).
+
+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 "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "obstack.h"
+#include "target.h"
+#include "ieee-float.h"
+
+/*#include "symfile.h" /* for objfiles.h */
+/*#include "objfiles.h" /* for find_pc_section */
+
+/* This file contains replacements and additions to sparc-tdep.c only.
+   Some of this code has been written for a day when we can merge at least
+   some of this with sparc-tdep.c.  Macro TARGET_SPARC64 exists to allow some
+   code to potentially be used by both.  */
+
+#define TARGET_SPARC64 1       /* later make a config parm or some such */
+
+/* From infrun.c */
+extern int stop_after_trap;
+
+/* Branches with prediction are treated like their non-predicting cousins.  */
+/* FIXME: What about floating point branches?  */
+
+typedef enum
+{
+  Error, not_branch, bicc, bicca, ba, baa, ticc, ta, done_retry
+} branch_type;
+
+/* Simulate single-step ptrace call for sun4.  Code written by Gary
+   Beihl (beihl@mcc.com).  */
+
+/* npc4 and next_pc describe the situation at the time that the
+   step-breakpoint was set, not necessary the current value of NPC_REGNUM.  */
+static CORE_ADDR next_pc, npc4, target;
+static int brknpc4, brktrg;
+typedef char binsn_quantum[BREAKPOINT_MAX];
+static binsn_quantum break_mem[3];
+
+/* Non-zero if we just simulated a single-step ptrace call.  This is
+   needed because we cannot remove the breakpoints in the inferior
+   process until after the `wait' in `wait_for_inferior'.  Used for
+   sun4. */
+
+int one_stepped;
+
+/* sparc64_single_step() is called just before we want to resume the inferior,
+   if we want to single-step it but there is no hardware or kernel single-step
+   support (as on all SPARCs).  We find all the possible targets of the
+   coming instruction and breakpoint them.
+
+   single_step is also called just after the inferior stops.  If we had
+   set up a simulated single-step, we undo our damage.  */
+
+/* FIXME: When the code is releasable, sparc's single step could become this
+   one, removing the duplication.  */
+
+void
+sparc64_single_step (ignore)
+     int ignore; /* pid, but we don't need it */
+{
+  branch_type br, isbranch();
+  CORE_ADDR pc;
+  long pc_instruction;
+
+  if (!one_stepped)
+    {
+      /* Always set breakpoint for NPC.  */
+      next_pc = read_register (NPC_REGNUM);
+      npc4 = next_pc + 4; /* branch not taken */
+
+      target_insert_breakpoint (next_pc, break_mem[0]);
+      /* printf ("set break at %x\n",next_pc); */
+
+      pc = read_register (PC_REGNUM);
+      pc_instruction = read_memory_integer (pc, sizeof(pc_instruction));
+      br = isbranch (pc_instruction, pc, &target);
+      brknpc4 = brktrg = 0;
+
+      if (br == bicca)
+       {
+         /* Conditional annulled branch will either end up at
+            npc (if taken) or at npc+4 (if not taken).
+            Trap npc+4.  */
+         brknpc4 = 1;
+         target_insert_breakpoint (npc4, break_mem[1]);
+       }
+      else if ((br == baa && target != next_pc)
+              || (TARGET_SPARC64 && br == done_retry))
+       {
+         /* Unconditional annulled branch will always end up at
+            the target.  */
+         brktrg = 1;
+         target_insert_breakpoint (target, break_mem[2]);
+       }
+
+      /* We are ready to let it go */
+      one_stepped = 1;
+      return;
+    }
+  else
+    {
+      /* Remove breakpoints */
+      target_remove_breakpoint (next_pc, break_mem[0]);
+
+      if (brknpc4)
+       target_remove_breakpoint (npc4, break_mem[1]);
+
+      if (brktrg)
+       target_remove_breakpoint (target, break_mem[2]);
+
+      one_stepped = 0;
+    }
+}
+\f
+/* FIXME: sparc64_frame_chain() is temporary.  sparc_frame_chain() can
+   be fixed to support both of us.  */
+
+#define        FRAME_SAVED_L0  0                         /* Byte offset from SP */
+#define        FRAME_SAVED_I0  (8*REGISTER_RAW_SIZE (0)) /* Byte offset from SP */
+
+CORE_ADDR
+sparc64_frame_chain (thisframe)
+     FRAME thisframe;
+{
+  REGISTER_TYPE retval;
+  int err;
+  CORE_ADDR addr;
+
+  addr = thisframe->frame + FRAME_SAVED_I0 +
+        REGISTER_RAW_SIZE (0) * (FP_REGNUM - I0_REGNUM);
+  err = target_read_memory (addr, (char *) &retval, sizeof (REGISTER_TYPE));
+  if (err)
+    return 0;
+  SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+  return retval;
+}
+
+CORE_ADDR
+sparc64_extract_struct_value_address (regbuf)
+     char regbuf[REGISTER_BYTES];
+{
+  CORE_ADDR addr;
+
+  /* FIXME: We assume a non-leaf function.  */
+  addr = read_register (I0_REGNUM);
+  return addr;
+}
+
+/* Find the pc saved in frame FRAME.  */
+/* FIXME: This function can be removed when sparc_frame_saved_pc
+   handles us too.  */
+
+CORE_ADDR
+sparc64_frame_saved_pc (frame)
+     FRAME frame;
+{
+  int err;
+  REGISTER_TYPE retval;
+  CORE_ADDR addr,prev_pc;
+
+  if (get_current_frame () == frame)  /* FIXME, debug check. Remove >=gdb-4.6 */
+    {
+      if (read_register (SP_REGNUM) != frame->bottom) abort();
+    }
+
+  addr = frame->bottom + FRAME_SAVED_I0 +
+        REGISTER_RAW_SIZE (0) * (I7_REGNUM - I0_REGNUM);
+  err = target_read_memory (addr, (char *) &retval, sizeof (REGISTER_TYPE));
+  if (err)
+    return 0;
+  SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+
+  /* CORE_ADDR isn't always the same size as REGISTER_TYPE, so convert.  */
+
+  prev_pc = (CORE_ADDR) retval;
+  return PC_ADJUST (prev_pc);
+}
+
+/* Check instruction at ADDR to see if it is an annulled branch or other
+   instruction whose npc isn't pc+4 (eg: trap, done, retry).
+   All other instructions will go to NPC or will trap.
+   Set *TARGET if we find a candidate branch; set to zero if not. */
+   
+branch_type
+isbranch (instruction, addr, target)
+     long instruction;
+     CORE_ADDR addr, *target;
+{
+  branch_type val = not_branch;
+  long int offset;             /* Must be signed for sign-extend.  */
+  union
+    {
+      unsigned long int code;
+      struct
+       {
+         unsigned int op:2;
+         unsigned int a:1;
+         unsigned int cond:4;
+         unsigned int op2:3;
+         unsigned int disp22:22;
+       } b;
+      struct
+       {
+         unsigned int op:2;
+         unsigned int a:1;
+         unsigned int cond:4;
+         unsigned int op2:3;
+         unsigned int cc:2;
+         unsigned int p:1;
+         unsigned int disp19:19;
+       } bp;
+      struct
+       {
+         unsigned int op:2;
+         unsigned int a:1;
+         unsigned int zero:1;
+         unsigned int rcond:3;
+         unsigned int op2:3;
+         unsigned int disp16hi:2;
+         unsigned int p:1;
+         unsigned int rs1:5;
+         unsigned int disp16lo:14;
+       } bpr;
+      struct
+       {
+         unsigned int op:2;
+         unsigned int fcn:5;
+         unsigned int op3:6;
+         unsigned int reserved:19;
+       } dr;
+    } insn;
+
+  *target = 0;
+  insn.code = instruction;
+
+  if (insn.b.op == 0
+      && (insn.b.op2 == 1 || insn.b.op2 == 2 || insn.b.op2 ==3
+         || insn.b.op2 == 5 || insn.b.op2 == 6))
+    {
+      if (insn.b.cond == 8)
+       val = insn.b.a ? baa : ba;
+      else
+       val = insn.b.a ? bicca : bicc;
+      switch (insn.b.op2)
+       {
+       case 1: /* bpcc */
+         offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
+         break;
+       case 2: /* bicc */
+         offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
+         break;
+       case 3: /* bpr */
+         offset = 4 * ((int) ((insn.bpr.disp16hi << 10)
+                              || (insn.bpr.disp16lo << 18)) >> 13);
+         break;
+       case 5: /* fbpfcc */
+         offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
+         break;
+       case 6: /* fbfcc */
+         offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
+         break;
+       }
+      *target = addr + offset;
+    }
+  else if (insn.dr.op == 2 && insn.dr.op3 == 62)
+    {
+      if (insn.dr.fcn == 0)
+       {
+         /* done */
+         *target = read_register (TNPC_REGNUM);
+         val = done_retry;
+       }
+      else if (insn.dr.fcn == 1)
+       {
+         /* retry */
+         *target = read_register (TPC_REGNUM);
+         val = done_retry;
+       }
+    }
+
+  return val;
+}
+
+/* We try to support 32 bit and 64 bit pointers.
+   We are called when the Shade target is selected by shadeif.c.  */
+
+int target_ptr_bit = 64;       /* default */
+
+void
+set_target_ptr_bit(ptr_bit)
+     int ptr_bit;
+{
+  target_ptr_bit = ptr_bit;
+}