]> Git Repo - binutils.git/blobdiff - gdb/a29k-tdep.c
import gdb-19990504 snapshot
[binutils.git] / gdb / a29k-tdep.c
index 4b5fa933737921bb683cb9af08c1030fc635f10f..2aab6a45ecaf4a47fd12da0bea0a5385d8f90837 100644 (file)
@@ -1,5 +1,6 @@
 /* Target-machine dependent code for the AMD 29000
 /* Target-machine dependent code for the AMD 29000
-   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995
+   Free Software Foundation, Inc.
    Contributed by Cygnus Support.  Written by Jim Kingdon.
 
 This file is part of GDB.
    Contributed by Cygnus Support.  Written by Jim Kingdon.
 
 This file is part of GDB.
@@ -16,7 +17,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
 
 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.  */
 
 #include "defs.h"
 #include "gdbcore.h"
 
 #include "defs.h"
 #include "gdbcore.h"
@@ -40,7 +41,20 @@ extern CORE_ADDR text_start; /* FIXME, kludge... */
 
 static CORE_ADDR rstack_high_address = UINT_MAX;
 
 
 static CORE_ADDR rstack_high_address = UINT_MAX;
 
+
+/* Should call_function allocate stack space for a struct return?  */
+/* On the a29k objects over 16 words require the caller to allocate space.  */
+int
+a29k_use_struct_convention (gcc_p, type)
+     int gcc_p;
+     struct type *type;
+{
+  return (TYPE_LENGTH (type) > 16 * 4);
+}
+
+
 /* Structure to hold cached info about function prologues.  */
 /* Structure to hold cached info about function prologues.  */
+
 struct prologue_info
 {
   CORE_ADDR pc;                        /* First addr after fn prologue */
 struct prologue_info
 {
   CORE_ADDR pc;                        /* First addr after fn prologue */
@@ -66,6 +80,7 @@ struct prologue_info
 
    If MFP_USED is non-NULL, *MFP_USED is set to nonzero if a memory
    frame pointer is being used.  */
 
    If MFP_USED is non-NULL, *MFP_USED is set to nonzero if a memory
    frame pointer is being used.  */
+
 CORE_ADDR
 examine_prologue (pc, rsize, msize, mfp_used)
      CORE_ADDR pc;
 CORE_ADDR
 examine_prologue (pc, rsize, msize, mfp_used)
      CORE_ADDR pc;
@@ -149,17 +164,18 @@ examine_prologue (pc, rsize, msize, mfp_used)
     }
   p += 4;
 
     }
   p += 4;
 
-  /* Next instruction must be asgeu V_SPILL,gr1,rab.  
+  /* Next instruction ought to be asgeu V_SPILL,gr1,rab.  
    * We don't check the vector number to allow for kernel debugging.  The 
    * kernel will use a different trap number. 
    * We don't check the vector number to allow for kernel debugging.  The 
    * kernel will use a different trap number. 
+   * If this insn is missing, we just keep going; Metaware R2.3u compiler
+   * generates prologue that intermixes initializations and puts the asgeu
+   * way down.
    */
   insn = read_memory_integer (p, 4);
    */
   insn = read_memory_integer (p, 4);
-  if ((insn & 0xff00ffff) != (0x5e000100|RAB_HW_REGNUM))
+  if ((insn & 0xff00ffff) == (0x5e000100|RAB_HW_REGNUM))
     {
     {
-      p = pc;
-      goto done;
+      p += 4;
     }
     }
-  p += 4;
 
   /* Next instruction usually sets the frame pointer (lr1) by adding
      <size * 4> from gr1.  However, this can (and high C does) be
 
   /* Next instruction usually sets the frame pointer (lr1) by adding
      <size * 4> from gr1.  However, this can (and high C does) be
@@ -271,6 +287,19 @@ examine_prologue (pc, rsize, msize, mfp_used)
        }
     }
 
        }
     }
 
+  /* Next instruction might be asgeu V_SPILL,gr1,rab.  
+   * We don't check the vector number to allow for kernel debugging.  The 
+   * kernel will use a different trap number. 
+   * Metaware R2.3u compiler
+   * generates prologue that intermixes initializations and puts the asgeu
+   * way down after everything else.
+   */
+  insn = read_memory_integer (p, 4);
+  if ((insn & 0xff00ffff) == (0x5e000100|RAB_HW_REGNUM))
+    {
+      p += 4;
+    }
+
  done:
   if (msymbol != NULL)
     {
  done:
   if (msymbol != NULL)
     {
@@ -308,12 +337,12 @@ examine_prologue (pc, rsize, msize, mfp_used)
    to reach some "real" code.  */
 
 CORE_ADDR
    to reach some "real" code.  */
 
 CORE_ADDR
-skip_prologue (pc)
+a29k_skip_prologue (pc)
      CORE_ADDR pc;
 {
      CORE_ADDR pc;
 {
-  return examine_prologue (pc, (unsigned *)NULL, (unsigned *)NULL,
-                          (int *)NULL);
+  return examine_prologue (pc, NULL, NULL, NULL);
 }
 }
+
 /*
  * Examine the one or two word tag at the beginning of a function.
  * The tag word is expect to be at 'p', if it is not there, we fail
 /*
  * Examine the one or two word tag at the beginning of a function.
  * The tag word is expect to be at 'p', if it is not there, we fail
@@ -323,11 +352,12 @@ skip_prologue (pc)
  * convention today (1/15/92).
  * msize is return in bytes.
  */
  * convention today (1/15/92).
  * msize is return in bytes.
  */
+
 static int     /* 0/1 - failure/success of finding the tag word  */
 static int     /* 0/1 - failure/success of finding the tag word  */
-examine_tag(p, is_trans, argcount, msize, mfp_used)
+examine_tag (p, is_trans, argcount, msize, mfp_used)
      CORE_ADDR p;
      int *is_trans;
      CORE_ADDR p;
      int *is_trans;
-     int   *argcount;
+     int *argcount;
      unsigned *msize;
      int *mfp_used;
 {
      unsigned *msize;
      int *mfp_used;
 {
@@ -338,9 +368,9 @@ examine_tag(p, is_trans, argcount, msize, mfp_used)
     return 0;
   if (tag1 & (1<<23))                  /* A two word tag */
     {
     return 0;
   if (tag1 & (1<<23))                  /* A two word tag */
     {
-       tag2 = read_memory_integer (p+4, 4);
+       tag2 = read_memory_integer (p-4, 4);
        if (msize)
        if (msize)
-        *msize = tag2;
+        *msize = tag2 * 2;
     }
   else                                 /* A one word tag */
     {
     }
   else                                 /* A one word tag */
     {
@@ -348,22 +378,27 @@ examine_tag(p, is_trans, argcount, msize, mfp_used)
         *msize = tag1 & 0x7ff;
     }
   if (is_trans)
         *msize = tag1 & 0x7ff;
     }
   if (is_trans)
-    *is_trans = ((tag1 & (1<<21)) ? 1 : 0); 
+    *is_trans = ((tag1 & (1<<21)) ? 1 : 0);
+  /* Note that this includes the frame pointer and the return address
+     register, so the actual number of registers of arguments is two less.
+     argcount can be zero, however, sometimes, for strange assembler
+     routines.  */
   if (argcount)
     *argcount = (tag1 >> 16) & 0x1f;
   if (mfp_used)
     *mfp_used = ((tag1 & (1<<22)) ? 1 : 0); 
   if (argcount)
     *argcount = (tag1 >> 16) & 0x1f;
   if (mfp_used)
     *mfp_used = ((tag1 & (1<<22)) ? 1 : 0); 
-  return(1);
+  return 1;
 }
 
 /* Initialize the frame.  In addition to setting "extra" frame info,
    we also set ->frame because we use it in a nonstandard way, and ->pc
    because we need to know it to get the other stuff.  See the diagram
    of stacks and the frame cache in tm-a29k.h for more detail.  */
 }
 
 /* Initialize the frame.  In addition to setting "extra" frame info,
    we also set ->frame because we use it in a nonstandard way, and ->pc
    because we need to know it to get the other stuff.  See the diagram
    of stacks and the frame cache in tm-a29k.h for more detail.  */
+
 static void
 static void
-init_frame_info (innermost_frame, fci)
+init_frame_info (innermost_frame, frame)
      int innermost_frame;
      int innermost_frame;
-     struct frame_info *fci;
+     struct frame_info *frame;
 {
   CORE_ADDR p;
   long insn;
 {
   CORE_ADDR p;
   long insn;
@@ -372,27 +407,27 @@ init_frame_info (innermost_frame, fci)
   int mfp_used, trans;
   struct symbol *func;
 
   int mfp_used, trans;
   struct symbol *func;
 
-  p = fci->pc;
+  p = frame->pc;
 
   if (innermost_frame)
 
   if (innermost_frame)
-    fci->frame = read_register (GR1_REGNUM);
+    frame->frame = read_register (GR1_REGNUM);
   else
   else
-    fci->frame = fci->next->frame + fci->next->rsize;
+    frame->frame = frame->next->frame + frame->next->rsize;
   
   
-#if CALL_DUMMY_LOCATION == ON_STACK
+#if 0 /* CALL_DUMMY_LOCATION == ON_STACK */
   This wont work;
 #else
   if (PC_IN_CALL_DUMMY (p, 0, 0))
 #endif
     {
   This wont work;
 #else
   if (PC_IN_CALL_DUMMY (p, 0, 0))
 #endif
     {
-      fci->rsize = DUMMY_FRAME_RSIZE;
+      frame->rsize = DUMMY_FRAME_RSIZE;
       /* This doesn't matter since we never try to get locals or args
         from a dummy frame.  */
       /* This doesn't matter since we never try to get locals or args
         from a dummy frame.  */
-      fci->msize = 0;
+      frame->msize = 0;
       /* Dummy frames always use a memory frame pointer.  */
       /* Dummy frames always use a memory frame pointer.  */
-      fci->saved_msp = 
-       read_register_stack_integer (fci->frame + DUMMY_FRAME_RSIZE - 4, 4);
-      fci->flags |= (TRANSPARENT|MFP_USED);
+      frame->saved_msp = 
+       read_register_stack_integer (frame->frame + DUMMY_FRAME_RSIZE - 4, 4);
+      frame->flags |= (TRANSPARENT_FRAME|MFP_USED);
       return;
     }
     
       return;
     }
     
@@ -404,18 +439,28 @@ init_frame_info (innermost_frame, fci)
       /* Search backward to find the trace-back tag.  However,
         do not trace back beyond the start of the text segment
         (just as a sanity check to avoid going into never-never land).  */
       /* Search backward to find the trace-back tag.  However,
         do not trace back beyond the start of the text segment
         (just as a sanity check to avoid going into never-never land).  */
+#if 1
       while (p >= text_start
             && ((insn = read_memory_integer (p, 4)) & TAGWORD_ZERO_MASK) != 0)
        p -= 4;
       while (p >= text_start
             && ((insn = read_memory_integer (p, 4)) & TAGWORD_ZERO_MASK) != 0)
        p -= 4;
-      
+#else /* 0 */
+      char pat[4] = {0, 0, 0, 0};
+      char mask[4];
+      char insn_raw[4];
+      store_unsigned_integer (mask, 4, TAGWORD_ZERO_MASK);
+      /* Enable this once target_search is enabled and tested.  */
+      target_search (4, pat, mask, p, -4, text_start, p+1, &p, &insn_raw);
+      insn = extract_unsigned_integer (insn_raw, 4);
+#endif /* 0 */
+
       if (p < text_start)
        {
          /* Couldn't find the trace-back tag.
             Something strange is going on.  */
       if (p < text_start)
        {
          /* Couldn't find the trace-back tag.
             Something strange is going on.  */
-         fci->saved_msp = 0;
-         fci->rsize = 0;
-         fci->msize = 0;
-         fci->flags = TRANSPARENT;
+         frame->saved_msp = 0;
+         frame->rsize = 0;
+         frame->msize = 0;
+         frame->flags = TRANSPARENT_FRAME;
          return;
        }
       else
          return;
        }
       else
@@ -423,62 +468,62 @@ init_frame_info (innermost_frame, fci)
           after the trace-back tag.  */
        p += 4;
     }
           after the trace-back tag.  */
        p += 4;
     }
+
   /* We've found the start of the function.  
   /* We've found the start of the function.  
-   * Try looking for a tag word that indicates whether there is a
-   * memory frame pointer and what the memory stack allocation is.
-   * If one doesn't exist, try using a more exhaustive search of
-   * the prologue.  For now we don't care about the argcount or
-   * whether or not the routine is transparent.
-   */
-  if (examine_tag(p-4,&trans,NULL,&msize,&mfp_used)) /* Found a good tag */
+     Try looking for a tag word that indicates whether there is a
+     memory frame pointer and what the memory stack allocation is.
+     If one doesn't exist, try using a more exhaustive search of
+     the prologue.  */
+
+  if (examine_tag(p-4,&trans,(int *)NULL,&msize,&mfp_used)) /* Found good tag */
       examine_prologue (p, &rsize, 0, 0);
   else                                                 /* No tag try prologue */
       examine_prologue (p, &rsize, &msize, &mfp_used);
 
       examine_prologue (p, &rsize, 0, 0);
   else                                                 /* No tag try prologue */
       examine_prologue (p, &rsize, &msize, &mfp_used);
 
-  fci->rsize = rsize;
-  fci->msize = msize;
-  fci->flags = 0;
+  frame->rsize = rsize;
+  frame->msize = msize;
+  frame->flags = 0;
   if (mfp_used)
   if (mfp_used)
-       fci->flags |= MFP_USED;
+       frame->flags |= MFP_USED;
   if (trans)
   if (trans)
-       fci->flags |= TRANSPARENT;
+       frame->flags |= TRANSPARENT_FRAME;
   if (innermost_frame)
     {
   if (innermost_frame)
     {
-      fci->saved_msp = read_register (MSP_REGNUM) + msize;
+      frame->saved_msp = read_register (MSP_REGNUM) + msize;
     }
   else
     {
       if (mfp_used)
     }
   else
     {
       if (mfp_used)
-        fci->saved_msp =
-             read_register_stack_integer (fci->frame + rsize - 4, 4);
+        frame->saved_msp =
+             read_register_stack_integer (frame->frame + rsize - 4, 4);
       else
       else
-           fci->saved_msp = fci->next->saved_msp + msize;
+           frame->saved_msp = frame->next->saved_msp + msize;
     }
 }
 
 void
     }
 }
 
 void
-init_extra_frame_info (fci)
-     struct frame_info *fci;
+init_extra_frame_info (frame)
+     struct frame_info *frame;
 {
 {
-  if (fci->next == 0)
+  if (frame->next == 0)
     /* Assume innermost frame.  May produce strange results for "info frame"
        but there isn't any way to tell the difference.  */
     /* Assume innermost frame.  May produce strange results for "info frame"
        but there isn't any way to tell the difference.  */
-    init_frame_info (1, fci);
+    init_frame_info (1, frame);
   else {
   else {
-      /* We're in get_prev_frame_info.
+      /* We're in get_prev_frame.
          Take care of everything in init_frame_pc.  */
       ;
     }
 }
 
 void
          Take care of everything in init_frame_pc.  */
       ;
     }
 }
 
 void
-init_frame_pc (fromleaf, fci)
+init_frame_pc (fromleaf, frame)
      int fromleaf;
      int fromleaf;
-     struct frame_info *fci;
+     struct frame_info *frame;
 {
 {
-  fci->pc = (fromleaf ? SAVED_PC_AFTER_CALL (fci->next) :
-            fci->next ? FRAME_SAVED_PC (fci->next) : read_pc ());
-  init_frame_info (fromleaf, fci);
+  frame->pc = (fromleaf ? SAVED_PC_AFTER_CALL (frame->next) :
+            frame->next ? FRAME_SAVED_PC (frame->next) : read_pc ());
+  init_frame_info (fromleaf, frame);
 }
 \f
 /* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
 }
 \f
 /* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
@@ -621,12 +666,13 @@ write_register_stack (memaddr, myaddr, actual_mem_addr)
    otherwise it was fetched from a register.
 
    The argument RAW_BUFFER must point to aligned memory.  */
    otherwise it was fetched from a register.
 
    The argument RAW_BUFFER must point to aligned memory.  */
+
 void
 void
-get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
+a29k_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
      char *raw_buffer;
      int *optimized;
      CORE_ADDR *addrp;
      char *raw_buffer;
      int *optimized;
      CORE_ADDR *addrp;
-     FRAME frame;
+     struct frame_info *frame;
      int regnum;
      enum lval_type *lvalp;
 {
      int regnum;
      enum lval_type *lvalp;
 {
@@ -634,11 +680,13 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
   CORE_ADDR addr;
   enum lval_type lval;
 
   CORE_ADDR addr;
   enum lval_type lval;
 
+  if (!target_has_registers)
+    error ("No registers.");
+
+  /* Probably now redundant with the target_has_registers check.  */
   if (frame == 0)
     return;
 
   if (frame == 0)
     return;
 
-  fi = get_frame_info (frame);
-
   /* Once something has a register number, it doesn't get optimized out.  */
   if (optimized != NULL)
     *optimized = 0;
   /* Once something has a register number, it doesn't get optimized out.  */
   if (optimized != NULL)
     *optimized = 0;
@@ -646,17 +694,17 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
     {
       if (raw_buffer != NULL)
        {
     {
       if (raw_buffer != NULL)
        {
-         store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), fi->frame);
+         store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->frame);
        }
       if (lvalp != NULL)
        *lvalp = not_lval;
       return;
     }
        }
       if (lvalp != NULL)
        *lvalp = not_lval;
       return;
     }
-  else if (regnum == PC_REGNUM)
+  else if (regnum == PC_REGNUM && frame->next != NULL)
     {
       if (raw_buffer != NULL)
        {
     {
       if (raw_buffer != NULL)
        {
-         store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), fi->pc);
+         store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc);
        }
 
       /* Not sure we have to do this.  */
        }
 
       /* Not sure we have to do this.  */
@@ -669,10 +717,10 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
     {
       if (raw_buffer != NULL)
        {
     {
       if (raw_buffer != NULL)
        {
-         if (fi->next != NULL)
+         if (frame->next != NULL)
            {
              store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
            {
              store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
-                            fi->next->saved_msp);
+                            frame->next->saved_msp);
            }
          else
            read_register_gen (MSP_REGNUM, raw_buffer);
            }
          else
            read_register_gen (MSP_REGNUM, raw_buffer);
@@ -695,7 +743,7 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
       return;
     }
       
       return;
     }
       
-  addr = fi->frame + (regnum - LR0_REGNUM) * 4;
+  addr = frame->frame + (regnum - LR0_REGNUM) * 4;
   if (raw_buffer != NULL)
     read_register_stack (addr, raw_buffer, &addr, &lval);
   if (lvalp != NULL)
   if (raw_buffer != NULL)
     read_register_stack (addr, raw_buffer, &addr, &lval);
   if (lvalp != NULL)
@@ -711,17 +759,18 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
 void
 pop_frame ()
 {
 void
 pop_frame ()
 {
-  FRAME frame = get_current_frame ();                                        
-  struct frame_info *fi = get_frame_info (frame);                            
-  CORE_ADDR rfb = read_register (RFB_REGNUM);                                
-  CORE_ADDR gr1 = fi->frame + fi->rsize;
+  struct frame_info *frame = get_current_frame ();
+  CORE_ADDR rfb = read_register (RFB_REGNUM);                
+  CORE_ADDR gr1 = frame->frame + frame->rsize;
   CORE_ADDR lr1;                                                             
   CORE_ADDR lr1;                                                             
+  CORE_ADDR original_lr0;
+  int must_fix_lr0 = 0;
   int i;
 
   /* If popping a dummy frame, need to restore registers.  */
   if (PC_IN_CALL_DUMMY (read_register (PC_REGNUM),
                        read_register (SP_REGNUM),
   int i;
 
   /* If popping a dummy frame, need to restore registers.  */
   if (PC_IN_CALL_DUMMY (read_register (PC_REGNUM),
                        read_register (SP_REGNUM),
-                       FRAME_FP (fi)))
+                       FRAME_FP (frame)))
     {
       int lrnum = LR0_REGNUM + DUMMY_ARG/4;
       for (i = 0; i < DUMMY_SAVE_SR128; ++i)
     {
       int lrnum = LR0_REGNUM + DUMMY_ARG/4;
       for (i = 0; i < DUMMY_SAVE_SR128; ++i)
@@ -730,15 +779,23 @@ pop_frame ()
        write_register (SR_REGNUM(i+160), read_register (lrnum++));
       for (i = 0; i < DUMMY_SAVE_GREGS; ++i)
        write_register (RETURN_REGNUM + i, read_register (lrnum++));
        write_register (SR_REGNUM(i+160), read_register (lrnum++));
       for (i = 0; i < DUMMY_SAVE_GREGS; ++i)
        write_register (RETURN_REGNUM + i, read_register (lrnum++));
-      /* Restore the PCs.  */
+      /* Restore the PCs and prepare to restore LR0.  */
       write_register(PC_REGNUM, read_register (lrnum++));
       write_register(PC_REGNUM, read_register (lrnum++));
-      write_register(NPC_REGNUM, read_register (lrnum));
+      write_register(NPC_REGNUM, read_register (lrnum++));
+      write_register(PC2_REGNUM, read_register (lrnum++));
+      original_lr0 = read_register (lrnum++);
+      must_fix_lr0 = 1;
     }
 
   /* Restore the memory stack pointer.  */
     }
 
   /* Restore the memory stack pointer.  */
-  write_register (MSP_REGNUM, fi->saved_msp);                                
+  write_register (MSP_REGNUM, frame->saved_msp);
   /* Restore the register stack pointer.  */                                 
   write_register (GR1_REGNUM, gr1);
   /* Restore the register stack pointer.  */                                 
   write_register (GR1_REGNUM, gr1);
+
+  /* If we popped a dummy frame, restore lr0 now that gr1 has been restored. */
+  if (must_fix_lr0) 
+    write_register (LR0_REGNUM, original_lr0);
+
   /* Check whether we need to fill registers.  */                            
   lr1 = read_register (LR0_REGNUM + 1);                                      
   if (lr1 > rfb)                                                             
   /* Check whether we need to fill registers.  */                            
   lr1 = read_register (LR0_REGNUM + 1);                                      
   if (lr1 > rfb)                                                             
@@ -746,7 +803,8 @@ pop_frame ()
       /* Fill.  */                                                           
       int num_bytes = lr1 - rfb;
       int i;                                                                 
       /* Fill.  */                                                           
       int num_bytes = lr1 - rfb;
       int i;                                                                 
-      long word;                                                             
+      long word;
+                                                     
       write_register (RAB_REGNUM, read_register (RAB_REGNUM) + num_bytes);  
       write_register (RFB_REGNUM, lr1);                                      
       for (i = 0; i < num_bytes; i += 4)                                     
       write_register (RAB_REGNUM, read_register (RAB_REGNUM) + num_bytes);  
       write_register (RFB_REGNUM, lr1);                                      
       for (i = 0; i < num_bytes; i += 4)                                     
@@ -757,7 +815,6 @@ pop_frame ()
         }                                                                    
     }
   flush_cached_frames ();                                                    
         }                                                                    
     }
   flush_cached_frames ();                                                    
-  set_current_frame (create_new_frame (0, read_pc()));               
 }
 
 /* Push an empty stack frame, to record the current PC, etc.  */
 }
 
 /* Push an empty stack frame, to record the current PC, etc.  */
@@ -768,13 +825,28 @@ push_dummy_frame ()
   long w;
   CORE_ADDR rab, gr1;
   CORE_ADDR msp = read_register (MSP_REGNUM);
   long w;
   CORE_ADDR rab, gr1;
   CORE_ADDR msp = read_register (MSP_REGNUM);
-  int lrnum,  i, saved_lr0;
-  
+  int lrnum, i;
+  CORE_ADDR original_lr0;
+      
+  /* Read original lr0 before changing gr1.  This order isn't really needed
+     since GDB happens to have a snapshot of all the regs and doesn't toss
+     it when gr1 is changed.  But it's The Right Thing To Do.  */
+  original_lr0 = read_register (LR0_REGNUM);
 
   /* Allocate the new frame. */ 
   gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE;
   write_register (GR1_REGNUM, gr1);
 
 
   /* Allocate the new frame. */ 
   gr1 = read_register (GR1_REGNUM) - DUMMY_FRAME_RSIZE;
   write_register (GR1_REGNUM, gr1);
 
+#ifdef VXWORKS_TARGET
+  /* We force re-reading all registers to get the new local registers set
+     after gr1 has been modified. This fix is due to the lack of single
+     register read/write operation in the RPC interface between VxGDB and
+     VxWorks. This really must be changed ! */
+
+  vx_read_register (-1);
+
+#endif /* VXWORK_TARGET */
+
   rab = read_register (RAB_REGNUM);
   if (gr1 < rab)
     {
   rab = read_register (RAB_REGNUM);
   if (gr1 < rab)
     {
@@ -812,17 +884,143 @@ push_dummy_frame ()
     write_register (lrnum++, read_register (SR_REGNUM (i + 160)));
   for (i = 0; i < DUMMY_SAVE_GREGS; ++i)
     write_register (lrnum++, read_register (RETURN_REGNUM + i));
     write_register (lrnum++, read_register (SR_REGNUM (i + 160)));
   for (i = 0; i < DUMMY_SAVE_GREGS; ++i)
     write_register (lrnum++, read_register (RETURN_REGNUM + i));
-  /* Save the PCs.  */
+  /* Save the PCs and LR0.  */
   write_register (lrnum++, read_register (PC_REGNUM));
   write_register (lrnum++, read_register (PC_REGNUM));
-  write_register (lrnum, read_register (NPC_REGNUM));
+  write_register (lrnum++, read_register (NPC_REGNUM));
+  write_register (lrnum++, read_register (PC2_REGNUM));
+
+  /* Why are we saving LR0?  What would clobber it? (the dummy frame should
+     be below it on the register stack, no?).  */
+  write_register (lrnum++, original_lr0);
+}
+
+
+
+/*
+   This routine takes three arguments and makes the cached frames look
+   as if these arguments defined a frame on the cache.  This allows the
+   rest of `info frame' to extract the important arguments without much
+   difficulty.  Since an individual frame on the 29K is determined by
+   three values (FP, PC, and MSP), we really need all three to do a
+   good job.  */
+
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+     int argc;
+     CORE_ADDR *argv;
+{
+  struct frame_info *frame;
+
+  if (argc != 3)
+    error ("AMD 29k frame specifications require three arguments: rsp pc msp");
+
+  frame = create_new_frame (argv[0], argv[1]);
+
+  if (!frame)
+    fatal ("internal: create_new_frame returned invalid frame id");
+  
+  /* Creating a new frame munges the `frame' value from the current
+     GR1, so we restore it again here.  FIXME, untangle all this
+     29K frame stuff...  */
+  frame->frame = argv[0];
+
+  /* Our MSP is in argv[2].  It'd be intelligent if we could just
+     save this value in the FRAME.  But the way it's set up (FIXME),
+     we must save our caller's MSP.  We compute that by adding our
+     memory stack frame size to our MSP.  */
+  frame->saved_msp = argv[2] + frame->msize;
+
+  return frame;
+}
+
+int
+gdb_print_insn_a29k (memaddr, info)
+     bfd_vma memaddr;
+     disassemble_info *info;
+{
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+    return print_insn_big_a29k (memaddr, info);
+  else
+    return print_insn_little_a29k (memaddr, info);
+}
+
+enum a29k_processor_types processor_type = a29k_unknown;
+
+void
+a29k_get_processor_type ()
+{
+  unsigned int cfg_reg = (unsigned int) read_register (CFG_REGNUM);
+
+  /* Most of these don't have freeze mode.  */
+  processor_type = a29k_no_freeze_mode;
+
+  switch ((cfg_reg >> 28) & 0xf)
+    {
+    case 0:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am29000");
+      break;
+    case 1:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am29005");
+      break;
+    case 2:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am29050");
+      processor_type = a29k_freeze_mode;
+      break;
+    case 3:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am29035");
+      break;
+    case 4:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am29030");
+      break;
+    case 5:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am2920*");
+      break;
+    case 6:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am2924*");
+      break;
+    case 7:
+      fprintf_filtered (gdb_stderr, "Remote debugging an Am29040");
+      break;
+    default:
+      fprintf_filtered (gdb_stderr, "Remote debugging an unknown Am29k\n");
+      /* Don't bother to print the revision.  */
+      return;
+    }
+  fprintf_filtered (gdb_stderr, " revision %c\n", 'A' + ((cfg_reg >> 24) & 0x0f));
 }
 
 }
 
+#ifdef GET_LONGJMP_TARGET
+/* Figure out where the longjmp will land.  We expect that we have just entered
+  longjmp and haven't yet setup the stack frame, so the args are still in the
+   output regs.  lr2 (LR2_REGNUM) points at the jmp_buf structure from which we
+   extract the pc (JB_PC) that we will land at.  The pc is copied into ADDR.
+   This routine returns true on success */
+
+int
+get_longjmp_target(pc)
+     CORE_ADDR *pc;
+{
+  CORE_ADDR jb_addr;
+  char buf[sizeof(CORE_ADDR)];
+
+  jb_addr = read_register(LR2_REGNUM);
+
+  if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, (char *) buf,
+                         sizeof(CORE_ADDR)))
+    return 0;
+
+  *pc = extract_address ((PTR) buf, sizeof(CORE_ADDR));
+  return 1;
+}
+#endif /* GET_LONGJMP_TARGET */
 
 void
 
 void
-_initialize_29k()
+_initialize_a29k_tdep ()
 {
   extern CORE_ADDR text_end;
 
 {
   extern CORE_ADDR text_end;
 
+  tm_print_insn = gdb_print_insn_a29k;
+
   /* FIXME, there should be a way to make a CORE_ADDR variable settable. */
   add_show_from_set
     (add_set_cmd ("rstack_high_address", class_support, var_uinteger,
   /* FIXME, there should be a way to make a CORE_ADDR variable settable. */
   add_show_from_set
     (add_set_cmd ("rstack_high_address", class_support, var_uinteger,
This page took 0.047831 seconds and 4 git commands to generate.