1999-01-19 Fernando Nasser <fnasser@totem.to.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / arc-tdep.c
index e76aa93770b347fcddc25bc6296cfaaa252809c3..92957700f9c53c274e5c4353218b644cc75024c6 100644 (file)
@@ -1,5 +1,5 @@
 /* ARC target-dependent stuff.
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1997 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +15,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "frame.h"
@@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcmd.h"
 
 /* Current CPU, set with the "set cpu" command.  */
+static int arc_bfd_mach_type;
 char *arc_cpu_type;
 char *tmp_arc_cpu_type;
 
@@ -36,9 +37,6 @@ struct {
   int value;
 } arc_cpu_type_table[] = {
   { "base", bfd_mach_arc_base },
-  { "host", bfd_mach_arc_host },
-  { "graphics", bfd_mach_arc_graphics },
-  { "audio", bfd_mach_arc_audio },
   { NULL, 0 }
 };
 
@@ -53,7 +51,8 @@ int debug_pipeline_p;
 
 #define OPMASK 0xf8000000
 
-/* Instruction field accessor macros.  */
+/* Instruction field accessor macros.
+   See the Programmer's Reference Manual.  */
 #define X_OP(i) (((i) >> 27) & 0x1f)
 #define X_A(i) (((i) >> 21) & 0x3f)
 #define X_B(i) (((i) >> 15) & 0x3f)
@@ -108,14 +107,25 @@ codestream_fill (peek_flag)
   codestream_next_addr += CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]);
   codestream_off = 0;
   codestream_cnt = CODESTREAM_BUFSIZ;
-  /* FIXME: need to handle byte order differences.  */
   read_memory (codestream_addr, (char *) codestream_buf,
               CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]));
+  /* FIXME: check return code?  */
+
+  /* Handle byte order differences.  */
+  if (HOST_BYTE_ORDER != TARGET_BYTE_ORDER)
+    {
+      register unsigned int i, j, n = sizeof (codestream_buf[0]);
+      register char tmp, *p;
+      for (i = 0, p = (char *) codestream_buf; i < CODESTREAM_BUFSIZ;
+          ++i, p += n)
+       for (j = 0; j < n / 2; ++j)
+         tmp = p[j], p[j] = p[n - 1 - j], p[n - 1 - j] = tmp;
+    }
   
   if (peek_flag)
-    return (codestream_peek());
+    return codestream_peek ();
   else
-    return (codestream_get());
+    return codestream_get ();
 }
 
 static void
@@ -126,10 +136,12 @@ codestream_seek (place)
   codestream_next_addr *= CODESTREAM_BUFSIZ;
   codestream_cnt = 0;
   codestream_fill (1);
-  while (codestream_tell() != place)
+  while (codestream_tell () != place)
     codestream_get ();
 }
 
+/* This function is currently unused but leave in for now.  */
+
 static void
 codestream_read (buf, count)
      unsigned int *buf;
@@ -142,8 +154,7 @@ codestream_read (buf, count)
     *p++ = codestream_get ();
 }
 \f
-/* Set up prologue scanning and return the first insn,
-   not including the "sub sp,sp,32" of a stdarg function.  */
+/* Set up prologue scanning and return the first insn.  */
 
 static unsigned int
 setup_prologue_scan (pc)
@@ -154,12 +165,6 @@ setup_prologue_scan (pc)
   codestream_seek (pc);
   insn = codestream_get ();
 
-  /* The authority for what appears here is the home-grown ABI.  */
-
-  /* First insn may be "sub sp,sp,32" if stdarg fn.  */
-  if (insn == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 32))
-    insn = codestream_get ();
-
   return insn;
 }
 
@@ -176,17 +181,30 @@ arc_get_frame_setup (pc)
 {
   unsigned int insn;
   /* Size of frame or -1 if unrecognizable prologue.  */
-  int n = -1;
+  int frame_size = -1;
+  /* An initial "sub sp,sp,N" may or may not be for a stdarg fn.  */
+  int maybe_stdarg_decr = -1;
 
   insn = setup_prologue_scan (pc);
 
+  /* The authority for what appears here is the home-grown ABI.
+     The most recent version is 1.2.  */
+
+  /* First insn may be "sub sp,sp,N" if stdarg fn.  */
+  if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
+      == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
+    {
+      maybe_stdarg_decr = X_D (insn);
+      insn = codestream_get ();
+    }
+
   if ((insn & BUILD_INSN (-1, 0, -1, -1, -1))  /* st blink,[sp,4] */
       == BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
     {
       insn = codestream_get ();
       /* Frame may not be necessary, even though blink is saved.
         At least this is something we recognize.  */
-      n = 0;
+      frame_size = 0;
     }
 
   if ((insn & BUILD_INSN (-1, 0, -1, -1, -1))          /* st fp,[sp] */
@@ -197,18 +215,18 @@ arc_get_frame_setup (pc)
               != BUILD_INSN (12, FP_REGNUM, SP_REGNUM, SP_REGNUM, 0))
        return -1;
 
-      /* Check for stack adjustment sub sp,sp,nnn.  */
+      /* Check for stack adjustment sub sp,sp,N.  */
       insn = codestream_peek ();
       if ((insn & BUILD_INSN (-1, -1, -1, 0, 0))
          == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, 0, 0))
        {
          if (LIMM_P (X_C (insn)))
-           n = codestream_get ();
+           frame_size = codestream_get ();
          else if (SHIMM_P (X_C (insn)))
-           n = X_D (insn);
+           frame_size = X_D (insn);
          else
            return -1;
-         if (n < 0)
+         if (frame_size < 0)
            return -1;
 
           codestream_get ();
@@ -222,11 +240,20 @@ arc_get_frame_setup (pc)
       /* Frameless fn.  */
       else
        {
-         n = 0;
+         frame_size = 0;
        }
     }
 
-  return n;
+  /* If we found a "sub sp,sp,N" and nothing else, it may or may not be a
+     stdarg fn.  The stdarg decrement is not treated as part of the frame size,
+     so we have a dilemma: what do we return?  For now, if we get a
+     "sub sp,sp,N" and nothing else assume this isn't a stdarg fn.  One way
+     to fix this completely would be to add a bit to the function descriptor
+     that says the function is a stdarg function.  */
+
+  if (frame_size < 0 && maybe_stdarg_decr > 0)
+    return maybe_stdarg_decr;
+  return frame_size;
 }
 
 /* Given a pc value, skip it forward past the function prologue by
@@ -283,13 +310,21 @@ arc_frame_saved_pc (frame)
       return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4));
     }
 
-  /* If the first insn is "st blink,[sp,4]" we can get blink from there.
+  /* The authority for what appears here is the home-grown ABI.
+     The most recent version is 1.2.  */
+
+  insn = setup_prologue_scan (func_start);
+
+  /* First insn may be "sub sp,sp,N" if stdarg fn.  */
+  if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
+      == BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
+    insn = codestream_get ();
+
+  /* If the next insn is "st blink,[sp,4]" we can get blink from there.
      Otherwise this is a leaf function and we can use blink.  Note that
      this still allows for the case where a leaf function saves/clobbers/
      restores blink.  */
 
-  insn = setup_prologue_scan (func_start);
-
   if ((insn & BUILD_INSN (-1, 0, -1, -1, -1))  /* st blink,[sp,4] */
       != BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
     return ARC_PC_TO_REAL_ADDRESS (read_register (BLINK_REGNUM));
@@ -473,12 +508,6 @@ get_insn_type (insn, pc, target)
     }
 }
 
-/* Non-zero if we just simulated a single-step.  This is needed because we
-   cannot remove the breakpoints in the inferior process until after the
-   `wait' in `wait_for_inferior'.  */
-
-int one_stepped;
-
 /* single_step() is called just before we want to resume the inferior, if we
    want to single-step it but there is no hardware or kernel single-step
    support.  We find all the possible targets of the coming instruction and
@@ -488,15 +517,16 @@ int one_stepped;
    set up a simulated single-step, we undo our damage.  */
 
 void
-single_step (ignore)
-     int ignore; /* sig, but we don't need it */
+arc_software_single_step (ignore, insert_breakpoints_p)
+     enum target_signal ignore; /* sig but we don't need it */
+     int insert_breakpoints_p;
 {
   static CORE_ADDR next_pc, target;
   static int brktrg_p;
   typedef char binsn_quantum[BREAKPOINT_MAX];
   static binsn_quantum break_mem[2];
 
-  if (!one_stepped)
+  if (insert_breakpoints_p)
     {
       insn_type type;
       CORE_ADDR pc;
@@ -523,8 +553,6 @@ single_step (ignore)
          target_insert_breakpoint (target, break_mem[1]);
        }
 
-      /* We are ready to let it go.  */
-      one_stepped = 1;
     }
   else
     {
@@ -537,8 +565,6 @@ single_step (ignore)
       /* Fix the pc.  */
       stop_pc -= DECR_PC_AFTER_BREAK;
       write_pc (stop_pc);
-
-      one_stepped = 0;
     }
 }
 \f
@@ -574,6 +600,30 @@ get_longjmp_target(pc)
 }
 #endif /* GET_LONGJMP_TARGET */
 \f
+/* Disassemble one instruction.  */
+
+static int
+arc_print_insn (vma, info)
+     bfd_vma vma;
+     disassemble_info *info;
+{
+  static int current_mach;
+  static int current_endian;
+  static disassembler_ftype current_disasm;
+
+  if (current_disasm == NULL
+      || arc_bfd_mach_type != current_mach
+      || TARGET_BYTE_ORDER != current_endian)
+    {
+      current_mach = arc_bfd_mach_type;
+      current_endian = TARGET_BYTE_ORDER;
+      current_disasm = arc_get_disassembler (current_mach,
+                                            current_endian == BIG_ENDIAN);
+    }
+
+  return (*current_disasm) (vma, info);
+}
+\f
 /* Command to set cpu type.  */
 
 void
@@ -627,8 +677,7 @@ arc_set_cpu_type (str)
       if (strcasecmp (str, arc_cpu_type_table[i].name) == 0)
        {
          arc_cpu_type = str;
-         tm_print_insn = arc_get_disassembler (arc_cpu_type_table[i].value,
-                                               TARGET_BYTE_ORDER == BIG_ENDIAN);
+         arc_bfd_mach_type = arc_cpu_type_table[i].value;
          return 1;
        }
     }
@@ -680,6 +729,5 @@ A negative value disables the timer.",
                   &setlist);
   c = add_show_from_set (c, &showlist);
 
-  /* FIXME: must be done after for now.  */
-  tm_print_insn = arc_get_disassembler (bfd_mach_arc_base, 1 /*FIXME*/);
+  tm_print_insn = arc_print_insn;
 }
This page took 0.026764 seconds and 4 git commands to generate.