gdb/
[deliverable/binutils-gdb.git] / gdb / m88k-tdep.c
index 4927878010517e7b53c806649fd2c874982d5359..1e4c546b0aef1617e36b9186f2210a79596894d2 100644 (file)
-/* Copyright (C) 1988, 1990 Free Software Foundation, Inc.
+/* Target-dependent code for the Motorola 88000 series.
 
-This file is part of GDB.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   Free Software Foundation, Inc.
 
-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 file is part of GDB.
 
-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 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 3 of the License, or
+   (at your option) any later version.
 
-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.  */
+   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, see <http://www.gnu.org/licenses/>.  */
 
-#include <stdio.h>
 #include "defs.h"
-#include "param.h"
+#include "arch-utils.h"
+#include "dis-asm.h"
 #include "frame.h"
-#include "inferior.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "regcache.h"
+#include "regset.h"
+#include "symtab.h"
+#include "trad-frame.h"
 #include "value.h"
 
-#ifdef USG
-#include <sys/types.h>
-#endif
+#include "gdb_assert.h"
+#include "gdb_string.h"
 
-#include <sys/param.h>
-#include <sys/dir.h>
-#include <signal.h>
-#include "gdbcore.h"
-#include <sys/user.h>
-#ifndef USER                   /* added to support BCS ptrace_user */
+#include "m88k-tdep.h"
 
-#define USER ptrace_user
-#endif
-#include <sys/ioctl.h>
-#include <fcntl.h>
+/* Fetch the instruction at PC.  */
 
-#ifdef COFF_ENCAPSULATE
-#include "a.out.encap.h"
-#else
-#include <a.out.h>
-#endif
-
-#include <sys/file.h>
-#include <sys/stat.h>
+static unsigned long
+m88k_fetch_instruction (CORE_ADDR pc, enum bfd_endian byte_order)
+{
+  return read_memory_unsigned_integer (pc, 4, byte_order);
+}
 
-#include "symtab.h"
-#include "setjmp.h"
-#include "value.h"
+/* Register information.  */
 
-int stack_error;
-jmp_buf stack_jmp;
+/* Return the name of register REGNUM.  */
 
-void
-tdesc_error_function  (environment, continuable, message)
-dc_word_t environment;
-dc_boolean_t continuable;
-char *message;
+static const char *
+m88k_register_name (struct gdbarch *gdbarch, int regnum)
 {
-  if (stack_error) longjmp (stack_jmp, 1);
-  if (!continuable)
-    {
-      printf("%s\n",message);
-      abort();
-    }
-}
+  static char *register_names[] =
+  {
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
+    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+    "epsr", "fpsr", "fpcr", "sxip", "snip", "sfip"
+  };
 
+  if (regnum >= 0 && regnum < ARRAY_SIZE (register_names))
+    return register_names[regnum];
 
-void
-tdesc_read_function (environment, memory, length, buffer)
-dc_word_t environment;
-dc_word_t memory;
-int length;
-char *buffer;
-{
-  int ptrace_code;
-  errno = 0;
-  if (memory < 2048) 
-#if 0
-    /* This is a no-op!  It sets buffer, but doesn't do anything to
-       what buffer points to.  What does this function do anyway?
-       And this is wrong for cross-debugging.  */
-    buffer = ptrace (3, inferior_pid, memory, 0);
-#else
-    return;
-#endif
-  else
-    read_memory (memory, buffer, length);
+  return NULL;
 }
 
-/* Map function for tdesc */
-void
-tdesc_map_function (map_env, loc, map_info_in, map_info_out)
-dc_word_t map_env;
-dc_word_t loc;
-dc_map_info_in_t map_info_in;
-dc_map_info_out_t *map_info_out;
-{
-int map_flags = DC_MIO_ENTRY_POINT | DC_MIO_IMPLICIT_PROLOGUE_END;
-int entry_point = get_pc_function_start(loc);
-map_info_out->flags = map_flags;
-map_info_out->entry_point = entry_point;
-}
+/* Return the GDB type object for the "standard" data type of data in
+   register REGNUM.  */
 
-dc_handle_t tdesc_handle;
+static struct type *
+m88k_register_type (struct gdbarch *gdbarch, int regnum)
+{
+  /* SXIP, SNIP, SFIP and R1 contain code addresses.  */
+  if ((regnum >= M88K_SXIP_REGNUM && regnum <= M88K_SFIP_REGNUM)
+      || regnum == M88K_R1_REGNUM)
+    return builtin_type (gdbarch)->builtin_func_ptr;
 
-extern int debug_info;
+  /* R30 and R31 typically contains data addresses.  */
+  if (regnum == M88K_R30_REGNUM || regnum == M88K_R31_REGNUM)
+    return builtin_type (gdbarch)->builtin_data_ptr;
 
-void
-init_tdesc ()
-{
-  tdesc_handle = dc_initiate (debug_info, tdesc_error_function,
-                             0,tdesc_read_function,0,0,0,0,0,tdesc_map_function,0);
-} 
-dc_dcontext_t current_context;
-  
-/* setup current context, called from wait_for_inferior */
-
-dc_dcontext_t
-init_dcontext()
-{
-  dc_word_t reg_info[DC_NUM_REG];
-  dc_word_t reg_flags[2] = {0,-1};
-  dc_word_t aux_info[DC_NUM_AUX];
-  dc_word_t aux_flags[2] = {0,-1};
-  dc_exactness_t loc_exact = DC_NO;
-  dc_word_t psr_info;
-  dc_boolean_t psr_ind = 0;
-  dc_word_t psr_flags[2] = {0,-1};
-
-  bcopy (&registers, reg_info, DC_NUM_REG * 4);
-  aux_info[DC_AUX_LOC] =  read_register(SXIP_REGNUM);
-  aux_info[DC_AUX_SXIP] = read_register(SXIP_REGNUM);
-  aux_info[DC_AUX_SNIP] = read_register(SNIP_REGNUM);
-  aux_info[DC_AUX_SFIP] = read_register(SFIP_REGNUM);
-  aux_info[DC_AUX_FPSR] = read_register(FPSR_REGNUM);
-  aux_info[DC_AUX_FPCR] = read_register(FPCR_REGNUM);
-
-  psr_info = read_register(PSR_REGNUM);
-
-  return dc_make_dcontext (tdesc_handle, reg_info, reg_flags, aux_info,
-                         aux_flags, loc_exact, psr_info, psr_ind, psr_flags);
+  return builtin_type (gdbarch)->builtin_int32;
 }
+\f
 
-
-dc_dcontext_t
-get_prev_context (context)
-  dc_dcontext_t context;
+static CORE_ADDR
+m88k_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
-  return current_context = dc_previous_dcontext (context); 
+  /* All instructures are 4-byte aligned.  The lower 2 bits of SXIP,
+     SNIP and SFIP are used for special purposes: bit 0 is the
+     exception bit and bit 1 is the valid bit.  */
+  return addr & ~0x3;
 }
-  
 
+/* Use the program counter to determine the contents and size of a
+   breakpoint instruction.  Return a pointer to a string of bytes that
+   encode a breakpoint instruction, store the length of the string in
+   *LEN and optionally adjust *PC to point to the correct memory
+   location for inserting the breakpoint.  */
+   
+static const gdb_byte *
+m88k_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len)
+{
+  /* tb 0,r0,511 */
+  static gdb_byte break_insn[] = { 0xf0, 0x00, 0xd1, 0xff };
 
+  *len = sizeof (break_insn);
+  return break_insn;
+}
 
-/* Determine frame base for this file's frames.  This will be either
-   the CFA or the old style FP_REGNUM; the symtab for the current pc's
-   file has the information                                          */
+static CORE_ADDR
+m88k_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  CORE_ADDR pc;
 
-CORE_ADDR
-get_frame_base(pc)
-CORE_ADDR pc;
+  pc = frame_unwind_register_unsigned (next_frame, M88K_SXIP_REGNUM);
+  return m88k_addr_bits_remove (gdbarch, pc);
+}
+
+static void
+m88k_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
-  struct symtab *this_file = find_pc_symtab(pc);
-  int coffsem_frame_position;
-  
-  /* If this_file is null, there's a good chance the file was compiled
-     without -g.  If that's the case, use CFA (canonical frame addr) 
-     as the default frame pointer.                                 */
+  /* According to the MC88100 RISC Microprocessor User's Manual,
+     section 6.4.3.1.2:
+
+     "... can be made to return to a particular instruction by placing
+     a valid instruction address in the SNIP and the next sequential
+     instruction address in the SFIP (with V bits set and E bits
+     clear).  The rte resumes execution at the instruction pointed to
+     by the SNIP, then the SFIP."
+
+     The E bit is the least significant bit (bit 0).  The V (valid)
+     bit is bit 1.  This is why we logical or 2 into the values we are
+     writing below.  It turns out that SXIP plays no role when
+     returning from an exception so nothing special has to be done
+     with it.  We could even (presumably) give it a totally bogus
+     value.  */
+
+  regcache_cooked_write_unsigned (regcache, M88K_SXIP_REGNUM, pc);
+  regcache_cooked_write_unsigned (regcache, M88K_SNIP_REGNUM, pc | 2);
+  regcache_cooked_write_unsigned (regcache, M88K_SFIP_REGNUM, (pc + 4) | 2);
+}
+\f
+
+/* The functions on this page are intended to be used to classify
+   function arguments.  */
 
-  if (this_file)
+/* Check whether TYPE is "Integral or Pointer".  */
+
+static int
+m88k_integral_or_pointer_p (const struct type *type)
+{
+  switch (TYPE_CODE (type))
     {
-    coffsem_frame_position = this_file->coffsem & 3;
-    if (coffsem_frame_position == 1) 
-      return (CORE_ADDR) dc_general_register (current_context, FP_REGNUM);
-    else
-      /* default is CFA, as well as if coffsem==2 */
-      return (CORE_ADDR) dc_frame_address  (current_context);
+    case TYPE_CODE_INT:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_RANGE:
+      {
+       /* We have byte, half-word, word and extended-word/doubleword
+           integral types.  */
+       int len = TYPE_LENGTH (type);
+       return (len == 1 || len == 2 || len == 4 || len == 8);
+      }
+      return 1;
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_REF:
+      {
+       /* Allow only 32-bit pointers.  */
+       return (TYPE_LENGTH (type) == 4);
+      }
+      return 1;
+    default:
+      break;
     }
 
-  return (CORE_ADDR) dc_frame_address (current_context);
+  return 0;
 }
 
-#if TARGET_BYTE_ORDER != HOST_BYTE_ORDER
-you lose
-#else /* Host and target byte order the same.  */
-#define SINGLE_EXP_BITS  8
-#define DOUBLE_EXP_BITS 11
-int
-IEEE_isNAN(fp, len)
-     int *fp, len;
-     /* fp points to a single precision OR double precision
-      * floating point value; len is the number of bytes, either 4 or 8.
-      * Returns 1 iff fp points to a valid IEEE floating point number.
-      * Returns 0 if fp points to a denormalized number or a NaN
-      */
-{
-  int exponent;
-  if (len == 4)
-    {
-      exponent = *fp;
-      exponent = exponent << 1 >> (32 - SINGLE_EXP_BITS - 1);
-      return ((exponent == -1) || (! exponent && *fp));
-    }
-  else if (len == 8)
+/* Check whether TYPE is "Floating".  */
+
+static int
+m88k_floating_p (const struct type *type)
+{
+  switch (TYPE_CODE (type))
     {
-      exponent = *(fp+1);
-      exponent = exponent << 1 >> (32 - DOUBLE_EXP_BITS - 1);
-      return ((exponent == -1) || (! exponent && *fp * *(fp+1)));
+    case TYPE_CODE_FLT:
+      {
+       int len = TYPE_LENGTH (type);
+       return (len == 4 || len == 8);
+      }
+    default:
+      break;
     }
-  else return 1;
+
+  return 0;
 }
-#endif /* Host and target byte order the same.  */
 
-#define FIRST_PRESERVED_REGNUM 14
-#define LAST_PRESERVED_REGNUM  25
-#define FIRST_PARM_REGNUM      2
-#define LAST_PARM_REGNUM       9
+/* Check whether TYPE is "Structure or Union".  */
 
-#define MAX_REG_PARMS  (LAST_PARM_REGNUM - FIRST_PARM_REGNUM + 1)
+static int
+m88k_structure_or_union_p (const struct type *type)
+{
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      return 1;
+    default:
+      break;
+    }
 
-void
-frame_find_saved_regs (fi, fsr)
-      struct frame_info *fi;
-      struct frame_saved_regs *fsr;
-{
-   register int regnum;
-   error ("Feature not implemented for the 88k yet.");
-   return;
-#if 0
-   for (regnum = FIRST_PARM_REGNUM; regnum <= LAST_PARM_REGNUM; regnum++)
-     fsr->regs[regnum]
-        = (unsigned) fi->frame - ((regnum - FIRST_PARM_REGNUM) * 4);
-   fsr->regs[SP_REGNUM] = 0;           /* SP not saved in frames */
-   fsr->regs[FP_REGNUM] = fi->frame;
-   fsr->regs[PC_REGNUM] = fi->frame + 4;
-#endif
+  return 0;
 }
 
+/* Check whether TYPE has 8-byte alignment.  */
+
 static int
-pushed_size (prev_words, v)
-     int prev_words;
-     struct value *v;
+m88k_8_byte_align_p (struct type *type)
 {
-  switch (TYPE_CODE (VALUE_TYPE (v)))
+  if (m88k_structure_or_union_p (type))
     {
-      case TYPE_CODE_VOID:             /* Void type (values zero length) */
-
-       return 0;       /* That was easy! */
+      int i;
 
-      case TYPE_CODE_PTR:              /* Pointer type */
-      case TYPE_CODE_ENUM:             /* Enumeration type */
-      case TYPE_CODE_INT:              /* Integer type */
-      case TYPE_CODE_REF:              /* C++ Reference types */
-      case TYPE_CODE_ARRAY:            /* Array type, lower bound zero */
+      for (i = 0; i < TYPE_NFIELDS (type); i++)
+       {
+         struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
 
-       return 1;
+         if (m88k_8_byte_align_p (subtype))
+           return 1;
+       }
+    }
 
-      case TYPE_CODE_FLT:              /* Floating type */
+  if (m88k_integral_or_pointer_p (type) || m88k_floating_p (type))
+    return (TYPE_LENGTH (type) == 8);
 
-       if (TYPE_LENGTH (VALUE_TYPE (v)) == 4)
-         return 1;
-       else
-         /* Assume that it must be a double.  */
-         if (prev_words & 1)           /* at an odd-word boundary */
-           return 3;                   /* round to 8-byte boundary */
-         else
-           return 2;
+  return 0;
+}
 
-      case TYPE_CODE_STRUCT:           /* C struct or Pascal record */
-      case TYPE_CODE_UNION:            /* C union or Pascal variant part */
+/* Check whether TYPE can be passed in a register.  */
 
-       return (((TYPE_LENGTH (VALUE_TYPE (v)) + 3) / 4) * 4);
+static int
+m88k_in_register_p (struct type *type)
+{
+  if (m88k_integral_or_pointer_p (type) || m88k_floating_p (type))
+    return 1;
 
-      case TYPE_CODE_FUNC:             /* Function type */
-      case TYPE_CODE_SET:              /* Pascal sets */
-      case TYPE_CODE_RANGE:            /* Range (integers within bounds) */
-      case TYPE_CODE_PASCAL_ARRAY:     /* Array with explicit type of index */
-      case TYPE_CODE_MEMBER:           /* Member type */
-      case TYPE_CODE_METHOD:           /* Method type */
-       /* Don't know how to pass these yet.  */
+  if (m88k_structure_or_union_p (type) && TYPE_LENGTH (type) == 4)
+    return 1;
 
-      case TYPE_CODE_UNDEF:            /* Not used; catches errors */
-      default:
-       abort ();
-    }
+  return 0;
 }
 
-static void
-store_parm_word (address, val)
-     CORE_ADDR address;
-     int val;
+static CORE_ADDR
+m88k_store_arguments (struct regcache *regcache, int nargs,
+                     struct value **args, CORE_ADDR sp)
 {
-  write_memory (address, &val, 4);
-}
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  int num_register_words = 0;
+  int num_stack_words = 0;
+  int i;
 
-static int
-store_parm (prev_words, left_parm_addr, v)
-     unsigned int prev_words;
-     CORE_ADDR left_parm_addr;
-     struct value *v;
-{
-  CORE_ADDR start = left_parm_addr + (prev_words * 4);
-  int *val_addr = (int *)VALUE_CONTENTS(v);
-
-  switch (TYPE_CODE (VALUE_TYPE (v)))
+  for (i = 0; i < nargs; i++)
     {
-      case TYPE_CODE_VOID:             /* Void type (values zero length) */
+      struct type *type = value_type (args[i]);
+      int len = TYPE_LENGTH (type);
 
-       return 0;
+      if (m88k_integral_or_pointer_p (type) && len < 4)
+       {
+         args[i] = value_cast (builtin_type (gdbarch)->builtin_int32,
+                               args[i]);
+         type = value_type (args[i]);
+         len = TYPE_LENGTH (type);
+       }
 
-      case TYPE_CODE_PTR:              /* Pointer type */
-      case TYPE_CODE_ENUM:             /* Enumeration type */
-      case TYPE_CODE_INT:              /* Integer type */
-      case TYPE_CODE_ARRAY:            /* Array type, lower bound zero */
-      case TYPE_CODE_REF:              /* C++ Reference types */
+      if (m88k_in_register_p (type))
+       {
+         int num_words = 0;
 
-       store_parm_word (start, *val_addr);
-       return 1;
+         if (num_register_words % 2 == 1 && m88k_8_byte_align_p (type))
+           num_words++;
 
-      case TYPE_CODE_FLT:              /* Floating type */
+         num_words += ((len + 3) / 4);
+         if (num_register_words + num_words <= 8)
+           {
+             num_register_words += num_words;
+             continue;
+           }
 
-       if (TYPE_LENGTH (VALUE_TYPE (v)) == 4)
-         {
-           store_parm_word (start, *val_addr);
-           return 1;
-         }
-       else
-         {
-           store_parm_word (start + ((prev_words & 1) * 4), val_addr[0]);
-           store_parm_word (start + ((prev_words & 1) * 4) + 4, val_addr[1]);
-           return 2 + (prev_words & 1);
-         }
+         /* We've run out of available registers.  Pass the argument
+             on the stack.  */
+       }
+
+      if (num_stack_words % 2 == 1 && m88k_8_byte_align_p (type))
+       num_stack_words++;
+
+      num_stack_words += ((len + 3) / 4);
+    }
+
+  /* Allocate stack space.  */
+  sp = align_down (sp - 32 - num_stack_words * 4, 16);
+  num_stack_words = num_register_words = 0;
 
-      case TYPE_CODE_STRUCT:           /* C struct or Pascal record */
-      case TYPE_CODE_UNION:            /* C union or Pascal variant part */
+  for (i = 0; i < nargs; i++)
+    {
+      const bfd_byte *valbuf = value_contents (args[i]);
+      struct type *type = value_type (args[i]);
+      int len = TYPE_LENGTH (type);
+      int stack_word = num_stack_words;
 
+      if (m88k_in_register_p (type))
        {
-         unsigned int words = (((TYPE_LENGTH (VALUE_TYPE (v)) + 3) / 4) * 4);
-         unsigned int word;
+         int register_word = num_register_words;
+
+         if (register_word % 2 == 1 && m88k_8_byte_align_p (type))
+           register_word++;
+
+         gdb_assert (len == 4 || len == 8);
+
+         if (register_word + len / 8 < 8)
+           {
+             int regnum = M88K_R2_REGNUM + register_word;
+
+             regcache_raw_write (regcache, regnum, valbuf);
+             if (len > 4)
+               regcache_raw_write (regcache, regnum + 1, valbuf + 4);
 
-         for (word = 0; word < words; word++)
-           store_parm_word (start + (word * 4), val_addr[word]);
-         return words;
+             num_register_words = (register_word + len / 4);
+             continue;
+           }
        }
 
-      default:
-       abort ();
+      if (stack_word % 2 == -1 && m88k_8_byte_align_p (type))
+       stack_word++;
+
+      write_memory (sp + stack_word * 4, valbuf, len);
+      num_stack_words = (stack_word + (len + 3) / 4);
     }
+
+  return sp;
 }
 
- /* This routine sets up all of the parameter values needed to make a pseudo
-    call.  The name "push_parameters" is a misnomer on some archs,
-    because (on the m88k) most parameters generally end up being passed in
-    registers rather than on the stack.  In this routine however, we do
-    end up storing *all* parameter values onto the stack (even if we will
-    realize later that some of these stores were unnecessary).  */
+static CORE_ADDR
+m88k_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                     struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
+                     struct value **args, CORE_ADDR sp, int struct_return,
+                     CORE_ADDR struct_addr)
+{
+  /* Set up the function arguments.  */
+  sp = m88k_store_arguments (regcache, nargs, args, sp);
+  gdb_assert (sp % 16 == 0);
 
-void
-push_parameters (return_type, struct_conv, nargs, args)
-      struct type *return_type; 
-      int struct_conv;
-      int nargs;
-      value *args;
- {
-   int parm_num;
-   unsigned int p_words = 0;
-   CORE_ADDR left_parm_addr;
-   /* Start out by creating a space for the return value (if need be).  We
-      only need to do this if the return value is a struct or union.  If we
-      do make a space for a struct or union return value, then we must also
-      arrange for the base address of that space to go into r12, which is the
-      standard place to pass the address of the return value area to the
-      callee.  Note that only structs and unions are returned in this fashion.
-      Ints, enums, pointers, and floats are returned into r2.  Doubles are
-      returned into the register pair {r2,r3}.  Note also that the space
-      reserved for a struct or union return value only has to be word aligned
-      (not double-word) but it is double-word aligned here anyway (just in
-      case that becomes important someday).  */
-   switch (TYPE_CODE (return_type))
-     {
-       case TYPE_CODE_STRUCT:
-       case TYPE_CODE_UNION:
-         {
-           int return_bytes = ((TYPE_LENGTH (return_type) + 7) / 8) * 8;
-           CORE_ADDR rv_addr;
-           rv_addr = read_register (SP_REGNUM) - return_bytes;
-           write_register (SP_REGNUM, rv_addr); /* push space onto the stack */
-           write_register (SRA_REGNUM, rv_addr);/* set return value register */
-         }
-     }
-   /* Here we make a pre-pass on the whole parameter list to figure out exactly
-      how many words worth of stuff we are going to pass.  */
-   for (p_words = 0, parm_num = 0; parm_num < nargs; parm_num++)
-     p_words += pushed_size (p_words, value_arg_coerce (args[parm_num]));
-   /* Now, check to see if we have to round up the number of parameter words
-      to get up to the next 8-bytes boundary.  This may be necessary because
-      of the software convention to always keep the stack aligned on an 8-byte
-      boundary.  */
-   if (p_words & 1)
-     p_words++;                /* round to 8-byte boundary */
-   /* Now figure out the absolute address of the leftmost parameter, and update
-      the stack pointer to point at that address.  */
-   left_parm_addr = read_register (SP_REGNUM) - (p_words * 4);
-   write_register (SP_REGNUM, left_parm_addr);
-   /* Now we can go through all of the parameters (in left-to-right order)
-      and write them to their parameter stack slots.  Note that we are not
-      really "pushing" the parameter values.  The stack space for these values
-      was already allocated above.  Now we are just filling it up.  */
-   for (p_words = 0, parm_num = 0; parm_num < nargs; parm_num++)
-     p_words +=
-       store_parm (p_words, left_parm_addr, value_arg_coerce (args[parm_num]));
-   /* Now that we are all done storing the parameter values into the stack, we
-      must go back and load up the parameter registers with the values from the
-      corresponding stack slots.  Note that in the two cases of (a) gaps in the
-      parameter word sequence causes by (otherwise) misaligned doubles, and (b)
-      slots correcponding to structs or unions, the work we do here in loading
-      some parameter registers may be unnecessary, but who cares?  */
-   for (p_words = 0; p_words < 8; p_words++)
-     {
-       write_register (FIRST_PARM_REGNUM + p_words,
-         read_memory_integer (left_parm_addr + (p_words * 4), 4));
-     }
+  /* Store return value address.  */
+  if (struct_return)
+    regcache_raw_write_unsigned (regcache, M88K_R12_REGNUM, struct_addr);
+
+  /* Store the stack pointer and return address in the appropriate
+     registers.  */
+  regcache_raw_write_unsigned (regcache, M88K_R31_REGNUM, sp);
+  regcache_raw_write_unsigned (regcache, M88K_R1_REGNUM, bp_addr);
+
+  /* Return the stack pointer.  */
+  return sp;
 }
 
-void
-pop_frame ()
+static struct frame_id
+m88k_dummy_id (struct gdbarch *arch, struct frame_info *this_frame)
 {
-  error ("Feature not implemented for the m88k yet.");
-  return;
+  CORE_ADDR sp;
+
+  sp = get_frame_register_unsigned (this_frame, M88K_R31_REGNUM);
+  return frame_id_build (sp, get_frame_pc (this_frame));
 }
+\f
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+   should be returned.  If it is supposed to be returned in registers,
+   and READBUF is non-zero, read the appropriate value from REGCACHE,
+   and copy it into READBUF.  If WRITEBUF is non-zero, write the value
+   from WRITEBUF into REGCACHE.  */
+
+static enum return_value_convention
+m88k_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                  struct type *type, struct regcache *regcache,
+                  gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  int len = TYPE_LENGTH (type);
+  gdb_byte buf[8];
 
- void
- collect_returned_value (rval, value_type, struct_return, nargs, args)
-      value *rval;
-      struct type *value_type;
-      int struct_return;
-      int nargs;
-      value *args;
- {
-   char retbuf[REGISTER_BYTES];
-   bcopy (registers, retbuf, REGISTER_BYTES);
-   *rval = value_being_returned (value_type, retbuf, struct_return);
-   return;
- }
-
-#if 0
-/* Now handled in a machine independent way with CALL_DUMMY_LOCATION.  */
- /* Stuff a breakpoint instruction onto the stack (or elsewhere if the stack
-    is not a good place for it).  Return the address at which the instruction
-    got stuffed, or zero if we were unable to stuff it anywhere.  */
-  
- CORE_ADDR
- push_breakpoint ()
-  {
-   static char breakpoint_insn[] = BREAKPOINT;
-   extern CORE_ADDR text_end;  /* of inferior */
-   static char readback_buffer[] = BREAKPOINT;
-   int i;
-  
-   /* With a little bit of luck, we can just stash the breakpoint instruction
-      in the word just beyond the end of normal text space.  For systems on
-      which the hardware will not allow us to execute out of the stack segment,
-      we have to hope that we *are* at least allowed to effectively extend the
-      text segment by one word.  If the actual end of user's the text segment
-      happens to fall right at a page boundary this trick may fail.  Note that
-      we check for this by reading after writing, and comparing in order to
-      be sure that the write worked.  */
-   write_memory (text_end, &breakpoint_insn, 4);
-   /* Fill the readback buffer with some garbage which is certain to be
-      unequal to the breakpoint insn.  That way we can tell if the
-      following read doesn't actually succeed.  */
-   for (i = 0; i < sizeof (readback_buffer); i++)
-     readback_buffer[i] = ~ readback_buffer[i];        /* Invert the bits */
-   /* Now check that the breakpoint insn was successfully installed.  */
-   read_memory (text_end, readback_buffer, sizeof (readback_buffer));
-   for (i = 0; i < sizeof (readback_buffer); i++)
-     if (readback_buffer[i] != breakpoint_insn[i])
-       return 0;               /* Failed to install! */
-   return text_end;
- }
-#endif
-
-/* Like dc_psr_register but takes an extra int arg.  */
-static dc_word_t
-psr_register (context, dummy)
-     dc_dcontext_t context;
-     int dummy;
-{
-  return dc_psr_register (context);
+  if (!m88k_integral_or_pointer_p (type) && !m88k_floating_p (type))
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
+  if (readbuf)
+    {
+      /* Read the contents of R2 and (if necessary) R3.  */
+      regcache_cooked_read (regcache, M88K_R2_REGNUM, buf);
+      if (len > 4)
+       {
+         regcache_cooked_read (regcache, M88K_R3_REGNUM, buf + 4);
+         gdb_assert (len == 8);
+         memcpy (readbuf, buf, len);
+       }
+      else
+       {
+         /* Just stripping off any unused bytes should preserve the
+             signed-ness just fine.  */
+         memcpy (readbuf, buf + 4 - len, len);
+       }
+    }
+
+  if (writebuf)
+    {
+      /* Read the contents to R2 and (if necessary) R3.  */
+      if (len > 4)
+       {
+         gdb_assert (len == 8);
+         memcpy (buf, writebuf, 8);
+         regcache_cooked_write (regcache, M88K_R3_REGNUM, buf + 4);
+       }
+      else
+       {
+         /* ??? Do we need to do any sign-extension here?  */
+         memcpy (buf + 4 - len, writebuf, len);
+       }
+      regcache_cooked_write (regcache, M88K_R2_REGNUM, buf);
+    }
+
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
+\f
+/* Default frame unwinder.  */
 
-/* Same functionality as get_saved_register in findvar.c, but implemented
-   to use tdesc.  */
-void
-get_saved_register (raw_buffer, optim, addrp, frame, regnum, lvalp)
-     char *raw_buffer;
-     int *optim;
-     CORE_ADDR *addrp;
-     FRAME frame;
-     int regnum;
-     enum lval_type *lvalp;
-{
-  struct frame_info *fi = get_frame_info (frame);
-  
-  /* Functions to say whether a register is optimized out, and
-     if not, to get the value.  Take as args a context and the
-     value of get_reg_arg.  */
-  int (*get_reg_state) ();
-  dc_word_t (*get_reg) ();
-  int get_reg_arg;
-
-  /* Because tdesc doesn't tell us whether it got it from a register
-     or memory, always say we don't have an address for it.  */
-  if (addrp != NULL)
-    *addrp = 0;
-  
-  if (regnum < DC_NUM_REG)
+struct m88k_frame_cache
+{
+  /* Base address.  */
+  CORE_ADDR base;
+  CORE_ADDR pc;
+
+  int sp_offset;
+  int fp_offset;
+
+  /* Table of saved registers.  */
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Prologue analysis.  */
+
+/* Macros for extracting fields from instructions.  */
+
+#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
+#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
+#define        SUBU_OFFSET(x)  ((unsigned)(x & 0xFFFF))
+#define        ST_OFFSET(x)    ((unsigned)((x) & 0xFFFF))
+#define        ST_SRC(x)       EXTRACT_FIELD ((x), 21, 5)
+#define        ADDU_OFFSET(x)  ((unsigned)(x & 0xFFFF))
+
+/* Possible actions to be taken by the prologue analyzer for the
+   instructions it encounters.  */
+
+enum m88k_prologue_insn_action
+{
+  M88K_PIA_SKIP,               /* Ignore.  */
+  M88K_PIA_NOTE_ST,            /* Note register store.  */
+  M88K_PIA_NOTE_STD,           /* Note register pair store.  */
+  M88K_PIA_NOTE_SP_ADJUSTMENT, /* Note stack pointer adjustment.  */
+  M88K_PIA_NOTE_FP_ASSIGNMENT, /* Note frame pointer assignment.  */
+  M88K_PIA_NOTE_BRANCH,                /* Note branch.  */
+  M88K_PIA_NOTE_PROLOGUE_END   /* Note end of prologue.  */
+};
+
+/* Table of instructions that may comprise a function prologue.  */
+
+struct m88k_prologue_insn
+{
+  unsigned long insn;
+  unsigned long mask;
+  enum m88k_prologue_insn_action action;
+};
+
+struct m88k_prologue_insn m88k_prologue_insn_table[] =
+{
+  /* Various register move instructions.  */
+  { 0x58000000, 0xf800ffff, M88K_PIA_SKIP },     /* or/or.u with immed of 0 */
+  { 0xf4005800, 0xfc1fffe0, M88K_PIA_SKIP },     /* or rd,r0,rs */
+  { 0xf4005800, 0xfc00ffff, M88K_PIA_SKIP },     /* or rd,rs,r0 */
+
+  /* Various other instructions.  */
+  { 0x58000000, 0xf8000000, M88K_PIA_SKIP },     /* or/or.u */
+
+  /* Stack pointer setup: "subu sp,sp,n" where n is a multiple of 8.  */
+  { 0x67ff0000, 0xffff0007, M88K_PIA_NOTE_SP_ADJUSTMENT },
+
+  /* Frame pointer assignment: "addu r30,r31,n".  */
+  { 0x63df0000, 0xffff0000, M88K_PIA_NOTE_FP_ASSIGNMENT },
+
+  /* Store to stack instructions; either "st rx,sp,n" or "st.d rx,sp,n".  */
+  { 0x241f0000, 0xfc1f0000, M88K_PIA_NOTE_ST },  /* st rx,sp,n */
+  { 0x201f0000, 0xfc1f0000, M88K_PIA_NOTE_STD }, /* st.d rs,sp,n */
+
+  /* Instructions needed for setting up r25 for pic code.  */
+  { 0x5f200000, 0xffff0000, M88K_PIA_SKIP },     /* or.u r25,r0,offset_high */
+  { 0xcc000002, 0xffffffff, M88K_PIA_SKIP },     /* bsr.n Lab */
+  { 0x5b390000, 0xffff0000, M88K_PIA_SKIP },     /* or r25,r25,offset_low */
+  { 0xf7396001, 0xffffffff, M88K_PIA_SKIP },     /* Lab: addu r25,r25,r1 */
+
+  /* Various branch or jump instructions which have a delay slot --
+     these do not form part of the prologue, but the instruction in
+     the delay slot might be a store instruction which should be
+     noted.  */
+  { 0xc4000000, 0xe4000000, M88K_PIA_NOTE_BRANCH },
+                                      /* br.n, bsr.n, bb0.n, or bb1.n */
+  { 0xec000000, 0xfc000000, M88K_PIA_NOTE_BRANCH }, /* bcnd.n */
+  { 0xf400c400, 0xfffff7e0, M88K_PIA_NOTE_BRANCH }, /* jmp.n or jsr.n */
+
+  /* Catch all.  Ends prologue analysis.  */
+  { 0x00000000, 0x00000000, M88K_PIA_NOTE_PROLOGUE_END }
+};
+
+/* Do a full analysis of the function prologue at PC and update CACHE
+   accordingly.  Bail out early if LIMIT is reached.  Return the
+   address where the analysis stopped.  If LIMIT points beyond the
+   function prologue, the return address should be the end of the
+   prologue.  */
+
+static CORE_ADDR
+m88k_analyze_prologue (struct gdbarch *gdbarch,
+                      CORE_ADDR pc, CORE_ADDR limit,
+                      struct m88k_frame_cache *cache)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  CORE_ADDR end = limit;
+
+  /* Provide a dummy cache if necessary.  */
+  if (cache == NULL)
     {
-      get_reg_state = dc_general_register_state;
-      get_reg = dc_general_register;
-      get_reg_arg = regnum;
+      size_t sizeof_saved_regs =
+       (M88K_R31_REGNUM + 1) * sizeof (struct trad_frame_saved_reg);
+
+      cache = alloca (sizeof (struct m88k_frame_cache));
+      cache->saved_regs = alloca (sizeof_saved_regs);
+
+      /* We only initialize the members we care about.  */
+      cache->saved_regs[M88K_R1_REGNUM].addr = -1;
+      cache->fp_offset = -1;
     }
-  else
+
+  while (pc < limit)
     {
-      get_reg_state = dc_auxiliary_register_state;
-      get_reg = dc_auxiliary_register;
-      switch (regnum)
+      struct m88k_prologue_insn *pi = m88k_prologue_insn_table;
+      unsigned long insn = m88k_fetch_instruction (pc, byte_order);
+
+      while ((insn & pi->mask) != pi->insn)
+       pi++;
+
+      switch (pi->action)
        {
-       case SXIP_REGNUM:
-         get_reg_arg = DC_AUX_SXIP;
+       case M88K_PIA_SKIP:
+         /* If we have a frame pointer, and R1 has been saved,
+             consider this instruction as not being part of the
+             prologue.  */
+         if (cache->fp_offset != -1
+             && cache->saved_regs[M88K_R1_REGNUM].addr != -1)
+           return min (pc, end);
          break;
-       case SNIP_REGNUM:
-         get_reg_arg = DC_AUX_SNIP;
+
+       case M88K_PIA_NOTE_ST:
+       case M88K_PIA_NOTE_STD:
+         /* If no frame has been allocated, the stores aren't part of
+             the prologue.  */
+         if (cache->sp_offset == 0)
+           return min (pc, end);
+
+         /* Record location of saved registers.  */
+         {
+           int regnum = ST_SRC (insn) + M88K_R0_REGNUM;
+           ULONGEST offset = ST_OFFSET (insn);
+
+           cache->saved_regs[regnum].addr = offset;
+           if (pi->action == M88K_PIA_NOTE_STD && regnum < M88K_R31_REGNUM)
+             cache->saved_regs[regnum + 1].addr = offset + 4;
+         }
          break;
-       case FPSR_REGNUM:
-         get_reg_arg = DC_AUX_FPSR;
+
+       case M88K_PIA_NOTE_SP_ADJUSTMENT:
+         /* A second stack pointer adjustment isn't part of the
+             prologue.  */
+         if (cache->sp_offset != 0)
+           return min (pc, end);
+
+         /* Store stack pointer adjustment.  */
+         cache->sp_offset = -SUBU_OFFSET (insn);
          break;
-       case FPCR_REGNUM:
-         get_reg_arg = DC_AUX_FPCR;
+
+       case M88K_PIA_NOTE_FP_ASSIGNMENT:
+         /* A second frame pointer assignment isn't part of the
+             prologue.  */
+         if (cache->fp_offset != -1)
+           return min (pc, end);
+
+         /* Record frame pointer assignment.  */
+         cache->fp_offset = ADDU_OFFSET (insn);
          break;
-       case PSR_REGNUM:
-         get_reg_state = dc_psr_register_bit_state;
-         get_reg = psr_register;
-         get_reg_arg = 0;
+
+       case M88K_PIA_NOTE_BRANCH:
+         /* The branch instruction isn't part of the prologue, but
+             the instruction in the delay slot might be.  Limit the
+             prologue analysis to the delay slot and record the branch
+             instruction as the end of the prologue.  */
+         limit = min (limit, pc + 2 * M88K_INSN_SIZE);
+         end = pc;
          break;
-       default:
-         if (optim != NULL)
-           *optim = 1;
-         return;
+
+       case M88K_PIA_NOTE_PROLOGUE_END:
+         return min (pc, end);
        }
+
+      pc += M88K_INSN_SIZE;
+    }
+
+  return end;
+}
+
+/* An upper limit to the size of the prologue.  */
+const int m88k_max_prologue_size = 128 * M88K_INSN_SIZE;
+
+/* Return the address of first real instruction of the function
+   starting at PC.  */
+
+static CORE_ADDR
+m88k_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  struct symtab_and_line sal;
+  CORE_ADDR func_start, func_end;
+
+  /* This is the preferred method, find the end of the prologue by
+     using the debugging information.  */
+  if (find_pc_partial_function (pc, NULL, &func_start, &func_end))
+    {
+      sal = find_pc_line (func_start, 0);
+
+      if (sal.end < func_end && pc <= sal.end)
+       return sal.end;
     }
 
-  if ((*get_reg_state) (fi->frame_context, get_reg_arg))
+  return m88k_analyze_prologue (gdbarch, pc, pc + m88k_max_prologue_size,
+                               NULL);
+}
+
+static struct m88k_frame_cache *
+m88k_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct m88k_frame_cache *cache;
+  CORE_ADDR frame_sp;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = FRAME_OBSTACK_ZALLOC (struct m88k_frame_cache);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+  cache->fp_offset = -1;
+
+  cache->pc = get_frame_func (this_frame);
+  if (cache->pc != 0)
+    m88k_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame),
+                          cache);
+
+  /* Calculate the stack pointer used in the prologue.  */
+  if (cache->fp_offset != -1)
     {
-      if (raw_buffer != NULL)
-       *(int *)raw_buffer = (*get_reg) (fi->frame_context, get_reg_arg);
-      if (optim != NULL)
-       *optim = 0;
-      return;
+      CORE_ADDR fp;
+
+      fp = get_frame_register_unsigned (this_frame, M88K_R30_REGNUM);
+      frame_sp = fp - cache->fp_offset;
     }
   else
     {
-      if (optim != NULL)
-       *optim = 1;
-      return;
+      /* If we know where the return address is saved, we can take a
+         solid guess at what the frame pointer should be.  */
+      if (cache->saved_regs[M88K_R1_REGNUM].addr != -1)
+       cache->fp_offset = cache->saved_regs[M88K_R1_REGNUM].addr - 4;
+      frame_sp = get_frame_register_unsigned (this_frame, M88K_R31_REGNUM);
     }
 
-  /* Well, the caller can't treat it as a register or memory...  */
-  if (lvalp != NULL)
-    *lvalp = not_lval;
+  /* Now that we know the stack pointer, adjust the location of the
+     saved registers.  */
+  {
+    int regnum;
+
+    for (regnum = M88K_R0_REGNUM; regnum < M88K_R31_REGNUM; regnum ++)
+      if (cache->saved_regs[regnum].addr != -1)
+       cache->saved_regs[regnum].addr += frame_sp;
+  }
+
+  /* Calculate the frame's base.  */
+  cache->base = frame_sp - cache->sp_offset;
+  trad_frame_set_value (cache->saved_regs, M88K_R31_REGNUM, cache->base);
+
+  /* Identify SXIP with the return address in R1.  */
+  cache->saved_regs[M88K_SXIP_REGNUM] = cache->saved_regs[M88K_R1_REGNUM];
+
+  *this_cache = cache;
+  return cache;
+}
+
+static void
+m88k_frame_this_id (struct frame_info *this_frame, void **this_cache,
+                   struct frame_id *this_id)
+{
+  struct m88k_frame_cache *cache = m88k_frame_cache (this_frame, this_cache);
+
+  /* This marks the outermost frame.  */
+  if (cache->base == 0)
+    return;
+
+  (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static struct value *
+m88k_frame_prev_register (struct frame_info *this_frame,
+                         void **this_cache, int regnum)
+{
+  struct m88k_frame_cache *cache = m88k_frame_cache (this_frame, this_cache);
+
+  if (regnum == M88K_SNIP_REGNUM || regnum == M88K_SFIP_REGNUM)
+    {
+      struct value *value;
+      CORE_ADDR pc;
+
+      value = trad_frame_get_prev_register (this_frame, cache->saved_regs,
+                                           M88K_SXIP_REGNUM);
+      pc = value_as_long (value);
+      release_value (value);
+      value_free (value);
+
+      if (regnum == M88K_SFIP_REGNUM)
+       pc += 4;
+
+      return frame_unwind_got_constant (this_frame, regnum, pc + 4);
+    }
+
+  return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
+}
+
+static const struct frame_unwind m88k_frame_unwind =
+{
+  NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
+  m88k_frame_this_id,
+  m88k_frame_prev_register,
+  NULL,
+  default_frame_sniffer
+};
+\f
+
+static CORE_ADDR
+m88k_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+  struct m88k_frame_cache *cache = m88k_frame_cache (this_frame, this_cache);
+
+  if (cache->fp_offset != -1)
+    return cache->base + cache->sp_offset + cache->fp_offset;
+
+  return 0;
+}
+
+static const struct frame_base m88k_frame_base =
+{
+  &m88k_frame_unwind,
+  m88k_frame_base_address,
+  m88k_frame_base_address,
+  m88k_frame_base_address
+};
+\f
+
+/* Core file support.  */
+
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
+   in the general-purpose register set REGSET to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+static void
+m88k_supply_gregset (const struct regset *regset,
+                    struct regcache *regcache,
+                    int regnum, const void *gregs, size_t len)
+{
+  const gdb_byte *regs = gregs;
+  int i;
+
+  for (i = 0; i < M88K_NUM_REGS; i++)
+    {
+      if (regnum == i || regnum == -1)
+       regcache_raw_supply (regcache, i, regs + i * 4);
+    }
+}
+
+/* Motorola 88000 register set.  */
+
+static struct regset m88k_gregset =
+{
+  NULL,
+  m88k_supply_gregset
+};
+
+/* Return the appropriate register set for the core section identified
+   by SECT_NAME and SECT_SIZE.  */
+
+static const struct regset *
+m88k_regset_from_core_section (struct gdbarch *gdbarch,
+                              const char *sect_name, size_t sect_size)
+{
+  if (strcmp (sect_name, ".reg") == 0 && sect_size >= M88K_NUM_REGS * 4)
+    return &m88k_gregset;
+
+  return NULL;
+}
+\f
+
+static struct gdbarch *
+m88k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  struct gdbarch *gdbarch;
+
+  /* If there is already a candidate, use it.  */
+  arches = gdbarch_list_lookup_by_info (arches, &info);
+  if (arches != NULL)
+    return arches->gdbarch;
+
+  /* Allocate space for the new architecture.  */
+  gdbarch = gdbarch_alloc (&info, NULL);
+
+  /* There is no real `long double'.  */
+  set_gdbarch_long_double_bit (gdbarch, 64);
+  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
+
+  set_gdbarch_num_regs (gdbarch, M88K_NUM_REGS);
+  set_gdbarch_register_name (gdbarch, m88k_register_name);
+  set_gdbarch_register_type (gdbarch, m88k_register_type);
+
+  /* Register numbers of various important registers.  */
+  set_gdbarch_sp_regnum (gdbarch, M88K_R31_REGNUM);
+  set_gdbarch_pc_regnum (gdbarch, M88K_SXIP_REGNUM);
+
+  /* Core file support.  */
+  set_gdbarch_regset_from_core_section
+    (gdbarch, m88k_regset_from_core_section);
+
+  set_gdbarch_print_insn (gdbarch, print_insn_m88k);
+
+  set_gdbarch_skip_prologue (gdbarch, m88k_skip_prologue);
+
+  /* Stack grows downward.  */
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+
+  /* Call dummy code.  */
+  set_gdbarch_push_dummy_call (gdbarch, m88k_push_dummy_call);
+  set_gdbarch_dummy_id (gdbarch, m88k_dummy_id);
+
+  /* Return value info.  */
+  set_gdbarch_return_value (gdbarch, m88k_return_value);
+
+  set_gdbarch_addr_bits_remove (gdbarch, m88k_addr_bits_remove);
+  set_gdbarch_breakpoint_from_pc (gdbarch, m88k_breakpoint_from_pc);
+  set_gdbarch_unwind_pc (gdbarch, m88k_unwind_pc);
+  set_gdbarch_write_pc (gdbarch, m88k_write_pc);
+
+  frame_base_set_default (gdbarch, &m88k_frame_base);
+  frame_unwind_append_unwinder (gdbarch, &m88k_frame_unwind);
+
+  return gdbarch;
+}
+\f
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_m88k_tdep (void);
+
+void
+_initialize_m88k_tdep (void)
+{
+  gdbarch_register (bfd_arch_m88k, m88k_gdbarch_init, NULL);
 }
This page took 0.037471 seconds and 4 git commands to generate.