]> Git Repo - binutils.git/blobdiff - gdb/sparc-tdep.c
Wed Oct 30 18:14:14 1996 Michael Snyder <[email protected]>
[binutils.git] / gdb / sparc-tdep.c
index 172f98d1a5b5374cc9c9265e76f0613f619407ca..bd85d28e219d154419c17c408d11fa41663e0269 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-dependent code for the SPARC for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -16,7 +16,7 @@ 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.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* ??? Support for calling functions from gdb in sparc64 is unfinished.  */
 
@@ -26,6 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "obstack.h"
 #include "target.h"
 #include "value.h"
+#include "bfd.h"
 
 #ifdef USE_PROC_FS
 #include <sys/procfs.h>
@@ -34,9 +35,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcore.h"
 
 #ifdef GDB_TARGET_IS_SPARC64
-#define NUM_SPARC_FPREGS 64
+#define FP_REGISTER_BYTES (64 * 4)
 #else
-#define NUM_SPARC_FPREGS 32
+#define FP_REGISTER_BYTES (32 * 4)
+#endif
+
+/* If not defined, assume 32 bit sparc.  */
+#ifndef FP_MAX_REGNUM
+#define FP_MAX_REGNUM (FP0_REGNUM + 32)
 #endif
 
 #define SPARC_INTREG_SIZE (REGISTER_RAW_SIZE (G0_REGNUM))
@@ -537,7 +543,7 @@ isbranch (instruction, addr, target)
        val = X_A (instruction) ? baa : ba;
       else
        val = X_A (instruction) ? bicca : bicc;
-      switch (X_OP (instruction))
+      switch (X_OP2 (instruction))
        {
        case 2:
        case 6:
@@ -607,6 +613,22 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
     *optimized = 0;
 
   addr = 0;
+
+  /* FIXME This code extracted from infcmd.c; should put elsewhere! */
+  if (frame == NULL)
+    {
+      /* error ("No selected frame."); */
+      if (!target_has_registers)
+        error ("The program has no registers now.");
+      if (selected_frame == NULL) 
+        error ("No selected frame.");
+      /* Try to use selected frame */
+      frame = get_prev_frame (selected_frame);  
+      if (frame == 0)
+        error ("Cmd not meaningful in the outermost frame."); 
+    }
+
+
   frame1 = frame->next;
   while (frame1 != NULL)
     {
@@ -614,20 +636,36 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
                         read_register (SP_REGNUM))
          && frame1->pc <= FRAME_FP (frame1))
        {
-         /* Dummy frame.  All but the window regs are in there somewhere. */
-         /* FIXME: The offsets are wrong for sparc64 (eg: 0xa0).  */
+         /* Dummy frame.  All but the window regs are in there somewhere.
+            The window registers are saved on the stack, just like in a
+            normal frame.  */
          if (regnum >= G1_REGNUM && regnum < G1_REGNUM + 7)
            addr = frame1->frame + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
-             - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE);
+             - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE);
          else if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
-           addr = frame1->frame + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
-             - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE);
-         else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + NUM_SPARC_FPREGS)
+           addr = (frame1->prev->bottom
+                   + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+                   + FRAME_SAVED_I0);
+         else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8)
+           addr = (frame1->prev->bottom
+                   + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+                   + FRAME_SAVED_L0);
+         else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
+           addr = frame1->frame + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE
+             - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE);
+#ifdef FP0_REGNUM
+         else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + 32)
            addr = frame1->frame + (regnum - FP0_REGNUM) * 4
-             - (NUM_SPARC_FPREGS * 4);
+             - (FP_REGISTER_BYTES);
+#ifdef GDB_TARGET_IS_SPARC64
+         else if (regnum >= FP0_REGNUM + 32 && regnum < FP_MAX_REGNUM)
+           addr = frame1->frame + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
+             - (FP_REGISTER_BYTES);
+#endif
+#endif /* FP0_REGNUM */
          else if (regnum >= Y_REGNUM && regnum < NUM_REGS)
            addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
-             - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE);
+             - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
        }
       else if (frame1->flat)
        {
@@ -715,8 +753,13 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
 #endif
 
 /* See tm-sparc.h for how this is calculated.  */
+#ifdef FP0_REGNUM
 #define DUMMY_STACK_REG_BUF_SIZE \
 (((8+8+8) * SPARC_INTREG_SIZE) + (32 * REGISTER_RAW_SIZE (FP0_REGNUM)))
+#else
+#define DUMMY_STACK_REG_BUF_SIZE \
+(((8+8+8) * SPARC_INTREG_SIZE) )
+#endif /* FP0_REGNUM */
 #define DUMMY_STACK_SIZE (DUMMY_STACK_REG_BUF_SIZE + DUMMY_REG_SAVE_OFFSET)
 
 void
@@ -743,11 +786,11 @@ sparc_push_dummy_frame ()
                       &register_temp[16 * SPARC_INTREG_SIZE],
                       SPARC_INTREG_SIZE * 8);
 
-  /* ??? The 32 here should be NUM_SPARC_FPREGS, but until we decide what
-     REGISTER_RAW_SIZE should be for fp regs, it's left as is.  */
+#ifdef FP0_REGNUM
   read_register_bytes (REGISTER_BYTE (FP0_REGNUM),
                       &register_temp[24 * SPARC_INTREG_SIZE],
-                      REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+                      FP_REGISTER_BYTES);
+#endif /* FP0_REGNUM */
 
   sp -= DUMMY_STACK_SIZE;
 
@@ -820,19 +863,27 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
       for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
-           - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE);
+           - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE);
       for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
-           - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE);
+           - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE);
+#ifdef FP0_REGNUM
       for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - FP0_REGNUM) * 4
-           - (NUM_SPARC_FPREGS * 4);
+           - (FP_REGISTER_BYTES);
+#ifdef GDB_TARGET_IS_SPARC64
+      for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
+       saved_regs_addr->regs[regnum] =
+         frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
+           - (FP_REGISTER_BYTES);
+#endif
+#endif /* FP0_REGNUM */
       for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
        saved_regs_addr->regs[regnum] =
          frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE - 0xe0;
-           - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE);
+           - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
       frame_addr = fi->bottom ?
        fi->bottom : read_register (SP_REGNUM);
     }
@@ -908,11 +959,12 @@ sparc_pop_frame ()
   int regnum;
 
   sparc_frame_find_saved_regs (frame, &fsr);
+#ifdef FP0_REGNUM
   if (fsr.regs[FP0_REGNUM])
     {
-      read_memory (fsr.regs[FP0_REGNUM], raw_buffer, NUM_SPARC_FPREGS * 4);
+      read_memory (fsr.regs[FP0_REGNUM], raw_buffer, FP_REGISTER_BYTES);
       write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
-                           raw_buffer, NUM_SPARC_FPREGS * 4);
+                           raw_buffer, FP_REGISTER_BYTES);
     }
 #ifndef GDB_TARGET_IS_SPARC64
   if (fsr.regs[FPS_REGNUM])
@@ -926,6 +978,7 @@ sparc_pop_frame ()
       write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4);
     }
 #endif
+#endif /* FP0_REGNUM */
   if (fsr.regs[G1_REGNUM])
     {
       read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE);
@@ -1043,7 +1096,7 @@ sparc_pc_adjust(pc)
 
   err = target_read_memory (pc + 8, buf, sizeof(long));
   insn = extract_unsigned_integer (buf, 4);
-  if ((err == 0) && (insn & 0xfffffe00) == 0)
+  if ((err == 0) && (insn & 0xffc00000) == 0)
     return pc+12;
   else
     return pc+8;
@@ -1139,6 +1192,7 @@ prgregset_t *gregsetp;
 {
   register int regi;
   register prgreg_t *regp = (prgreg_t *) gregsetp;
+  static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
 
   /* GDB register numbers for Gn, On, Ln, In all match /proc reg numbers.  */
   for (regi = G0_REGNUM ; regi <= I7_REGNUM ; regi++)
@@ -1151,6 +1205,11 @@ prgregset_t *gregsetp;
   supply_register (PC_REGNUM, (char *) (regp + R_PC));
   supply_register (NPC_REGNUM,(char *) (regp + R_nPC));
   supply_register (Y_REGNUM,  (char *) (regp + R_Y));
+
+  /* Fill inaccessible registers with zero.  */
+  supply_register (WIM_REGNUM, zerobuf);
+  supply_register (TBR_REGNUM, zerobuf);
+  supply_register (CPS_REGNUM, zerobuf);
 }
 
 void
@@ -1199,7 +1258,7 @@ prfpregset_t *fpregsetp;
   register int regi;
   char *from;
   
-  for (regi = FP0_REGNUM ; regi < FP0_REGNUM+32 ; regi++)
+  for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
     {
       from = (char *) &fpregsetp->pr_fr.pr_regs[regi-FP0_REGNUM];
       supply_register (regi, from);
@@ -1222,9 +1281,7 @@ int regno;
   char *to;
   char *from;
 
-  /* ??? The 32 should probably be NUM_SPARC_FPREGS, but again we're
-     waiting on what REGISTER_RAW_SIZE should be for fp regs.  */
-  for (regi = FP0_REGNUM ; regi < FP0_REGNUM + 32 ; regi++)
+  for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
     {
       if ((regno == -1) || (regno == regi))
        {
@@ -1354,17 +1411,50 @@ sparc_print_register_hook (regno)
 {
   unsigned LONGEST val;
 
-  if (((unsigned) (regno) - FP0_REGNUM < FP_MAX_REGNUM - FP0_REGNUM)
-       && ((regno) & 1) == 0)
+  /* Handle double/quad versions of lower 32 fp regs.  */
+  if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32
+      && (regno & 1) == 0)
+    {
+      char value[16];
+
+      if (!read_relative_register_raw_bytes (regno, value)
+         && !read_relative_register_raw_bytes (regno + 1, value + 4))
+       {
+         printf_unfiltered ("\t");
+         print_floating (value, builtin_type_double, gdb_stdout);
+       }
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+      if ((regno & 3) == 0)
+       {
+         if (!read_relative_register_raw_bytes (regno + 2, value + 8)
+             && !read_relative_register_raw_bytes (regno + 3, value + 12))
+           {
+             printf_unfiltered ("\t");
+             print_floating (value, builtin_type_long_double, gdb_stdout);
+           }
+       }
+#endif
+      return;
+    }
+
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+  /* Print upper fp regs as long double if appropriate.  */
+  if (regno >= FP0_REGNUM + 32 && regno < FP_MAX_REGNUM
+      /* We test for even numbered regs and not a multiple of 4 because
+        the upper fp regs are recorded as doubles.  */
+      && (regno & 1) == 0)
     {
-      char doublereg[8];               /* two float regs */
-      if (!read_relative_register_raw_bytes ((regno), doublereg))
+      char value[16];
+
+      if (!read_relative_register_raw_bytes (regno, value)
+         && !read_relative_register_raw_bytes (regno + 1, value + 8))
        {
-         printf_unfiltered("\t");
-         print_floating (doublereg, builtin_type_double, gdb_stdout);
+         printf_unfiltered ("\t");
+         print_floating (value, builtin_type_long_double, gdb_stdout);
        }
       return;
     }
+#endif
 
   /* FIXME: Some of these are priviledged registers.
      Not sure how they should be handled.  */
@@ -1460,4 +1550,5 @@ void
 _initialize_sparc_tdep ()
 {
   tm_print_insn = print_insn_sparc;
+  tm_print_insn_info.mach = TM_PRINT_INSN_MACH;  /* Selects sparc/sparclite */
 }
This page took 0.038673 seconds and 4 git commands to generate.