* i387-tdep.c (print_i387_value): Cast &value to (char *) in
[deliverable/binutils-gdb.git] / gdb / a29k-tdep.c
index 42232cec22000f6383c1a3d7caa2ac1f0a566ef4..5370106acc17a5f03d1f6fd64046721235c8273d 100644 (file)
@@ -1,22 +1,24 @@
 /* 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.
+   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 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.
+   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.  */
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "gdbcore.h"
@@ -40,15 +42,28 @@ extern CORE_ADDR text_start;        /* FIXME, kludge... */
 
 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.  */
+
 struct prologue_info
 {
   CORE_ADDR pc;                        /* First addr after fn prologue */
   unsigned rsize, msize;       /* register stack frame size, mem stack ditto */
-  unsigned mfp_used : 1;       /* memory frame pointer used */
-  unsigned rsize_valid : 1;    /* Validity bits for the above */
-  unsigned msize_valid : 1;
-  unsigned mfp_valid : 1;
+  unsigned mfp_used:1;         /* memory frame pointer used */
+  unsigned rsize_valid:1;      /* Validity bits for the above */
+  unsigned msize_valid:1;
+  unsigned mfp_valid:1;
 };
 
 /* Examine the prologue of a function which starts at PC.  Return
@@ -66,6 +81,7 @@ struct prologue_info
 
    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;
@@ -79,7 +95,7 @@ examine_prologue (pc, rsize, msize, mfp_used)
   struct prologue_info *mi = 0;
 
   if (msymbol != NULL)
-    mi = (struct prologue_info *) msymbol -> info;
+    mi = (struct prologue_info *) msymbol->info;
 
   if (mi != 0)
     {
@@ -109,21 +125,21 @@ examine_prologue (pc, rsize, msize, mfp_used)
     *msize = 0;
   if (mfp_used != NULL)
     *mfp_used = 0;
-  
+
   /* Prologue must start with subtracting a constant from gr1.
      Normally this is sub gr1,gr1,<rsize * 4>.  */
   insn = read_memory_integer (p, 4);
   if ((insn & 0xffffff00) != 0x25010100)
     {
       /* If the frame is large, instead of a single instruction it
-        might be a pair of instructions:
-        const <reg>, <rsize * 4>
-        sub gr1,gr1,<reg>
-        */
+         might be a pair of instructions:
+         const <reg>, <rsize * 4>
+         sub gr1,gr1,<reg>
+       */
       int reg;
       /* Possible value for rsize.  */
       unsigned int rsize0;
-      
+
       if ((insn & 0xff000000) != 0x03000000)
        {
          p = pc;
@@ -149,17 +165,18 @@ examine_prologue (pc, rsize, msize, mfp_used)
     }
   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. 
+   * 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);
-  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
@@ -175,9 +192,9 @@ examine_prologue (pc, rsize, msize, mfp_used)
   else
     {
       /* However, for large frames it can be
-        const <reg>, <size *4>
-        add lr1,gr1,<reg>
-        */
+         const <reg>, <size *4>
+         add lr1,gr1,<reg>
+       */
       int reg;
       CORE_ADDR q;
 
@@ -205,8 +222,8 @@ examine_prologue (pc, rsize, msize, mfp_used)
      to be looking for a "sub" instruction here, but the mask was set
      up to lose all the time. */
   insn = read_memory_integer (p, 4);
-  if (((insn & 0xff80ffff) == (0x15800000|(MSP_HW_REGNUM<<8)))     /* add */
-   || ((insn & 0xff80ffff) == (0x81800000|(MSP_HW_REGNUM<<8))))    /* sll */
+  if (((insn & 0xff80ffff) == (0x15800000 | (MSP_HW_REGNUM << 8)))     /* add */
+      || ((insn & 0xff80ffff) == (0x81800000 | (MSP_HW_REGNUM << 8)))) /* sll */
     {
       p += 4;
       if (mfp_used != NULL)
@@ -222,24 +239,24 @@ examine_prologue (pc, rsize, msize, mfp_used)
 
      Normally this is just
      sub msp,msp,<msize>
-     */
+   */
   insn = read_memory_integer (p, 4);
-  if ((insn & 0xffffff00) == 
-               (0x25000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8)))
+  if ((insn & 0xffffff00) ==
+      (0x25000000 | (MSP_HW_REGNUM << 16) | (MSP_HW_REGNUM << 8)))
     {
       p += 4;
-      if (msize != NULL) 
+      if (msize != NULL)
        *msize = insn & 0xff;
     }
   else
     {
       /* For large frames, instead of a single instruction it might
-        be
+         be
 
-        const <reg>, <msize>
-        consth <reg>, <msize>     ; optional
-        sub msp,msp,<reg>
-        */
+         const <reg>, <msize>
+         consth <reg>, <msize>     ; optional
+         sub msp,msp,<reg>
+       */
       int reg;
       unsigned msize0;
       CORE_ADDR q = p;
@@ -260,8 +277,8 @@ examine_prologue (pc, rsize, msize, mfp_used)
              insn = read_memory_integer (q, 4);
            }
          /* Check for sub msp,msp,<reg>.  */
-          if ((insn & 0xffffff00) == 
-               (0x24000000|(MSP_HW_REGNUM<<16)|(MSP_HW_REGNUM<<8))
+         if ((insn & 0xffffff00) ==
+             (0x24000000 | (MSP_HW_REGNUM << 16) | (MSP_HW_REGNUM << 8))
              && (insn & 0xff) == reg)
            {
              p = q + 4;
@@ -271,14 +288,27 @@ examine_prologue (pc, rsize, msize, mfp_used)
        }
     }
 
- done:
+  /* 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)
     {
       if (mi == 0)
        {
          /* Add a new cache entry.  */
-         mi = (struct prologue_info *)xmalloc (sizeof (struct prologue_info));
-         msymbol -> info = (char *)mi;
+         mi = (struct prologue_info *) xmalloc (sizeof (struct prologue_info));
+         msymbol->info = (char *) mi;
          mi->rsize_valid = 0;
          mi->msize_valid = 0;
          mi->mfp_valid = 0;
@@ -308,12 +338,12 @@ examine_prologue (pc, rsize, msize, mfp_used)
    to reach some "real" code.  */
 
 CORE_ADDR
-skip_prologue (pc)
+a29k_skip_prologue (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
@@ -323,11 +353,12 @@ skip_prologue (pc)
  * convention today (1/15/92).
  * msize is return in bytes.
  */
-static int     /* 0/1 - failure/success of finding the tag word  */
-examine_tag(p, is_trans, argcount, msize, mfp_used)
+
+static int                     /* 0/1 - failure/success of finding the tag word  */
+examine_tag (p, is_trans, argcount, msize, mfp_used)
      CORE_ADDR p;
      int *is_trans;
-     int   *argcount;
+     int *argcount;
      unsigned *msize;
      int *mfp_used;
 {
@@ -336,34 +367,40 @@ examine_tag(p, is_trans, argcount, msize, mfp_used)
   tag1 = read_memory_integer (p, 4);
   if ((tag1 & TAGWORD_ZERO_MASK) != 0) /* Not a tag word */
     return 0;
-  if (tag1 & (1<<23))                  /* A two word tag */
+  if (tag1 & (1 << 23))                /* A two word tag */
     {
-       tag2 = read_memory_integer (p+4, 4);
-       if (msize)
-        *msize = tag2;
+      tag2 = read_memory_integer (p - 4, 4);
+      if (msize)
+       *msize = tag2 * 2;
     }
-  else                                 /* A one word tag */
+  else
+    /* A one word tag */
     {
-       if (msize)
-        *msize = tag1 & 0x7ff;
+      if (msize)
+       *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); 
-  return(1);
+    *mfp_used = ((tag1 & (1 << 22)) ? 1 : 0);
+  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.  */
+
 static void
-init_frame_info (innermost_frame, fci)
+init_frame_info (innermost_frame, frame)
      int innermost_frame;
-     struct frame_info *fci;
+     struct frame_info *frame;
 {
   CORE_ADDR p;
   long insn;
@@ -372,50 +409,61 @@ init_frame_info (innermost_frame, fci)
   int mfp_used, trans;
   struct symbol *func;
 
-  p = fci->pc;
+  p = frame->pc;
 
   if (innermost_frame)
-    fci->frame = read_register (GR1_REGNUM);
+    frame->frame = read_register (GR1_REGNUM);
   else
-    fci->frame = fci->next->frame + fci->next->rsize;
-  
-#if CALL_DUMMY_LOCATION == ON_STACK
+    frame->frame = frame->next->frame + frame->next->rsize;
+
+#if 0                          /* CALL_DUMMY_LOCATION == ON_STACK */
   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.  */
-      fci->msize = 0;
+         from a dummy frame.  */
+      frame->msize = 0;
       /* 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;
     }
-    
+
   func = find_pc_function (p);
   if (func != NULL)
     p = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
   else
     {
       /* 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).  */
+         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)
+         && ((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.  */
-         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
@@ -423,62 +471,63 @@ init_frame_info (innermost_frame, fci)
           after the trace-back tag.  */
        p += 4;
     }
+
   /* 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 */
-      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;
+     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);
+
+  frame->rsize = rsize;
+  frame->msize = msize;
+  frame->flags = 0;
   if (mfp_used)
-       fci->flags |= MFP_USED;
+    frame->flags |= MFP_USED;
   if (trans)
-       fci->flags |= TRANSPARENT;
+    frame->flags |= TRANSPARENT_FRAME;
   if (innermost_frame)
     {
-      fci->saved_msp = read_register (MSP_REGNUM) + msize;
+      frame->saved_msp = read_register (MSP_REGNUM) + msize;
     }
   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
-           fci->saved_msp = fci->next->saved_msp + msize;
+       frame->saved_msp = frame->next->saved_msp + msize;
     }
 }
 
 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.  */
-    init_frame_info (1, fci);
-  else {
-      /* We're in get_prev_frame_info.
+    init_frame_info (1, frame);
+  else
+    {
+      /* We're in get_prev_frame.
          Take care of everything in init_frame_pc.  */
       ;
     }
 }
 
 void
-init_frame_pc (fromleaf, fci)
+init_frame_pc (fromleaf, frame)
      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
@@ -489,7 +538,7 @@ CORE_ADDR
 frame_locals_address (fi)
      struct frame_info *fi;
 {
-  if (fi->flags & MFP_USED) 
+  if (fi->flags & MFP_USED)
     return fi->saved_msp;
   else
     return fi->saved_msp - fi->msize;
@@ -517,10 +566,11 @@ read_register_stack (memaddr, myaddr, actual_mem_addr, lval)
   long rsp = read_register (RSP_REGNUM);
 
   /* If we don't do this 'info register' stops in the middle. */
-  if (memaddr >= rstack_high_address) 
+  if (memaddr >= rstack_high_address)
     {
       /* a bogus value */
-      char val[] = {~0, ~0, ~0, ~0};
+      static char val[] =
+      {~0, ~0, ~0, ~0};
       /* It's in a local register, but off the end of the stack.  */
       int regnum = (memaddr - rsp) / 4 + LR0_REGNUM;
       if (myaddr != NULL)
@@ -528,7 +578,7 @@ read_register_stack (memaddr, myaddr, actual_mem_addr, lval)
          /* Provide bogusness */
          memcpy (myaddr, val, 4);
        }
-      supply_register(regnum, val);    /* More bogusness */
+      supply_register (regnum, val);   /* More bogusness */
       if (lval != NULL)
        *lval = lval_register;
       if (actual_mem_addr != NULL)
@@ -554,7 +604,7 @@ read_register_stack (memaddr, myaddr, actual_mem_addr, lval)
   else
     {
       /* It's in the memory portion of the register stack.  */
-      if (myaddr != NULL) 
+      if (myaddr != NULL)
        read_memory (memaddr, myaddr, 4);
       if (lval != NULL)
        *lval = lval_memory;
@@ -587,11 +637,11 @@ write_register_stack (memaddr, myaddr, actual_mem_addr)
   long rfb = read_register (RFB_REGNUM);
   long rsp = read_register (RSP_REGNUM);
   /* If we don't do this 'info register' stops in the middle. */
-  if (memaddr >= rstack_high_address) 
+  if (memaddr >= rstack_high_address)
     {
       /* It's in a register, but off the end of the stack.  */
       if (actual_mem_addr != NULL)
-       *actual_mem_addr = 0; 
+       *actual_mem_addr = 0;
     }
   else if (memaddr < rfb)
     {
@@ -600,7 +650,7 @@ write_register_stack (memaddr, myaddr, actual_mem_addr)
       if (regnum < LR0_REGNUM || regnum > LR0_REGNUM + 127)
        error ("Attempt to read register stack out of range.");
       if (myaddr != NULL)
-       write_register (regnum, *(long *)myaddr);
+       write_register (regnum, *(long *) myaddr);
       if (actual_mem_addr != NULL)
        *actual_mem_addr = 0;
     }
@@ -621,12 +671,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.  */
+
 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;
-     FRAME frame;
+     struct frame_info *frame;
      int regnum;
      enum lval_type *lvalp;
 {
@@ -634,11 +685,13 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
   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;
 
-  fi = get_frame_info (frame);
-
   /* Once something has a register number, it doesn't get optimized out.  */
   if (optimized != NULL)
     *optimized = 0;
@@ -646,17 +699,17 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
     {
       if (raw_buffer != NULL)
        {
-         store_address (raw_buffer, REGISTER_RAW_BYTES (regnum), fi->frame);
+         store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->frame);
        }
       if (lvalp != NULL)
        *lvalp = not_lval;
       return;
     }
-  else if (regnum == PC_REGNUM)
+  else if (regnum == PC_REGNUM && frame->next != NULL)
     {
       if (raw_buffer != NULL)
        {
-         store_address (raw_buffer, REGISTER_RAW_BYTES (regnum), fi->pc);
+         store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc);
        }
 
       /* Not sure we have to do this.  */
@@ -669,10 +722,10 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
     {
       if (raw_buffer != NULL)
        {
-         if (fi->next != NULL)
+         if (frame->next != NULL)
            {
-             store_address (raw_buffer, REGISTER_RAW_BYTES (regnum),
-                            fi->next->saved_msp);
+             store_address (raw_buffer, REGISTER_RAW_SIZE (regnum),
+                            frame->next->saved_msp);
            }
          else
            read_register_gen (MSP_REGNUM, raw_buffer);
@@ -685,7 +738,7 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
   else if (regnum < LR0_REGNUM || regnum >= LR0_REGNUM + 128)
     {
       /* These registers are not saved over procedure calls,
-        so just print out the current values.  */
+         so just print out the current values.  */
       if (raw_buffer != NULL)
        read_register_gen (regnum, raw_buffer);
       if (lvalp != NULL)
@@ -694,8 +747,8 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
        *addrp = REGISTER_BYTE (regnum);
       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)
@@ -711,70 +764,94 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lvalp)
 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;
-  CORE_ADDR lr1;                                                             
+  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 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),
-                       FRAME_FP (fi)))
+                       FRAME_FP (frame)))
     {
-      int lrnum = LR0_REGNUM + DUMMY_ARG/4;
+      int lrnum = LR0_REGNUM + DUMMY_ARG / 4;
       for (i = 0; i < DUMMY_SAVE_SR128; ++i)
-       write_register (SR_REGNUM (i + 128),read_register (lrnum++));
+       write_register (SR_REGNUM (i + 128), read_register (lrnum++));
       for (i = 0; i < DUMMY_SAVE_SR160; ++i)
-       write_register (SR_REGNUM(i+160), 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.  */
-      write_register(PC_REGNUM, read_register (lrnum++));
-      write_register(NPC_REGNUM, read_register (lrnum));
+      /* Restore the PCs and prepare to restore LR0.  */
+      write_register (PC_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.  */
-  write_register (MSP_REGNUM, fi->saved_msp);                                
-  /* Restore the register stack pointer.  */                                 
+  write_register (MSP_REGNUM, frame->saved_msp);
+  /* Restore the register stack pointer.  */
   write_register (GR1_REGNUM, gr1);
-  /* Check whether we need to fill registers.  */                            
-  lr1 = read_register (LR0_REGNUM + 1);                                      
-  if (lr1 > rfb)                                                             
-    {                                                                        
-      /* Fill.  */                                                           
+
+  /* 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)
+    {
+      /* Fill.  */
       int num_bytes = lr1 - rfb;
-      int i;                                                                 
-      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)                                     
-        {
+      int i;
+      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)
+       {
          /* Note: word is in host byte order.  */
-          word = read_memory_integer (rfb + i, 4);
-          write_register (LR0_REGNUM + ((rfb - gr1) % 0x80) + i / 4, word);
-        }                                                                    
+         word = read_memory_integer (rfb + i, 4);
+         write_register (LR0_REGNUM + ((rfb - gr1) % 0x80) + i / 4, word);
+       }
     }
-  flush_cached_frames ();                                                    
-  set_current_frame (create_new_frame (0, read_pc()));               
+  flush_cached_frames ();
 }
 
 /* Push an empty stack frame, to record the current PC, etc.  */
 
-void 
+void
 push_dummy_frame ()
 {
   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. */ 
+  /* 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)
     {
@@ -805,28 +882,154 @@ push_dummy_frame ()
   write_register (MSP_REGNUM, msp - 16 * 4);
 
   /* Save registers.  */
-  lrnum = LR0_REGNUM + DUMMY_ARG/4;
+  lrnum = LR0_REGNUM + DUMMY_ARG / 4;
   for (i = 0; i < DUMMY_SAVE_SR128; ++i)
     write_register (lrnum++, read_register (SR_REGNUM (i + 128)));
   for (i = 0; i < DUMMY_SAVE_SR160; ++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 (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)
+    internal_error ("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
-_initialize_29k()
+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
+_initialize_a29k_tdep ()
 {
   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,
-                 (char *)&rstack_high_address,
+                 (char *) &rstack_high_address,
                  "Set top address in memory of the register stack.\n\
 Attempts to access registers saved above this address will be ignored\n\
 or will produce the value -1.", &setlist),
@@ -835,8 +1038,8 @@ or will produce the value -1.", &setlist),
   /* FIXME, there should be a way to make a CORE_ADDR variable settable. */
   add_show_from_set
     (add_set_cmd ("call_scratch_address", class_support, var_uinteger,
-                 (char *)&text_end,
-"Set address in memory where small amounts of RAM can be used\n\
+                 (char *) &text_end,
+                 "Set address in memory where small amounts of RAM can be used\n\
 when making function calls into the inferior.", &setlist),
      &showlist);
 }
This page took 0.037505 seconds and 4 git commands to generate.