2002-11-18 Andrew Cagney <ac131313@redhat.com>
[deliverable/binutils-gdb.git] / gdb / m68k-tdep.c
index a6cecfe4c2dd821b52aea12cda4872e1247d2c20..250f68115522da0251b429d29ee70f02b1114643 100644 (file)
@@ -1,5 +1,6 @@
 /* Target dependent code for the Motorola 68000 series.
-   Copyright (C) 1990, 1992 Free Software Foundation, Inc.
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -25,6 +26,8 @@
 #include "value.h"
 #include "gdb_string.h"
 #include "inferior.h"
+#include "regcache.h"
+#include "arch-utils.h"
 \f
 
 #define P_LINKL_FP     0x480e
 #define P_FMOVM                0xf237
 #define P_TRAP         0x4e40
 
-/* The only reason this is here is the tm-altos.h reference below.  It
-   was moved back here from tm-m68k.h.  FIXME? */
 
-extern CORE_ADDR
-altos_skip_prologue (pc)
-     CORE_ADDR pc;
+/* Register numbers of various important registers.
+   Note that some of these values are "real" register numbers,
+   and correspond to the general registers of the machine,
+   and some are "phony" register numbers which are too large
+   to be actual register numbers as far as the user is concerned
+   but do serve to get the desired values when passed to read_register.  */
+
+/* Note: Since they are used in files other than this (monitor files), 
+   D0_REGNUM and A0_REGNUM are currently defined in tm-m68k.h.  */
+
+enum
 {
-  register int op = read_memory_integer (pc, 2);
-  if (op == P_LINKW_FP)
-    pc += 4;                   /* Skip link #word */
-  else if (op == P_LINKL_FP)
-    pc += 6;                   /* Skip link #long */
-  /* Not sure why branches are here.  */
-  /* From tm-isi.h, tm-altos.h */
-  else if (op == 0060000)
-    pc += 4;                   /* Skip bra #word */
-  else if (op == 00600377)
-    pc += 6;                   /* skip bra #long */
-  else if ((op & 0177400) == 0060000)
-    pc += 2;                   /* skip bra #char */
-  return pc;
+  E_A1_REGNUM = 9,
+  E_FP_REGNUM = 14,            /* Contains address of executing stack frame */
+  E_SP_REGNUM = 15,            /* Contains address of top of stack */
+  E_PS_REGNUM = 16,            /* Contains processor status */
+  E_PC_REGNUM = 17,            /* Contains program counter */
+  E_FP0_REGNUM = 18,           /* Floating point register 0 */
+  E_FPC_REGNUM = 26,           /* 68881 control register */
+  E_FPS_REGNUM = 27,           /* 68881 status register */
+  E_FPI_REGNUM = 28
+};
+
+#define REGISTER_BYTES_FP (16*4 + 8 + 8*12 + 3*4)
+#define REGISTER_BYTES_NOFP (16*4 + 8)
+
+#define NUM_FREGS (NUM_REGS-24)
+
+/* Offset from SP to first arg on stack at first instruction of a function */
+
+#define SP_ARG0 (1 * 4)
+
+/* This was determined by experimentation on hp300 BSD 4.3.  Perhaps
+   it corresponds to some offset in /usr/include/sys/user.h or
+   something like that.  Using some system include file would
+   have the advantage of probably being more robust in the face
+   of OS upgrades, but the disadvantage of being wrong for
+   cross-debugging.  */
+
+#define SIG_PC_FP_OFFSET 530
+
+#define TARGET_M68K
+
+
+#if !defined (BPT_VECTOR)
+#define BPT_VECTOR 0xf
+#endif
+
+#if !defined (REMOTE_BPT_VECTOR)
+#define REMOTE_BPT_VECTOR 1
+#endif
+
+
+void m68k_frame_init_saved_regs (struct frame_info *frame_info);
+
+
+/* gdbarch_breakpoint_from_pc is set to m68k_local_breakpoint_from_pc
+   so m68k_remote_breakpoint_from_pc is currently not used.  */
+
+const static unsigned char *
+m68k_remote_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+{
+  static unsigned char break_insn[] = {0x4e, (0x40 | REMOTE_BPT_VECTOR)};
+  *lenptr = sizeof (break_insn);
+  return break_insn;
+}
+
+const static unsigned char *
+m68k_local_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+{
+  static unsigned char break_insn[] = {0x4e, (0x40 | BPT_VECTOR)};
+  *lenptr = sizeof (break_insn);
+  return break_insn;
+}
+
+
+static int
+m68k_register_bytes_ok (long numbytes)
+{
+  return ((numbytes == REGISTER_BYTES_FP)
+         || (numbytes == REGISTER_BYTES_NOFP));
+}
+
+/* Number of bytes of storage in the actual machine representation
+   for register regnum.  On the 68000, all regs are 4 bytes
+   except the floating point regs which are 12 bytes.  */
+/* Note that the unsigned cast here forces the result of the
+   subtraction to very high positive values if regnum < FP0_REGNUM */
+
+static int
+m68k_register_raw_size (int regnum)
+{
+  return (((unsigned) (regnum) - FP0_REGNUM) < 8 ? 12 : 4);
+}
+
+/* Number of bytes of storage in the program's representation
+   for register regnum.  On the 68000, all regs are 4 bytes
+   except the floating point regs which are 12-byte long doubles.  */
+
+static int
+m68k_register_virtual_size (int regnum)
+{
+  return (((unsigned) (regnum) - FP0_REGNUM) < 8 ? 12 : 4);
+}
+
+/* Return the GDB type object for the "standard" data type of data 
+   in register N.  This should be int for D0-D7, long double for FP0-FP7,
+   and void pointer for all others (A0-A7, PC, SR, FPCONTROL etc).
+   Note, for registers which contain addresses return pointer to void, 
+   not pointer to char, because we don't want to attempt to print 
+   the string after printing the address.  */
+
+static struct type *
+m68k_register_virtual_type (int regnum)
+{
+  if ((unsigned) regnum >= E_FPC_REGNUM)
+    return lookup_pointer_type (builtin_type_void);
+  else if ((unsigned) regnum >= FP0_REGNUM)
+    return builtin_type_long_double;
+  else if ((unsigned) regnum >= A0_REGNUM)
+    return lookup_pointer_type (builtin_type_void);
+  else
+    return builtin_type_int;
+}
+
+/* Function: m68k_register_name
+   Returns the name of the standard m68k register regnum. */
+
+static const char *
+m68k_register_name (int regnum)
+{
+  static char *register_names[] = {
+    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+    "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp",
+    "ps", "pc",
+    "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
+    "fpcontrol", "fpstatus", "fpiaddr", "fpcode", "fpflags"
+  };
+
+  if (regnum < 0 ||
+      regnum >= sizeof (register_names) / sizeof (register_names[0]))
+    internal_error (__FILE__, __LINE__,
+                   "m68k_register_name: illegal register number %d", regnum);
+  else
+    return register_names[regnum];
 }
 
-/* The only reason this is here is the tm-isi.h reference below.  It
+/* Stack must be kept short aligned when doing function calls.  */
+
+static CORE_ADDR
+m68k_stack_align (CORE_ADDR addr)
+{
+  return ((addr + 1) & ~1);
+}
+
+/* Index within `registers' of the first byte of the space for
+   register regnum.  */
+
+static int
+m68k_register_byte (int regnum)
+{
+  if (regnum >= E_FPC_REGNUM)
+    return (((regnum - E_FPC_REGNUM) * 4) + 168);
+  else if (regnum >= FP0_REGNUM)
+    return (((regnum - FP0_REGNUM) * 12) + 72);
+  else
+    return (regnum * 4);
+}
+
+/* Store the address of the place in which to copy the structure the
+   subroutine will return.  This is called from call_function. */
+
+static void
+m68k_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+  write_register (E_A1_REGNUM, addr);
+}
+
+/* Extract from an array regbuf containing the (raw) register state
+   a function return value of type type, and copy that, in virtual format,
+   into valbuf.  This is assuming that floating point values are returned
+   as doubles in d0/d1.  */
+
+static void
+m68k_deprecated_extract_return_value (struct type *type, char *regbuf,
+                                     char *valbuf)
+{
+  int offset = 0;
+  int typeLength = TYPE_LENGTH (type);
+
+  if (typeLength < 4)
+    offset = 4 - typeLength;
+
+  memcpy (valbuf, regbuf + offset, typeLength);
+}
+
+static CORE_ADDR
+m68k_deprecated_extract_struct_value_address (char *regbuf)
+{
+  return (*(CORE_ADDR *) (regbuf));
+}
+
+/* Write into appropriate registers a function return value
+   of type TYPE, given in virtual format.  Assumes floats are passed
+   in d0/d1.  */
+
+static void
+m68k_store_return_value (struct type *type, char *valbuf)
+{
+  deprecated_write_register_bytes (0, valbuf, TYPE_LENGTH (type));
+}
+
+/* Describe the pointer in each stack frame to the previous stack frame
+   (its caller).  */
+
+/* FRAME_CHAIN takes a frame's nominal address and produces the frame's
+   chain-pointer.
+   In the case of the 68000, the frame's nominal address
+   is the address of a 4-byte word containing the calling frame's address.  */
+
+/* If we are chaining from sigtramp, then manufacture a sigtramp frame
+   (which isn't really on the stack.  I'm not sure this is right for anything
+   but BSD4.3 on an hp300.  */
+
+static CORE_ADDR
+m68k_frame_chain (struct frame_info *thisframe)
+{
+  if ((get_frame_type (thisframe) == SIGTRAMP_FRAME))
+    return thisframe->frame;
+  else if (!inside_entry_file ((thisframe)->pc))
+    return read_memory_integer ((thisframe)->frame, 4);
+  else
+    return 0;
+}
+
+/* A function that tells us whether the function invocation represented
+   by fi does not have a frame on the stack associated with it.  If it
+   does not, FRAMELESS is set to 1, else 0.  */
+
+static int
+m68k_frameless_function_invocation (struct frame_info *fi)
+{
+  if ((get_frame_type (fi) == SIGTRAMP_FRAME))
+    return 0;
+  else
+    return frameless_look_for_prologue (fi);
+}
+
+static CORE_ADDR
+m68k_frame_saved_pc (struct frame_info *frame)
+{
+  if ((get_frame_type (frame) == SIGTRAMP_FRAME))
+    {
+      if (frame->next)
+       return read_memory_integer (frame->next->frame + SIG_PC_FP_OFFSET, 4);
+      else
+       return read_memory_integer (read_register (SP_REGNUM)
+                                   + SIG_PC_FP_OFFSET - 8, 4);
+    }
+  else
+    return read_memory_integer (frame->frame + 4, 4);
+}
+
+
+/* The only reason this is here is the tm-altos.h reference below.  It
    was moved back here from tm-m68k.h.  FIXME? */
 
 extern CORE_ADDR
-isi_skip_prologue (pc)
-     CORE_ADDR pc;
+altos_skip_prologue (CORE_ADDR pc)
 {
   register int op = read_memory_integer (pc, 2);
   if (op == P_LINKW_FP)
@@ -75,7 +319,7 @@ isi_skip_prologue (pc)
   else if (op == P_LINKL_FP)
     pc += 6;                   /* Skip link #long */
   /* Not sure why branches are here.  */
-  /* From tm-isi.h, tm-altos.h */
+  /* From tm-altos.h */
   else if (op == 0060000)
     pc += 4;                   /* Skip bra #word */
   else if (op == 00600377)
@@ -86,36 +330,35 @@ isi_skip_prologue (pc)
 }
 
 int
-delta68_in_sigtramp (pc, name)
-     CORE_ADDR pc;
-     char *name;
+delta68_in_sigtramp (CORE_ADDR pc, char *name)
 {
-  return strcmp (name, "_sigcode") == 0;
+  if (name != NULL)
+    return strcmp (name, "_sigcode") == 0;
+  else
+    return 0;
 }
 
 CORE_ADDR
-delta68_frame_args_address (frame_info)
-     struct frame_info * frame_info;
+delta68_frame_args_address (struct frame_info *frame_info)
 {
   /* we assume here that the only frameless functions are the system calls
      or other functions who do not put anything on the stack. */
-  if (frame_info->signal_handler_caller)
+  if ((get_frame_type (frame_info) == SIGTRAMP_FRAME))
     return frame_info->frame + 12;
   else if (frameless_look_for_prologue (frame_info))
     {
-    /* Check for an interrupted system call */
-    if (frame_info->next && frame_info->next->signal_handler_caller)
-      return frame_info->next->frame + 16;
-    else
-      return frame_info->frame + 4;
+      /* Check for an interrupted system call */
+      if (frame_info->next && (get_frame_type (frame_info->next) == SIGTRAMP_FRAME))
+       return frame_info->next->frame + 16;
+      else
+       return frame_info->frame + 4;
     }
   else
     return frame_info->frame;
 }
 
 CORE_ADDR
-delta68_frame_saved_pc (frame_info)
-     struct frame_info * frame_info;
+delta68_frame_saved_pc (struct frame_info *frame_info)
 {
   return read_memory_integer (delta68_frame_args_address (frame_info) + 4, 4);
 }
@@ -124,8 +367,7 @@ delta68_frame_saved_pc (frame_info)
    Can return -1, meaning no way to tell.  */
 
 int
-isi_frame_num_args (fi)
-     struct frame_info *fi;
+isi_frame_num_args (struct frame_info *fi)
 {
   int val;
   CORE_ADDR pc = FRAME_SAVED_PC (fi);
@@ -147,8 +389,7 @@ isi_frame_num_args (fi)
 }
 
 int
-delta68_frame_num_args (fi)
-     struct frame_info *fi;
+delta68_frame_num_args (struct frame_info *fi)
 {
   int val;
   CORE_ADDR pc = FRAME_SAVED_PC (fi);
@@ -170,8 +411,7 @@ delta68_frame_num_args (fi)
 }
 
 int
-news_frame_num_args (fi)
-     struct frame_info *fi;
+news_frame_num_args (struct frame_info *fi)
 {
   int val;
   CORE_ADDR pc = FRAME_SAVED_PC (fi);
@@ -192,10 +432,24 @@ news_frame_num_args (fi)
   return val;
 }
 
+/* Insert the specified number of args and function address
+   into a call sequence of the above form stored at DUMMYNAME.
+   We use the BFD routines to store a big-endian value of known size.  */
+
+void
+m68k_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+                    struct value **args, struct type *type, int gcc_p)
+{
+  bfd_putb32 (fun, (unsigned char *) dummy + CALL_DUMMY_START_OFFSET + 2);
+  bfd_putb32 (nargs * 4,
+             (unsigned char *) dummy + CALL_DUMMY_START_OFFSET + 8);
+}
+
+
 /* Push an empty stack frame, to record the current PC, etc.  */
 
 void
-m68k_push_dummy_frame ()
+m68k_push_dummy_frame (void)
 {
   register CORE_ADDR sp = read_register (SP_REGNUM);
   register int regnum;
@@ -209,7 +463,7 @@ m68k_push_dummy_frame ()
      this target or not.  */
   for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
     {
-      read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
+      deprecated_read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
       sp = push_bytes (sp, raw_buffer, 12);
     }
 
@@ -225,34 +479,36 @@ m68k_push_dummy_frame ()
    restoring all saved registers.  */
 
 void
-m68k_pop_frame ()
+m68k_pop_frame (void)
 {
   register struct frame_info *frame = get_current_frame ();
   register CORE_ADDR fp;
   register int regnum;
-  struct frame_saved_regs fsr;
   char raw_buffer[12];
 
   fp = FRAME_FP (frame);
-  get_frame_saved_regs (frame, &fsr);
+  m68k_frame_init_saved_regs (frame);
   for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
     {
-      if (fsr.regs[regnum])
+      if (frame->saved_regs[regnum])
        {
-         read_memory (fsr.regs[regnum], raw_buffer, 12);
-         write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
+         read_memory (frame->saved_regs[regnum], raw_buffer, 12);
+         deprecated_write_register_bytes (REGISTER_BYTE (regnum), raw_buffer,
+                                          12);
        }
     }
   for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
     {
-      if (fsr.regs[regnum])
+      if (frame->saved_regs[regnum])
        {
-         write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+         write_register (regnum,
+                         read_memory_integer (frame->saved_regs[regnum], 4));
        }
     }
-  if (fsr.regs[PS_REGNUM])
+  if (frame->saved_regs[PS_REGNUM])
     {
-      write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
+      write_register (PS_REGNUM,
+                     read_memory_integer (frame->saved_regs[PS_REGNUM], 4));
     }
   write_register (FP_REGNUM, read_memory_integer (fp, 4));
   write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
@@ -294,8 +550,7 @@ m68k_pop_frame ()
  */
 
 CORE_ADDR
-m68k_skip_prologue (ip)
-     CORE_ADDR ip;
+m68k_skip_prologue (CORE_ADDR ip)
 {
   register CORE_ADDR limit;
   struct symtab_and_line sal;
@@ -305,7 +560,7 @@ m68k_skip_prologue (ip)
      If so, ensure we don't go past it.  If not, assume "infinity". */
 
   sal = find_pc_line (ip, 0);
-  limit = (sal.end) ? sal.end : (CORE_ADDR) ~ 0;
+  limit = (sal.end) ? sal.end : (CORE_ADDR) ~0;
 
   while (ip < limit)
     {
@@ -325,15 +580,19 @@ m68k_skip_prologue (ip)
       else if (op == P_FMOVM)
        ip += 10;               /* Skip fmovm */
       else
-       break;          /* Found unknown code, bail out. */
+       break;                  /* Found unknown code, bail out. */
     }
   return (ip);
 }
 
+/* Store the addresses of the saved registers of the frame described by 
+   FRAME_INFO in its saved_regs field.
+   This includes special registers such as pc and fp saved in special
+   ways in the stack frame.  sp is even more special:
+   the address we return for it IS the sp for the next frame.  */
+
 void
-m68k_find_saved_regs (frame_info, saved_regs)
-     struct frame_info *frame_info;
-     struct frame_saved_regs *saved_regs;
+m68k_frame_init_saved_regs (struct frame_info *frame_info)
 {
   register int regnum;
   register int regmask;
@@ -342,10 +601,17 @@ m68k_find_saved_regs (frame_info, saved_regs)
 
   /* First possible address for a pc in a call dummy for this frame.  */
   CORE_ADDR possible_call_dummy_start =
-  (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM * 4 - 4 - 8 * 12;
+    (frame_info)->frame - 28 - FP_REGNUM * 4 - 4 - 8 * 12;
 
   int nextinsn;
-  memset (saved_regs, 0, sizeof (*saved_regs));
+
+  if (frame_info->saved_regs)
+    return;
+
+  frame_saved_regs_zalloc (frame_info);
+
+  memset (frame_info->saved_regs, 0, SIZEOF_FRAME_SAVED_REGS);
+
   if ((frame_info)->pc >= possible_call_dummy_start
       && (frame_info)->pc <= (frame_info)->frame)
     {
@@ -395,7 +661,7 @@ m68k_find_saved_regs (frame_info, saved_regs)
        next_addr += read_memory_integer (pc += 2, 4), pc += 4;
     }
 
-  for ( ; ; )
+  for (;;)
     {
       nextinsn = 0xffff & read_memory_integer (pc, 2);
       regmask = read_memory_integer (pc + 2, 2);
@@ -405,7 +671,7 @@ m68k_find_saved_regs (frame_info, saved_regs)
          /* Regmask's low bit is for register fp7, the first pushed */
          for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
            if (regmask & 1)
-             saved_regs->regs[regnum] = (next_addr -= 12);
+             frame_info->saved_regs[regnum] = (next_addr -= 12);
          pc += 4;
        }
       /* fmovemx to (fp + displacement) */
@@ -418,7 +684,7 @@ m68k_find_saved_regs (frame_info, saved_regs)
          for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = addr;
+               frame_info->saved_regs[regnum] = addr;
                addr += 12;
              }
          pc += 6;
@@ -430,7 +696,7 @@ m68k_find_saved_regs (frame_info, saved_regs)
          for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = next_addr;
+               frame_info->saved_regs[regnum] = next_addr;
                next_addr += 4;
              }
          pc += 4;
@@ -445,7 +711,7 @@ m68k_find_saved_regs (frame_info, saved_regs)
          for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = addr;
+               frame_info->saved_regs[regnum] = addr;
                addr += 4;
              }
          pc += 6;
@@ -456,14 +722,14 @@ m68k_find_saved_regs (frame_info, saved_regs)
          /* Regmask's low bit is for register 15, the first pushed */
          for (regnum = 16; --regnum >= 0; regmask >>= 1)
            if (regmask & 1)
-             saved_regs->regs[regnum] = (next_addr -= 4);
+             frame_info->saved_regs[regnum] = (next_addr -= 4);
          pc += 4;
        }
       /* movl r,-(sp) */
       else if (0x2f00 == (0xfff0 & nextinsn))
        {
          regnum = 0xf & nextinsn;
-         saved_regs->regs[regnum] = (next_addr -= 4);
+         frame_info->saved_regs[regnum] = (next_addr -= 4);
          pc += 2;
        }
       /* fmovemx to index of sp */
@@ -473,7 +739,7 @@ m68k_find_saved_regs (frame_info, saved_regs)
          for (regnum = FP0_REGNUM + 8; --regnum >= FP0_REGNUM; regmask >>= 1)
            if (regmask & 1)
              {
-               saved_regs->regs[regnum] = next_addr;
+               frame_info->saved_regs[regnum] = next_addr;
                next_addr += 12;
              }
          pc += 10;
@@ -481,20 +747,21 @@ m68k_find_saved_regs (frame_info, saved_regs)
       /* clrw -(sp); movw ccr,-(sp) */
       else if (0x4267 == nextinsn && 0x42e7 == regmask)
        {
-         saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
+         frame_info->saved_regs[PS_REGNUM] = (next_addr -= 4);
          pc += 4;
        }
       else
        break;
     }
 lose:;
-  saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
-  saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
-  saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
+  frame_info->saved_regs[SP_REGNUM] = (frame_info)->frame + 8;
+  frame_info->saved_regs[FP_REGNUM] = (frame_info)->frame;
+  frame_info->saved_regs[PC_REGNUM] = (frame_info)->frame + 4;
 #ifdef SIG_SP_FP_OFFSET
   /* Adjust saved SP_REGNUM for fake _sigtramp frames.  */
-  if (frame_info->signal_handler_caller && frame_info->next)
-    saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
+  if ((get_frame_type (frame_info) == SIGTRAMP_FRAME) && frame_info->next)
+    frame_info->saved_regs[SP_REGNUM] =
+      frame_info->next->frame + SIG_SP_FP_OFFSET;
 #endif
 }
 
@@ -503,6 +770,9 @@ lose:;
 
 #include <sys/procfs.h>
 
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
+
 /*  The /proc interface divides the target machine's register set up into
    two different sets, the general register set (gregset) and the floating
    point register set (fpregset).  For each set, there is an ioctl to get
@@ -544,8 +814,7 @@ lose:;
    register values. */
 
 void
-supply_gregset (gregsetp)
-     gregset_t *gregsetp;
+supply_gregset (gregset_t *gregsetp)
 {
   register int regi;
   register greg_t *regp = (greg_t *) gregsetp;
@@ -559,9 +828,7 @@ supply_gregset (gregsetp)
 }
 
 void
-fill_gregset (gregsetp, regno)
-     gregset_t *gregsetp;
-     int regno;
+fill_gregset (gregset_t *gregsetp, int regno)
 {
   register int regi;
   register greg_t *regp = (greg_t *) gregsetp;
@@ -570,16 +837,16 @@ fill_gregset (gregsetp, regno)
     {
       if ((regno == -1) || (regno == regi))
        {
-         *(regp + regi) = *(int *) &registers[REGISTER_BYTE (regi)];
+         *(regp + regi) = *(int *) &deprecated_registers[REGISTER_BYTE (regi)];
        }
     }
   if ((regno == -1) || (regno == PS_REGNUM))
     {
-      *(regp + R_PS) = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
+      *(regp + R_PS) = *(int *) &deprecated_registers[REGISTER_BYTE (PS_REGNUM)];
     }
   if ((regno == -1) || (regno == PC_REGNUM))
     {
-      *(regp + R_PC) = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+      *(regp + R_PC) = *(int *) &deprecated_registers[REGISTER_BYTE (PC_REGNUM)];
     }
 }
 
@@ -590,20 +857,19 @@ fill_gregset (gregsetp, regno)
    idea of the current floating point register values. */
 
 void
-supply_fpregset (fpregsetp)
-     fpregset_t *fpregsetp;
+supply_fpregset (fpregset_t *fpregsetp)
 {
   register int regi;
   char *from;
 
-  for (regi = FP0_REGNUM; regi < FPC_REGNUM; regi++)
+  for (regi = FP0_REGNUM; regi < E_FPC_REGNUM; regi++)
     {
       from = (char *) &(fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
       supply_register (regi, from);
     }
-  supply_register (FPC_REGNUM, (char *) &(fpregsetp->f_pcr));
-  supply_register (FPS_REGNUM, (char *) &(fpregsetp->f_psr));
-  supply_register (FPI_REGNUM, (char *) &(fpregsetp->f_fpiaddr));
+  supply_register (E_FPC_REGNUM, (char *) &(fpregsetp->f_pcr));
+  supply_register (E_FPS_REGNUM, (char *) &(fpregsetp->f_psr));
+  supply_register (E_FPI_REGNUM, (char *) &(fpregsetp->f_fpiaddr));
 }
 
 /*  Given a pointer to a floating point register set in /proc format
@@ -612,34 +878,32 @@ supply_fpregset (fpregsetp)
    them all. */
 
 void
-fill_fpregset (fpregsetp, regno)
-     fpregset_t *fpregsetp;
-     int regno;
+fill_fpregset (fpregset_t *fpregsetp, int regno)
 {
   int regi;
   char *to;
   char *from;
 
-  for (regi = FP0_REGNUM; regi < FPC_REGNUM; regi++)
+  for (regi = FP0_REGNUM; regi < E_FPC_REGNUM; regi++)
     {
       if ((regno == -1) || (regno == regi))
        {
-         from = (char *) &registers[REGISTER_BYTE (regi)];
+         from = (char *) &deprecated_registers[REGISTER_BYTE (regi)];
          to = (char *) &(fpregsetp->f_fpregs[regi - FP0_REGNUM][0]);
          memcpy (to, from, REGISTER_RAW_SIZE (regi));
        }
     }
-  if ((regno == -1) || (regno == FPC_REGNUM))
+  if ((regno == -1) || (regno == E_FPC_REGNUM))
     {
-      fpregsetp->f_pcr = *(int *) &registers[REGISTER_BYTE (FPC_REGNUM)];
+      fpregsetp->f_pcr = *(int *) &deprecated_registers[REGISTER_BYTE (E_FPC_REGNUM)];
     }
-  if ((regno == -1) || (regno == FPS_REGNUM))
+  if ((regno == -1) || (regno == E_FPS_REGNUM))
     {
-      fpregsetp->f_psr = *(int *) &registers[REGISTER_BYTE (FPS_REGNUM)];
+      fpregsetp->f_psr = *(int *) &deprecated_registers[REGISTER_BYTE (E_FPS_REGNUM)];
     }
-  if ((regno == -1) || (regno == FPI_REGNUM))
+  if ((regno == -1) || (regno == E_FPI_REGNUM))
     {
-      fpregsetp->f_fpiaddr = *(int *) &registers[REGISTER_BYTE (FPI_REGNUM)];
+      fpregsetp->f_fpiaddr = *(int *) &deprecated_registers[REGISTER_BYTE (E_FPI_REGNUM)];
     }
 }
 
@@ -647,24 +911,28 @@ fill_fpregset (fpregsetp, regno)
 
 #endif /* USE_PROC_FS */
 
-#ifdef GET_LONGJMP_TARGET
 /* Figure out where the longjmp will land.  Slurp the args out of the stack.
    We expect the first arg to be a pointer to the jmp_buf structure from which
    we extract the pc (JB_PC) that we will land at.  The pc is copied into PC.
    This routine returns true on success. */
 
+/* NOTE: cagney/2000-11-08: For this function to be fully multi-arched
+   the macro's JB_PC and JB_ELEMENT_SIZE would need to be moved into
+   the ``struct gdbarch_tdep'' object and then set on a target ISA/ABI
+   dependant basis. */
+
 int
-get_longjmp_target (pc)
-     CORE_ADDR *pc;
+m68k_get_longjmp_target (CORE_ADDR *pc)
 {
-  char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+#if defined (JB_PC) && defined (JB_ELEMENT_SIZE)
+  char *buf;
   CORE_ADDR sp, jb_addr;
 
+  buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
   sp = read_register (SP_REGNUM);
 
-  if (target_read_memory (sp + SP_ARG0,                /* Offset of first arg on stack */
-                         buf,
-                         TARGET_PTR_BIT / TARGET_CHAR_BIT))
+  if (target_read_memory (sp + SP_ARG0,        /* Offset of first arg on stack */
+                         buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
     return 0;
 
   jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
@@ -676,8 +944,12 @@ get_longjmp_target (pc)
   *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
 
   return 1;
+#else
+  internal_error (__FILE__, __LINE__,
+                 "m68k_get_longjmp_target: not implemented");
+  return 0;
+#endif
 }
-#endif /* GET_LONGJMP_TARGET */
 
 /* Immediately after a function call, return the saved pc before the frame
    is setup.  For sun3's, we check for the common case of being inside of a
@@ -685,8 +957,7 @@ get_longjmp_target (pc)
    prior to doing the trap. */
 
 CORE_ADDR
-m68k_saved_pc_after_call (frame)
-     struct frame_info *frame;
+m68k_saved_pc_after_call (struct frame_info *frame)
 {
 #ifdef SYSCALL_TRAP
   int op;
@@ -700,9 +971,112 @@ m68k_saved_pc_after_call (frame)
     return read_memory_integer (read_register (SP_REGNUM), 4);
 }
 
+/* Function: m68k_gdbarch_init
+   Initializer function for the m68k gdbarch vector.
+   Called by gdbarch.  Sets up the gdbarch vector(s) for this target. */
+
+static struct gdbarch *
+m68k_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  static LONGEST call_dummy_words[7] = { 0xf227e0ff, 0x48e7fffc, 0x426742e7,
+    0x4eb93232, 0x3232dffc, 0x69696969,
+    (0x4e404e71 | (BPT_VECTOR << 16))
+  };
+  struct gdbarch_tdep *tdep = NULL;
+  struct gdbarch *gdbarch;
+
+  /* find a candidate among the list of pre-declared architectures. */
+  arches = gdbarch_list_lookup_by_info (arches, &info);
+  if (arches != NULL)
+    return (arches->gdbarch);
+
+#if 0
+  tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+#endif
+  gdbarch = gdbarch_alloc (&info, 0);
+
+  set_gdbarch_long_double_format (gdbarch, &floatformat_m68881_ext);
+  set_gdbarch_long_double_bit (gdbarch, 96);
+
+  set_gdbarch_function_start_offset (gdbarch, 0);
+
+  set_gdbarch_skip_prologue (gdbarch, m68k_skip_prologue);
+  set_gdbarch_saved_pc_after_call (gdbarch, m68k_saved_pc_after_call);
+  set_gdbarch_breakpoint_from_pc (gdbarch, m68k_local_breakpoint_from_pc);
+
+  /* Stack grows down. */
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  set_gdbarch_stack_align (gdbarch, m68k_stack_align);
+
+
+  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+  set_gdbarch_decr_pc_after_break (gdbarch, 2);
+
+  set_gdbarch_store_struct_return (gdbarch, m68k_store_struct_return);
+  set_gdbarch_deprecated_extract_return_value (gdbarch,
+                                              m68k_deprecated_extract_return_value);
+  set_gdbarch_deprecated_store_return_value (gdbarch, m68k_store_return_value);
+
+  set_gdbarch_frame_chain (gdbarch, m68k_frame_chain);
+  set_gdbarch_frame_chain_valid (gdbarch, generic_func_frame_chain_valid);
+  set_gdbarch_frame_saved_pc (gdbarch, m68k_frame_saved_pc);
+  set_gdbarch_frame_init_saved_regs (gdbarch, m68k_frame_init_saved_regs);
+  set_gdbarch_frameless_function_invocation (gdbarch,
+                                            m68k_frameless_function_invocation);
+  /* OK to default this value to 'unknown'. */
+  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+  set_gdbarch_frame_args_skip (gdbarch, 8);
+  set_gdbarch_frame_args_address (gdbarch, default_frame_address);
+  set_gdbarch_frame_locals_address (gdbarch, default_frame_address);
+
+  set_gdbarch_register_raw_size (gdbarch, m68k_register_raw_size);
+  set_gdbarch_register_virtual_size (gdbarch, m68k_register_virtual_size);
+  set_gdbarch_max_register_raw_size (gdbarch, 12);
+  set_gdbarch_max_register_virtual_size (gdbarch, 12);
+  set_gdbarch_register_virtual_type (gdbarch, m68k_register_virtual_type);
+  set_gdbarch_register_name (gdbarch, m68k_register_name);
+  set_gdbarch_register_size (gdbarch, 4);
+  set_gdbarch_register_byte (gdbarch, m68k_register_byte);
+  set_gdbarch_num_regs (gdbarch, 29);
+  set_gdbarch_register_bytes_ok (gdbarch, m68k_register_bytes_ok);
+  set_gdbarch_register_bytes (gdbarch, (16 * 4 + 8 + 8 * 12 + 3 * 4));
+  set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
+  set_gdbarch_fp_regnum (gdbarch, E_FP_REGNUM);
+  set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
+  set_gdbarch_ps_regnum (gdbarch, E_PS_REGNUM);
+  set_gdbarch_fp0_regnum (gdbarch, E_FP0_REGNUM);
+
+  set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
+  set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
+  set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
+  set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 24);
+  set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
+  set_gdbarch_call_dummy_p (gdbarch, 1);
+  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+  set_gdbarch_call_dummy_length (gdbarch, 28);
+  set_gdbarch_call_dummy_start_offset (gdbarch, 12);
+
+  set_gdbarch_call_dummy_words (gdbarch, call_dummy_words);
+  set_gdbarch_sizeof_call_dummy_words (gdbarch, sizeof (call_dummy_words));
+  set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+  set_gdbarch_fix_call_dummy (gdbarch, m68k_fix_call_dummy);
+  set_gdbarch_push_dummy_frame (gdbarch, m68k_push_dummy_frame);
+  set_gdbarch_pop_frame (gdbarch, m68k_pop_frame);
+
+  return gdbarch;
+}
+
+
+static void
+m68k_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+{
+
+}
 
 void
-_initialize_m68k_tdep ()
+_initialize_m68k_tdep (void)
 {
+  gdbarch_register (bfd_arch_m68k, m68k_gdbarch_init, m68k_dump_tdep);
   tm_print_insn = print_insn_m68k;
 }
This page took 0.061964 seconds and 4 git commands to generate.