* config/pa/tm-hppa.h: Define lots register offsets needed by
[deliverable/binutils-gdb.git] / gdb / i960-tdep.c
index a82328a2e5e5e44400333814fde722ca41554eb7..3ea70117a2be6d921a2f648bfa5832bc8dc63fb9 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-machine dependent code for the Intel 960
-   Copyright (C) 1991 Free Software Foundation, Inc.
+   Copyright 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
    Contributed by Intel Corporation.
    examine_prologue and other parts contributed by Wind River Systems.
 
@@ -7,8 +7,8 @@ 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 1, or (at your option)
-any later version.
+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
@@ -16,28 +16,19 @@ 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; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-/* Miscellaneous i80960-dependent routines.
-   Most are called from macros defined in "tm-i960.h".  */
-
-#include <stdio.h>
-#include <signal.h>
 #include "defs.h"
-#include "param.h"
 #include "symtab.h"
 #include "value.h"
 #include "frame.h"
-#include "signame.h"
-#include "ieee-float.h"
-
-/* Structure of i960 extended floating point format.  */
+#include "floatformat.h"
+#include "target.h"
 
-const struct ext_format ext_format_i960 [] = {
-/* tot sbyte smask expbyte manbyte */
- { 12, 9,    0x80, 9,8,           4,0  },              /* i960 */
-};
+static CORE_ADDR next_insn PARAMS ((CORE_ADDR memaddr,
+                                   unsigned long *pword1,
+                                   unsigned long *pword2));
 
 /* gdb960 is always running on a non-960 host.  Check its characteristics.
    This routine must be called as part of gdb initialization.  */
@@ -65,7 +56,7 @@ check_host()
         */
        for ( i = 0; i < TYPELEN; i++ ){
                if ( types[i].hostsize != types[i].i960size ){
-                       printf("sizeof(%s) != %d:  PROCEED AT YOUR OWN RISK!\n",
+                       printf_unfiltered("sizeof(%s) != %d:  PROCEED AT YOUR OWN RISK!\n",
                                        types[i].typename, types[i].i960size );
                }
 
@@ -135,7 +126,7 @@ static CORE_ADDR
 examine_prologue (ip, limit, frame_addr, fsr)
      register CORE_ADDR ip;
      register CORE_ADDR limit;
-     FRAME_ADDR frame_addr;
+     CORE_ADDR frame_addr;
      struct frame_saved_regs *fsr;
 {
   register CORE_ADDR next_ip;
@@ -308,7 +299,7 @@ skip_prologue (ip)
   sal = find_pc_line (ip, 0);
   limit = (sal.end) ? sal.end : 0xffffffff;
 
-  return (examine_prologue (ip, limit, (FRAME_ADDR) 0, &saved_regs_dummy));
+  return (examine_prologue (ip, limit, (CORE_ADDR) 0, &saved_regs_dummy));
 }
 
 /* Put here the code to store, into a struct frame_saved_regs,
@@ -339,7 +330,7 @@ frame_find_saved_regs (fi, fsr)
       cache_fsr = (struct frame_saved_regs *)
                  obstack_alloc (&frame_cache_obstack,
                                 sizeof (struct frame_saved_regs));
-      bzero (cache_fsr, sizeof (struct frame_saved_regs));
+      memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
       fi->fsr = cache_fsr;
 
       /* Find the start and end of the function prologue.  If the PC
@@ -394,7 +385,6 @@ CORE_ADDR
 frame_args_address (fi, must_be_correct)
      struct frame_info *fi;
 {
-  register FRAME frame;
   struct frame_saved_regs fsr;
   CORE_ADDR ap;
 
@@ -402,18 +392,20 @@ frame_args_address (fi, must_be_correct)
      the saved value.  If the frame is current and we are being sloppy,
      return the value of g14.  Otherwise, return zero.  */
 
-  frame = FRAME_INFO_ID (fi);
   get_frame_saved_regs (fi, &fsr);
   if (fsr.regs[G14_REGNUM])
     ap = read_memory_integer (fsr.regs[G14_REGNUM],4);
-  else {
-    if (must_be_correct)
-      return 0;                        /* Don't cache this result */
-    if (get_next_frame (frame))
-      ap = 0;
-    else
-      ap = read_register (G14_REGNUM);
-  }
+  else
+    {
+      if (must_be_correct)
+       return 0;                       /* Don't cache this result */
+      if (get_next_frame (fi))
+       ap = 0;
+      else
+       ap = read_register (G14_REGNUM);
+      if (ap == 0)
+       ap = fi->frame;
+    }
   fi->arg_pointer = ap;                /* Cache it for next time */
   return ap;
 }
@@ -425,7 +417,6 @@ CORE_ADDR
 frame_struct_result_address (fi)
      struct frame_info *fi;
 {
-  register FRAME frame;
   struct frame_saved_regs fsr;
   CORE_ADDR ap;
 
@@ -437,16 +428,17 @@ frame_struct_result_address (fi)
      the function prologue, and only use the current value if we have
      no saved value and are at TOS?   -- gnu@cygnus.com */
 
-  frame = FRAME_INFO_ID (fi);
-  if (get_next_frame (frame)) {
-    get_frame_saved_regs (fi, &fsr);
-    if (fsr.regs[G13_REGNUM])
-      ap = read_memory_integer (fsr.regs[G13_REGNUM],4);
-    else
-      ap = 0;
-  } else {
+  if (get_next_frame (fi))
+    {
+      get_frame_saved_regs (fi, &fsr);
+      if (fsr.regs[G13_REGNUM])
+       ap = read_memory_integer (fsr.regs[G13_REGNUM],4);
+      else
+       ap = 0;
+    }
+  else
     ap = read_register (G13_REGNUM);
-  }
+
   return ap;
 }
 
@@ -464,20 +456,17 @@ CORE_ADDR
 leafproc_return (ip)
      CORE_ADDR ip;     /* ip from currently executing function */
 {
-  int i;
-  register struct misc_function *mf;
+  register struct minimal_symbol *msymbol;
   char *p;
   int dst;
   unsigned int insn1, insn2;
   CORE_ADDR return_addr;
-  char *index ();
 
-  if ((i = find_pc_misc_function (ip)) >= 0)
+  if ((msymbol = lookup_minimal_symbol_by_pc (ip)) != NULL)
     {
-      mf = &misc_function_vector[i];
-      if ((p = index (mf->name, '.')) && !strcmp (p, ".lf"))
+      if ((p = strchr(SYMBOL_NAME (msymbol), '.')) && STREQ (p, ".lf"))
        {
-         if (next_insn (mf->address, &insn1, &insn2)
+         if (next_insn (SYMBOL_VALUE_ADDRESS (msymbol), &insn1, &insn2)
              && (insn1 & 0xff87ffff) == 0x5c80161e       /* mov g14, gx */
              && (dst = REG_SRCDST (insn1)) <= G0_REGNUM + 7)
            {
@@ -486,7 +475,8 @@ leafproc_return (ip)
                 the return address from g14; otherwise, read it
                 from the register into which g14 was moved.  */
 
-             return_addr = read_register ((ip == mf->address)
+             return_addr =
+                 read_register ((ip == SYMBOL_VALUE_ADDRESS (msymbol))
                                           ? G14_REGNUM : dst);
 
              /* We know we are in a leaf procedure, but we don't know
@@ -499,7 +489,7 @@ leafproc_return (ip)
 
              if (!next_insn (return_addr, &insn1, &insn2)
                  || (insn1 & 0xff000000) != 0xa000000   /* ret */
-                 || find_pc_misc_function (return_addr) != i)
+                 || lookup_minimal_symbol_by_pc (return_addr) != msymbol)
                return (return_addr);
            }
        }
@@ -517,16 +507,15 @@ leafproc_return (ip)
 
 CORE_ADDR
 saved_pc_after_call (frame)
-     FRAME frame;
+     struct frame_info *frame;
 {
   CORE_ADDR saved_pc;
-  CORE_ADDR get_frame_pc ();
 
   saved_pc = leafproc_return (get_frame_pc (frame));
   if (!saved_pc)
     saved_pc = FRAME_SAVED_PC (frame);
 
-  return (saved_pc);
+  return saved_pc;
 }
 
 /* Discard from the stack the innermost frame,
@@ -541,7 +530,7 @@ pop_frame ()
   struct frame_saved_regs fsr;
   char local_regs_buf[16 * 4];
 
-  current_fi = get_frame_info (get_current_frame ());
+  current_fi = get_current_frame ();
 
   /* First, undo what the hardware does when we return.
      If this is a non-leaf procedure, restore local registers from
@@ -552,7 +541,7 @@ pop_frame ()
   if (!leaf_return_addr)
     {
       /* Non-leaf procedure.  Restore local registers, incl IP.  */
-      prev_fi = get_frame_info (get_prev_frame (FRAME_INFO_ID (current_fi)));
+      prev_fi = get_prev_frame (current_fi);
       read_memory (prev_fi->frame, local_regs_buf, sizeof (local_regs_buf));
       write_register_bytes (REGISTER_BYTE (R0_REGNUM), local_regs_buf, 
                            sizeof (local_regs_buf));
@@ -578,69 +567,203 @@ pop_frame ()
      and make it the current frame.  */
 
   flush_cached_frames ();
-  set_current_frame (create_new_frame (read_register (FP_REGNUM), read_pc ()));
 }
 
-/* Print out text describing a "signal number" with which the i80960 halted.
-  
-   See the file "fault.c" in the nindy monitor source code for a list
-   of stop codes.  */
+/* Given a 960 stop code (fault or trace), return the signal which
+   corresponds.  */
 
-void
-print_fault( siggnal )
-    int siggnal;       /* Signal number, as returned by target_wait() */
+enum target_signal
+i960_fault_to_signal (fault)
+    int fault;
+{
+  switch (fault)
+    {
+    case 0: return TARGET_SIGNAL_BUS; /* parallel fault */
+    case 1: return TARGET_SIGNAL_UNKNOWN;
+    case 2: return TARGET_SIGNAL_ILL; /* operation fault */
+    case 3: return TARGET_SIGNAL_FPE; /* arithmetic fault */
+    case 4: return TARGET_SIGNAL_FPE; /* floating point fault */
+
+      /* constraint fault.  This appears not to distinguish between
+        a range constraint fault (which should be SIGFPE) and a privileged
+        fault (which should be SIGILL).  */
+    case 5: return TARGET_SIGNAL_ILL;
+
+    case 6: return TARGET_SIGNAL_SEGV; /* virtual memory fault */
+
+      /* protection fault.  This is for an out-of-range argument to
+        "calls".  I guess it also could be SIGILL. */
+    case 7: return TARGET_SIGNAL_SEGV;
+
+    case 8: return TARGET_SIGNAL_BUS; /* machine fault */
+    case 9: return TARGET_SIGNAL_BUS; /* structural fault */
+    case 0xa: return TARGET_SIGNAL_ILL; /* type fault */
+    case 0xb: return TARGET_SIGNAL_UNKNOWN; /* reserved fault */
+    case 0xc: return TARGET_SIGNAL_BUS; /* process fault */
+    case 0xd: return TARGET_SIGNAL_SEGV; /* descriptor fault */
+    case 0xe: return TARGET_SIGNAL_BUS; /* event fault */
+    case 0xf: return TARGET_SIGNAL_UNKNOWN; /* reserved fault */
+    case 0x10: return TARGET_SIGNAL_TRAP; /* single-step trace */
+    case 0x11: return TARGET_SIGNAL_TRAP; /* branch trace */
+    case 0x12: return TARGET_SIGNAL_TRAP; /* call trace */
+    case 0x13: return TARGET_SIGNAL_TRAP; /* return trace */
+    case 0x14: return TARGET_SIGNAL_TRAP; /* pre-return trace */
+    case 0x15: return TARGET_SIGNAL_TRAP; /* supervisor call trace */
+    case 0x16: return TARGET_SIGNAL_TRAP; /* breakpoint trace */
+    default: return TARGET_SIGNAL_UNKNOWN;
+    }
+}
+
+/****************************************/
+/* MEM format                          */
+/****************************************/
+
+struct tabent {
+       char    *name;
+       char    numops;
+};
+
+static int                             /* returns instruction length: 4 or 8 */
+mem( memaddr, word1, word2, noprint )
+    unsigned long memaddr;
+    unsigned long word1, word2;
+    int noprint;               /* If TRUE, return instruction length, but
+                                  don't output any text.  */
 {
-       static char unknown[] = "Unknown fault or trace";
-       static char *sigmsgs[] = {
-               /* FAULTS */
-               "parallel fault",       /* 0x00 */
-               unknown,                /* 0x01 */
-               "operation fault",      /* 0x02 */
-               "arithmetic fault",     /* 0x03 */
-               "floating point fault", /* 0x04 */
-               "constraint fault",     /* 0x05 */
-               "virtual memory fault", /* 0x06 */
-               "protection fault",     /* 0x07 */
-               "machine fault",        /* 0x08 */
-               "structural fault",     /* 0x09 */
-               "type fault",           /* 0x0a */
-               "reserved (0xb) fault", /* 0x0b */
-               "process fault",        /* 0x0c */
-               "descriptor fault",     /* 0x0d */
-               "event fault",          /* 0x0e */
-               "reserved (0xf) fault", /* 0x0f */
-
-               /* TRACES */
-               "single-step trace",    /* 0x10 */
-               "branch trace",         /* 0x11 */
-               "call trace",           /* 0x12 */
-               "return trace",         /* 0x13 */
-               "pre-return trace",     /* 0x14 */
-               "supervisor call trace",/* 0x15 */
-               "breakpoint trace",     /* 0x16 */
+       int i, j;
+       int len;
+       int mode;
+       int offset;
+       const char *reg1, *reg2, *reg3;
+
+       /* This lookup table is too sparse to make it worth typing in, but not
+        * so large as to make a sparse array necessary.  We allocate the
+        * table at runtime, initialize all entries to empty, and copy the
+        * real ones in from an initialization table.
+        *
+        * NOTE: In this table, the meaning of 'numops' is:
+        *       1: single operand
+        *       2: 2 operands, load instruction
+        *      -2: 2 operands, store instruction
+        */
+       static struct tabent *mem_tab = NULL;
+/* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table.  */
+#define MEM_MIN        0x80
+#define MEM_MAX        0xcf
+#define MEM_SIZ        ((MEM_MAX-MEM_MIN+1) * sizeof(struct tabent))
+
+       static struct { int opcode; char *name; char numops; } mem_init[] = {
+               0x80,   "ldob",  2,
+               0x82,   "stob", -2,
+               0x84,   "bx",    1,
+               0x85,   "balx",  2,
+               0x86,   "callx", 1,
+               0x88,   "ldos",  2,
+               0x8a,   "stos", -2,
+               0x8c,   "lda",   2,
+               0x90,   "ld",    2,
+               0x92,   "st",   -2,
+               0x98,   "ldl",   2,
+               0x9a,   "stl",  -2,
+               0xa0,   "ldt",   2,
+               0xa2,   "stt",  -2,
+               0xb0,   "ldq",   2,
+               0xb2,   "stq",  -2,
+               0xc0,   "ldib",  2,
+               0xc2,   "stib", -2,
+               0xc8,   "ldis",  2,
+               0xca,   "stis", -2,
+               0,      NULL,   0
        };
-#      define NUMMSGS ((int)( sizeof(sigmsgs) / sizeof(sigmsgs[0]) ))
 
-       if (siggnal < NSIG) {
-             printf ("\nProgram received signal %d, %s\n",
-                     siggnal,
-                     sys_siglist[siggnal]);
+       if ( mem_tab == NULL ){
+               mem_tab = (struct tabent *) xmalloc( MEM_SIZ );
+               memset( mem_tab, '\0', MEM_SIZ );
+               for ( i = 0; mem_init[i].opcode != 0; i++ ){
+                       j = mem_init[i].opcode - MEM_MIN;
+                       mem_tab[j].name = mem_init[i].name;
+                       mem_tab[j].numops = mem_init[i].numops;
+               }
+       }
+
+       i = ((word1 >> 24) & 0xff) - MEM_MIN;
+       mode = (word1 >> 10) & 0xf;
+
+       if ( (mem_tab[i].name != NULL)          /* Valid instruction */
+       &&   ((mode == 5) || (mode >=12)) ){    /* With 32-bit displacement */
+               len = 8;
        } else {
-               /* The various target_wait()s bias the 80960 "signal number"
-                  by adding NSIG to it, so it won't get confused with any
-                  of the Unix signals elsewhere in GDB.  We need to
-                  "unbias" it before using it.  */
-               siggnal -= NSIG;
-
-               printf("Program stopped for reason #%d: %s.\n", siggnal,
-                               (siggnal < NUMMSGS && siggnal >= 0)?
-                               sigmsgs[siggnal] : unknown );
+               len = 4;
+       }
+
+       if ( noprint ){
+               return len;
        }
+       abort ();
 }
 
-/* Initialization stub */
+/* Read the i960 instruction at 'memaddr' and return the address of 
+   the next instruction after that, or 0 if 'memaddr' is not the
+   address of a valid instruction.  The first word of the instruction
+   is stored at 'pword1', and the second word, if any, is stored at
+   'pword2'.  */
+
+static CORE_ADDR
+next_insn (memaddr, pword1, pword2)
+     unsigned long *pword1, *pword2;
+     CORE_ADDR memaddr;
+{
+  int len;
+  char buf[8];
+
+  /* Read the two (potential) words of the instruction at once,
+     to eliminate the overhead of two calls to read_memory ().
+     FIXME: Loses if the first one is readable but the second is not
+     (e.g. last word of the segment).  */
 
+  read_memory (memaddr, buf, 8);
+  *pword1 = extract_unsigned_integer (buf, 4);
+  *pword2 = extract_unsigned_integer (buf + 4, 4);
+
+  /* Divide instruction set into classes based on high 4 bits of opcode*/
+
+  switch ((*pword1 >> 28) & 0xf)
+    {
+    case 0x0:
+    case 0x1:  /* ctrl */
+
+    case 0x2:
+    case 0x3:  /* cobr */
+
+    case 0x5:
+    case 0x6:
+    case 0x7:  /* reg */
+      len = 4;
+      break;
+
+    case 0x8:
+    case 0x9:
+    case 0xa:
+    case 0xb:
+    case 0xc:
+      len = mem (memaddr, *pword1, *pword2, 1);
+      break;
+
+    default:   /* invalid instruction */
+      len = 0;
+      break;
+    }
+
+  if (len)
+    return memaddr + len;
+  else
+    return 0;
+}
+
+void
 _initialize_i960_tdep ()
 {
   check_host ();
+
+  tm_print_insn = print_insn_i960;
 }
This page took 0.030087 seconds and 4 git commands to generate.