Removed v850eq sanitization.
[deliverable/binutils-gdb.git] / gdb / sparc-tdep.c
index 8801136d28039e7e6591f7d559aa5731d085eecb..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
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -16,7 +16,9 @@ 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.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -24,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>
@@ -31,6 +34,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 #include "gdbcore.h"
 
+#ifdef GDB_TARGET_IS_SPARC64
+#define FP_REGISTER_BYTES (64 * 4)
+#else
+#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))
+
 /* From infrun.c */
 extern int stop_after_trap;
 
@@ -42,6 +58,9 @@ extern int stop_after_trap;
 
 int deferred_stores = 0;       /* Cumulates stores we want to do eventually. */
 
+/* Branches with prediction are treated like their non-predicting cousins.  */
+/* FIXME: What about floating point branches?  */
+
 /* Macros to extract fields from sparc instructions.  */
 #define X_OP(i) (((i) >> 30) & 0x3)
 #define X_RD(i) (((i) >> 25) & 0x1f)
@@ -56,10 +75,21 @@ int deferred_stores = 0;    /* Cumulates stores we want to do eventually. */
 /* Sign extension macros.  */
 #define X_SIMM13(i) ((X_IMM13 (i) ^ 0x1000) - 0x1000)
 #define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
+#ifdef GDB_TARGET_IS_SPARC64
+#define X_CC(i) (((i) >> 20) & 3)
+#define X_P(i) (((i) >> 19) & 1)
+#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
+#define X_RCOND(i) (((i) >> 25) & 7)
+#define X_DISP16(i) ((((((i) >> 6) && 0xc000) | ((i) & 0x3fff)) ^ 0x8000) - 0x8000)
+#define X_FCN(i) (((i) >> 25) & 31)
+#endif
 
 typedef enum
 {
-  Error, not_branch, bicc, bicca, ba, baa, ticc, ta
+  Error, not_branch, bicc, bicca, ba, baa, ticc, ta,
+#ifdef GDB_TARGET_IS_SPARC64
+  done_retry
+#endif
 } branch_type;
 
 /* Simulate single-step ptrace call for sun4.  Code written by Gary
@@ -91,7 +121,7 @@ void
 single_step (ignore)
      int ignore; /* pid, but we don't need it */
 {
-  branch_type br, isannulled();
+  branch_type br, isbranch();
   CORE_ADDR pc;
   long pc_instruction;
 
@@ -106,7 +136,7 @@ single_step (ignore)
 
       pc = read_register (PC_REGNUM);
       pc_instruction = read_memory_integer (pc, 4);
-      br = isannulled (pc_instruction, pc, &target);
+      br = isbranch (pc_instruction, pc, &target);
       brknpc4 = brktrg = 0;
 
       if (br == bicca)
@@ -124,6 +154,13 @@ single_step (ignore)
          brktrg = 1;
          target_insert_breakpoint (target, break_mem[2]);
        }
+#ifdef GDB_TARGET_IS_SPARC64
+      else if (br == done_retry)
+       {
+         brktrg = 1;
+         target_insert_breakpoint (target, break_mem[2]);
+       }
+#endif
 
       /* We are ready to let it go */
       one_stepped = 1;
@@ -248,8 +285,13 @@ CORE_ADDR
 sparc_extract_struct_value_address (regbuf)
      char regbuf[REGISTER_BYTES];
 {
-  return read_memory_integer (((int *)(regbuf))[SP_REGNUM]+(16*4), 
+#ifdef GDB_TARGET_IS_SPARC64
+  return extract_address (regbuf + REGISTER_BYTE (O0_REGNUM),
+                         REGISTER_RAW_SIZE (O0_REGNUM));
+#else
+  return read_memory_integer (((int *)(regbuf)) [SP_REGNUM] + (16 * SPARC_INTREG_SIZE), 
                              TARGET_PTR_BIT / TARGET_CHAR_BIT);
+#endif
 }
 
 /* Find the pc saved in frame FRAME.  */
@@ -285,7 +327,7 @@ sparc_frame_saved_pc (frame)
       /* The sigcontext address is contained in register O2.  */
       get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL,
                          frame, O0_REGNUM + 2, (enum lval_type *)NULL);
-      sigcontext_addr = extract_address (buf, REGISTER_RAW_SIZE (O0_REGNUM));
+      sigcontext_addr = extract_address (buf, REGISTER_RAW_SIZE (O0_REGNUM + 2));
 
       /* Don't cause a memory_error when accessing sigcontext in case the
         stack layout has changed or the stack is corrupt.  */
@@ -297,15 +339,15 @@ sparc_frame_saved_pc (frame)
     addr = frame->pc_addr;
   else
     addr = frame->bottom + FRAME_SAVED_I0 +
-      REGISTER_RAW_SIZE (I7_REGNUM) * (I7_REGNUM - I0_REGNUM);
+      SPARC_INTREG_SIZE * (I7_REGNUM - I0_REGNUM);
 
   if (addr == 0)
     /* A flat frame leaf function might not save the PC anywhere,
        just leave it in %o7.  */
     return PC_ADJUST (read_register (O7_REGNUM));
 
-  read_memory (addr, buf, REGISTER_RAW_SIZE (I7_REGNUM));
-  return PC_ADJUST (extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM)));
+  read_memory (addr, buf, SPARC_INTREG_SIZE);
+  return PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE));
 }
 
 /* Since an individual frame in the frame cache is defined by two
@@ -469,12 +511,14 @@ skip_prologue (start_pc, frameless_p)
   return examine_prologue (start_pc, frameless_p, NULL, NULL);
 }
 
-/* Check instruction at ADDR to see if it is an annulled branch.
-   All other instructions will go to NPC or will trap.
-   Set *TARGET if we find a candidate branch; set to zero if not. */
-   
+/* Check instruction at ADDR to see if it is a branch.
+   All non-annulled instructions will go to NPC or will trap.
+   Set *TARGET if we find a candidate branch; set to zero if not.
+
+   This isn't static as it's used by remote-sa.sparc.c.  */
+
 branch_type
-isannulled (instruction, addr, target)
+isbranch (instruction, addr, target)
      long instruction;
      CORE_ADDR addr, *target;
 {
@@ -486,15 +530,58 @@ isannulled (instruction, addr, target)
   if (X_OP (instruction) == 0
       && (X_OP2 (instruction) == 2
          || X_OP2 (instruction) == 6
-         || X_OP2 (instruction) == 7))
+#ifdef GDB_TARGET_IS_SPARC64
+         || X_OP2 (instruction) == 1
+         || X_OP2 (instruction) == 3
+         || X_OP2 (instruction) == 5
+#else
+         || X_OP2 (instruction) == 7
+#endif
+         ))
     {
       if (X_COND (instruction) == 8)
        val = X_A (instruction) ? baa : ba;
       else
        val = X_A (instruction) ? bicca : bicc;
-      offset = 4 * X_DISP22 (instruction);
+      switch (X_OP2 (instruction))
+       {
+       case 2:
+       case 6:
+#ifndef GDB_TARGET_IS_SPARC64
+       case 7:
+#endif
+         offset = 4 * X_DISP22 (instruction);
+         break;
+#ifdef GDB_TARGET_IS_SPARC64
+       case 1:
+       case 5:
+         offset = 4 * X_DISP19 (instruction);
+         break;
+       case 3:
+         offset = 4 * X_DISP16 (instruction);
+         break;
+#endif
+       }
       *target = addr + offset;
     }
+#ifdef GDB_TARGET_IS_SPARC64
+  else if (X_OP (instruction) == 2
+          && X_OP3 (instruction) == 62)
+    {
+      if (X_FCN (instruction) == 0)
+       {
+         /* done */
+         *target = read_register (TNPC_REGNUM);
+         val = done_retry;
+       }
+      else if (X_FCN (instruction) == 1)
+       {
+         /* retry */
+         *target = read_register (TPC_REGNUM);
+         val = done_retry;
+       }
+    }
+#endif
 
   return val;
 }
@@ -519,10 +606,29 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
   struct frame_info *frame1;
   CORE_ADDR addr;
 
+  if (!target_has_registers)
+    error ("No registers.");
+
   if (optimized)
     *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)
     {
@@ -530,15 +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. */
+         /* 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) * 4 - 0xa0;
+           addr = frame1->frame + (regnum - G0_REGNUM) * 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) * 4 - 0xc0;
+           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 - 0x80;
+           addr = frame1->frame + (regnum - FP0_REGNUM) * 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) * 4 - 0xe0;
+           addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
+             - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
        }
       else if (frame1->flat)
        {
@@ -563,11 +690,11 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
          /* Normal frame.  Local and In registers are saved on stack.  */
          if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
            addr = (frame1->prev->bottom
-                   + (regnum - I0_REGNUM) * REGISTER_RAW_SIZE (I0_REGNUM)
+                   + (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) * REGISTER_RAW_SIZE (L0_REGNUM)
+                   + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
                    + FRAME_SAVED_L0);
          else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
            {
@@ -619,32 +746,58 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
 
 /* Definitely see tm-sparc.h for more doc of the frame format here.  */
 
+#ifdef GDB_TARGET_IS_SPARC64
+#define DUMMY_REG_SAVE_OFFSET (128 + 16)
+#else
+#define DUMMY_REG_SAVE_OFFSET 0x60
+#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
 sparc_push_dummy_frame ()
 {
   CORE_ADDR sp, old_sp;
-  char register_temp[0x140];
+  char register_temp[DUMMY_STACK_SIZE];
 
   old_sp = sp = read_register (SP_REGNUM);
 
+#ifdef GDB_TARGET_IS_SPARC64
+  /* FIXME: not sure what needs to be saved here.  */
+#else
   /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
   read_register_bytes (REGISTER_BYTE (Y_REGNUM), &register_temp[0],
                       REGISTER_RAW_SIZE (Y_REGNUM) * 8);
+#endif
 
-  read_register_bytes (REGISTER_BYTE (O0_REGNUM), &register_temp[8 * 4],
-                      REGISTER_RAW_SIZE (O0_REGNUM) * 8);
+  read_register_bytes (REGISTER_BYTE (O0_REGNUM),
+                      &register_temp[8 * SPARC_INTREG_SIZE],
+                      SPARC_INTREG_SIZE * 8);
 
-  read_register_bytes (REGISTER_BYTE (G0_REGNUM), &register_temp[16 * 4],
-                      REGISTER_RAW_SIZE (G0_REGNUM) * 8);
+  read_register_bytes (REGISTER_BYTE (G0_REGNUM),
+                      &register_temp[16 * SPARC_INTREG_SIZE],
+                      SPARC_INTREG_SIZE * 8);
 
-  read_register_bytes (REGISTER_BYTE (FP0_REGNUM), &register_temp[24 * 4],
-                      REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+#ifdef FP0_REGNUM
+  read_register_bytes (REGISTER_BYTE (FP0_REGNUM),
+                      &register_temp[24 * SPARC_INTREG_SIZE],
+                      FP_REGISTER_BYTES);
+#endif /* FP0_REGNUM */
 
-  sp -= 0x140;
+  sp -= DUMMY_STACK_SIZE;
 
   write_register (SP_REGNUM, sp);
 
-  write_memory (sp + 0x60, &register_temp[0], (8 + 8 + 8 + 32) * 4);
+  write_memory (sp + DUMMY_REG_SAVE_OFFSET, &register_temp[0],
+               DUMMY_STACK_REG_BUF_SIZE);
 
   write_register (FP_REGNUM, old_sp);
 
@@ -709,16 +862,28 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
       /* Dummy frame.  All but the window regs are in there somewhere. */
       for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
        saved_regs_addr->regs[regnum] =
-         frame_addr + (regnum - G0_REGNUM) * 4 - 0xa0;
+         frame_addr + (regnum - G0_REGNUM) * 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) * 4 - 0xc0;
+         frame_addr + (regnum - I0_REGNUM) * 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 - 0x80;
+         frame_addr + (regnum - FP0_REGNUM) * 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) * 4 - 0xe0;
+         frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE - 0xe0;
+           - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
       frame_addr = fi->bottom ?
        fi->bottom : read_register (SP_REGNUM);
     }
@@ -739,11 +904,11 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
        fi->bottom : read_register (SP_REGNUM);
       for (regnum = L0_REGNUM; regnum < L0_REGNUM+8; regnum++)
        saved_regs_addr->regs[regnum] =
-         (frame_addr + (regnum - L0_REGNUM) * REGISTER_RAW_SIZE (L0_REGNUM)
+         (frame_addr + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
           + FRAME_SAVED_L0);
       for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
        saved_regs_addr->regs[regnum] =
-         (frame_addr + (regnum - I0_REGNUM) * REGISTER_RAW_SIZE (I0_REGNUM)
+         (frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
           + FRAME_SAVED_I0);
     }
   if (fi->next)
@@ -762,7 +927,7 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
          for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++)
            saved_regs_addr->regs[regnum] =
              (next_next_frame_addr
-              + (regnum - O0_REGNUM) * REGISTER_RAW_SIZE (O0_REGNUM)
+              + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE
               + FRAME_SAVED_I0);
        }
     }
@@ -794,11 +959,14 @@ 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, 32 * 4);
-      write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer, 32 * 4);
+      read_memory (fsr.regs[FP0_REGNUM], raw_buffer, FP_REGISTER_BYTES);
+      write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
+                           raw_buffer, FP_REGISTER_BYTES);
     }
+#ifndef GDB_TARGET_IS_SPARC64
   if (fsr.regs[FPS_REGNUM])
     {
       read_memory (fsr.regs[FPS_REGNUM], raw_buffer, 4);
@@ -809,10 +977,13 @@ sparc_pop_frame ()
       read_memory (fsr.regs[CPS_REGNUM], raw_buffer, 4);
       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 * 4);
-      write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer, 7 * 4);
+      read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE);
+      write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer,
+                           7 * SPARC_INTREG_SIZE);
     }
 
   if (frame->flat)
@@ -821,20 +992,24 @@ sparc_pop_frame ()
         individually.  */
       for (regnum = L0_REGNUM; regnum < L0_REGNUM + 8; ++regnum)
        if (fsr.regs[regnum])
-         write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+         write_register (regnum, read_memory_integer (fsr.regs[regnum],
+                                                      SPARC_INTREG_SIZE));
       for (regnum = I0_REGNUM; regnum < I0_REGNUM + 8; ++regnum)
        if (fsr.regs[regnum])
-         write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+         write_register (regnum, read_memory_integer (fsr.regs[regnum],
+                                                      SPARC_INTREG_SIZE));
 
       /* Handle all outs except stack pointer (o0-o5; o7).  */
       for (regnum = O0_REGNUM; regnum < O0_REGNUM + 6; ++regnum)
        if (fsr.regs[regnum])
-         write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+         write_register (regnum, read_memory_integer (fsr.regs[regnum],
+                                                      SPARC_INTREG_SIZE));
       if (fsr.regs[O0_REGNUM + 7])
        write_register (O0_REGNUM + 7,
-                       read_memory_integer (fsr.regs[O0_REGNUM + 7], 4));
+                       read_memory_integer (fsr.regs[O0_REGNUM + 7],
+                                            SPARC_INTREG_SIZE));
 
-      write_register (SP_REGNUM, frame->frame, 4);
+      write_register (SP_REGNUM, frame->frame);
     }
   else if (fsr.regs[I0_REGNUM])
     {
@@ -842,7 +1017,7 @@ sparc_pop_frame ()
 
       char reg_temp[REGISTER_BYTES];
 
-      read_memory (fsr.regs[I0_REGNUM], raw_buffer, 8 * 4);
+      read_memory (fsr.regs[I0_REGNUM], raw_buffer, 8 * SPARC_INTREG_SIZE);
 
       /* Get the ins and locals which we are about to restore.  Just
         moving the stack pointer is all that is really needed, except
@@ -850,32 +1025,38 @@ sparc_pop_frame ()
         locals from the registers array, so we need to muck with the
         registers array.  */
       sp = fsr.regs[SP_REGNUM];
-      read_memory (sp, reg_temp, REGISTER_RAW_SIZE (L0_REGNUM) * 16);
+      read_memory (sp, reg_temp, SPARC_INTREG_SIZE * 16);
 
       /* Restore the out registers.
         Among other things this writes the new stack pointer.  */
       write_register_bytes (REGISTER_BYTE (O0_REGNUM), raw_buffer,
-                           REGISTER_RAW_SIZE (O0_REGNUM) * 8);
+                           SPARC_INTREG_SIZE * 8);
 
       write_register_bytes (REGISTER_BYTE (L0_REGNUM), reg_temp,
-                           REGISTER_RAW_SIZE (L0_REGNUM) * 16);
+                           SPARC_INTREG_SIZE * 16);
     }
+#ifndef GDB_TARGET_IS_SPARC64
   if (fsr.regs[PS_REGNUM])
     write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
+#endif
   if (fsr.regs[Y_REGNUM])
-    write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], 4));
+    write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], REGISTER_RAW_SIZE (Y_REGNUM)));
   if (fsr.regs[PC_REGNUM])
     {
       /* Explicitly specified PC (and maybe NPC) -- just restore them. */
-      write_register (PC_REGNUM, read_memory_integer (fsr.regs[PC_REGNUM], 4));
+      write_register (PC_REGNUM, read_memory_integer (fsr.regs[PC_REGNUM],
+                                                     REGISTER_RAW_SIZE (PC_REGNUM)));
       if (fsr.regs[NPC_REGNUM])
        write_register (NPC_REGNUM,
-                       read_memory_integer (fsr.regs[NPC_REGNUM], 4));
+                       read_memory_integer (fsr.regs[NPC_REGNUM],
+                                            REGISTER_RAW_SIZE (NPC_REGNUM)));
     }
   else if (frame->flat)
     {
       if (frame->pc_addr)
-       pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (frame->pc_addr, 4));
+       pc = PC_ADJUST ((CORE_ADDR)
+                       read_memory_integer (frame->pc_addr,
+                                            REGISTER_RAW_SIZE (PC_REGNUM)));
       else
        {
          /* I think this happens only in the innermost frame, if so then
@@ -893,7 +1074,8 @@ sparc_pop_frame ()
   else if (fsr.regs[I7_REGNUM])
     {
       /* Return address in %i7 -- adjust it, then restore PC and NPC from it */
-      pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (fsr.regs[I7_REGNUM], 4));
+      pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (fsr.regs[I7_REGNUM],
+                                                      SPARC_INTREG_SIZE));
       write_register (PC_REGNUM,  pc);
       write_register (NPC_REGNUM, pc + 4);
     }
@@ -914,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;
@@ -1000,9 +1182,9 @@ sunos4_skip_trampoline_code (pc)
 
  */
 
-/*  Given a pointer to a general register set in /proc format (gregset_t *),
-    unpack the register contents and supply them as gdb's idea of the current
-    register values. */
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+   unpack the register contents and supply them as gdb's idea of the current
+   register values. */
 
 void
 supply_gregset (gregsetp)
@@ -1010,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++)
@@ -1022,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
@@ -1031,7 +1219,6 @@ int regno;
 {
   int regi;
   register prgreg_t *regp = (prgreg_t *) gregsetp;
-  extern char registers[];
 
   for (regi = 0 ; regi <= R_I7 ; regi++)
     {
@@ -1071,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);
@@ -1083,6 +1270,7 @@ prfpregset_t *fpregsetp;
     (fpregset_t *), update the register specified by REGNO from gdb's idea
     of the current floating point register set.  If REGNO is -1, update
     them all. */
+/* ??? This will probably need some changes for sparc64.  */
 
 void
 fill_fpregset (fpregsetp, regno)
@@ -1092,9 +1280,8 @@ int regno;
   int regi;
   char *to;
   char *from;
-  extern char registers[];
 
-  for (regi = FP0_REGNUM ; regi < FP0_REGNUM+32 ; regi++)
+  for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
     {
       if ((regno == -1) || (regno == regi))
        {
@@ -1141,3 +1328,227 @@ get_longjmp_target (pc)
   return 1;
 }
 #endif /* GET_LONGJMP_TARGET */
+\f
+#ifdef STATIC_TRANSFORM_NAME
+/* SunPRO (3.0 at least), encodes the static variables.  This is not
+   related to C++ mangling, it is done for C too.  */
+
+char *
+sunpro_static_transform_name (name)
+     char *name;
+{
+  char *p;
+  if (name[0] == '$')
+    {
+      /* For file-local statics there will be a dollar sign, a bunch
+        of junk (the contents of which match a string given in the
+        N_OPT), a period and the name.  For function-local statics
+        there will be a bunch of junk (which seems to change the
+        second character from 'A' to 'B'), a period, the name of the
+        function, and the name.  So just skip everything before the
+        last period.  */
+      p = strrchr (name, '.');
+      if (p != NULL)
+       name = p + 1;
+    }
+  return name;
+}
+#endif /* STATIC_TRANSFORM_NAME */
+\f
+#ifdef GDB_TARGET_IS_SPARC64
+
+/* Utilities for printing registers.
+   Page numbers refer to the SPARC Architecture Manual.  */
+
+static void dump_ccreg PARAMS ((char *, int));
+
+static void
+dump_ccreg (reg, val)
+     char *reg;
+     int val;
+{
+  /* page 41 */
+  printf_unfiltered ("%s:%s,%s,%s,%s", reg,
+         val & 8 ? "N" : "NN",
+         val & 4 ? "Z" : "NZ",
+         val & 2 ? "O" : "NO",
+         val & 1 ? "C" : "NC"
+  );
+}
+
+static char *
+decode_asi (val)
+     int val;
+{
+  /* page 72 */
+  switch (val)
+    {
+    case 4 : return "ASI_NUCLEUS";
+    case 0x0c : return "ASI_NUCLEUS_LITTLE";
+    case 0x10 : return "ASI_AS_IF_USER_PRIMARY";
+    case 0x11 : return "ASI_AS_IF_USER_SECONDARY";
+    case 0x18 : return "ASI_AS_IF_USER_PRIMARY_LITTLE";
+    case 0x19 : return "ASI_AS_IF_USER_SECONDARY_LITTLE";
+    case 0x80 : return "ASI_PRIMARY";
+    case 0x81 : return "ASI_SECONDARY";
+    case 0x82 : return "ASI_PRIMARY_NOFAULT";
+    case 0x83 : return "ASI_SECONDARY_NOFAULT";
+    case 0x88 : return "ASI_PRIMARY_LITTLE";
+    case 0x89 : return "ASI_SECONDARY_LITTLE";
+    case 0x8a : return "ASI_PRIMARY_NOFAULT_LITTLE";
+    case 0x8b : return "ASI_SECONDARY_NOFAULT_LITTLE";
+    default : return NULL;
+    }
+}
+
+/* PRINT_REGISTER_HOOK routine.
+   Pretty print various registers.  */
+/* FIXME: Would be nice if this did some fancy things for 32 bit sparc.  */
+
+void
+sparc_print_register_hook (regno)
+     int regno;
+{
+  unsigned LONGEST val;
+
+  /* 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 value[16];
+
+      if (!read_relative_register_raw_bytes (regno, value)
+         && !read_relative_register_raw_bytes (regno + 1, value + 8))
+       {
+         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.  */
+
+#define BITS(n, mask) ((int) (((val) >> (n)) & (mask)))
+
+  val = read_register (regno);
+
+  /* pages 40 - 60 */
+  switch (regno)
+    {
+    case CCR_REGNUM :
+      printf_unfiltered("\t");
+      dump_ccreg ("xcc", val >> 4);
+      printf_unfiltered(", ");
+      dump_ccreg ("icc", val & 15);
+      break;
+    case FPRS_REGNUM :
+      printf ("\tfef:%d, du:%d, dl:%d",
+             BITS (2, 1), BITS (1, 1), BITS (0, 1));
+      break;
+    case FSR_REGNUM :
+      {
+       static char *fcc[4] = { "=", "<", ">", "?" };
+       static char *rd[4] = { "N", "0", "+", "-" };
+       /* Long, yes, but I'd rather leave it as is and use a wide screen.  */
+       printf ("\t0:%s, 1:%s, 2:%s, 3:%s, rd:%s, tem:%d, ns:%d, ver:%d, ftt:%d, qne:%d, aexc:%d, cexc:%d",
+               fcc[BITS (10, 3)], fcc[BITS (32, 3)],
+               fcc[BITS (34, 3)], fcc[BITS (36, 3)],
+               rd[BITS (30, 3)], BITS (23, 31), BITS (22, 1), BITS (17, 7),
+               BITS (14, 7), BITS (13, 1), BITS (5, 31), BITS (0, 31));
+       break;
+      }
+    case ASI_REGNUM :
+      {
+       char *asi = decode_asi (val);
+       if (asi != NULL)
+         printf ("\t%s", asi);
+       break;
+      }
+    case VER_REGNUM :
+      printf ("\tmanuf:%d, impl:%d, mask:%d, maxtl:%d, maxwin:%d",
+             BITS (48, 0xffff), BITS (32, 0xffff),
+             BITS (24, 0xff), BITS (8, 0xff), BITS (0, 31));
+      break;
+    case PSTATE_REGNUM :
+      {
+       static char *mm[4] = { "tso", "pso", "rso", "?" };
+       printf ("\tcle:%d, tle:%d, mm:%s, red:%d, pef:%d, am:%d, priv:%d, ie:%d, ag:%d",
+               BITS (9, 1), BITS (8, 1), mm[BITS (6, 3)], BITS (5, 1),
+               BITS (4, 1), BITS (3, 1), BITS (2, 1), BITS (1, 1),
+               BITS (0, 1));
+       break;
+      }
+    case TSTATE_REGNUM :
+      /* FIXME: print all 4? */
+      break;
+    case TT_REGNUM :
+      /* FIXME: print all 4? */
+      break;
+    case TPC_REGNUM :
+      /* FIXME: print all 4? */
+      break;
+    case TNPC_REGNUM :
+      /* FIXME: print all 4? */
+      break;
+    case WSTATE_REGNUM :
+      printf ("\tother:%d, normal:%d", BITS (3, 7), BITS (0, 7));
+      break;
+    case CWP_REGNUM :
+      printf ("\t%d", BITS (0, 31));
+      break;
+    case CANSAVE_REGNUM :
+      printf ("\t%-2d before spill", BITS (0, 31));
+      break;
+    case CANRESTORE_REGNUM :
+      printf ("\t%-2d before fill", BITS (0, 31));
+      break;
+    case CLEANWIN_REGNUM :
+      printf ("\t%-2d before clean", BITS (0, 31));
+      break;
+    case OTHERWIN_REGNUM :
+      printf ("\t%d", BITS (0, 31));
+      break;
+    }
+
+#undef BITS
+}
+
+#endif
+\f
+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.061973 seconds and 4 git commands to generate.