* gdb.base/a2-run.exp: Add arm-*-coff setup_xfails for cases
[deliverable/binutils-gdb.git] / gdb / i960-tdep.c
index 013bf8261e4ea92f54f6579b68fae72eebad140e..a125ec209e211fc7f54b14f706481124faf7f126 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.
 
@@ -17,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
-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 "symtab.h"
@@ -25,6 +25,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "frame.h"
 #include "floatformat.h"
 #include "target.h"
+#include "gdbcore.h"
+
+static CORE_ADDR next_insn PARAMS ((CORE_ADDR memaddr,
+                                   unsigned int *pword1,
+                                   unsigned int *pword2));
 
 /* gdb960 is always running on a non-960 host.  Check its characteristics.
    This routine must be called as part of gdb initialization.  */
@@ -610,10 +615,203 @@ i960_fault_to_signal (fault)
     }
 }
 
-/* Initialization stub */
+/****************************************/
+/* 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.  */
+{
+       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
+       };
+
+       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 {
+               len = 4;
+       }
+
+       if ( noprint ){
+               return len;
+       }
+       abort ();
+}
+
+/* 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 int *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;
+}
+
+/* 'start_frame' is a variable in the MON960 runtime startup routine
+   that contains the frame pointer of the 'start' routine (the routine
+   that calls 'main').  By reading its contents out of remote memory,
+   we can tell where the frame chain ends:  backtraces should halt before
+   they display this frame.  */
+
+int
+mon960_frame_chain_valid (chain, curframe)
+    unsigned int chain;
+    struct frame_info *curframe;
+{
+       struct symbol *sym;
+       struct minimal_symbol *msymbol;
+
+       /* crtmon960.o is an assembler module that is assumed to be linked
+        * first in an i80960 executable.  It contains the true entry point;
+        * it performs startup up initialization and then calls 'main'.
+        *
+        * 'sf' is the name of a variable in crtmon960.o that is set
+        *      during startup to the address of the first frame.
+        *
+        * 'a' is the address of that variable in 80960 memory.
+        */
+       static char sf[] = "start_frame";
+       CORE_ADDR a;
+
+
+       chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
+                          contain return status info in them.  */
+       if ( chain == 0 ){
+               return 0;
+       }
+
+       sym = lookup_symbol(sf, 0, VAR_NAMESPACE, (int *)NULL, 
+                                 (struct symtab **)NULL);
+       if ( sym != 0 ){
+               a = SYMBOL_VALUE (sym);
+       } else {
+               msymbol = lookup_minimal_symbol (sf, NULL, NULL);
+               if (msymbol == NULL)
+                       return 0;
+               a = SYMBOL_VALUE_ADDRESS (msymbol);
+       }
+
+       return ( chain != read_memory_integer(a,4) );
+}
 
 void
 _initialize_i960_tdep ()
 {
   check_host ();
+
+  tm_print_insn = print_insn_i960;
 }
This page took 0.026232 seconds and 4 git commands to generate.