* alpha-tdep.h (struct gdbarch_tdep): Add members `sc_pc_offset',
[deliverable/binutils-gdb.git] / gdb / alpha-tdep.c
index fd8c88ee75d052f1a81a5021bc7b80b2ae0723d7..0a3185fd8909c99ec424117e046a763545cd7efa 100644 (file)
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
+#include "doublest.h"
 #include "frame.h"
 #include "frame-unwind.h"
 #include "frame-base.h"
+#include "dwarf2-frame.h"
 #include "inferior.h"
 #include "symtab.h"
 #include "value.h"
@@ -34,7 +36,7 @@
 #include "gdb_string.h"
 #include "linespec.h"
 #include "regcache.h"
-#include "doublest.h"
+#include "reggroups.h"
 #include "arch-utils.h"
 #include "osabi.h"
 #include "block.h"
@@ -47,7 +49,7 @@
 static const char *
 alpha_register_name (int regno)
 {
-  static char *register_names[] =
+  static const char * const register_names[] =
   {
     "v0",   "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",
     "t7",   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "fp",
@@ -57,39 +59,83 @@ alpha_register_name (int regno)
     "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
     "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
     "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "fpcr",
-    "pc",   "vfp",  "unique",
+    "pc",   "",     "unique"
   };
 
   if (regno < 0)
-    return (NULL);
+    return NULL;
   if (regno >= (sizeof(register_names) / sizeof(*register_names)))
-    return (NULL);
-  return (register_names[regno]);
+    return NULL;
+  return register_names[regno];
 }
 
 static int
 alpha_cannot_fetch_register (int regno)
 {
-  return (regno == ALPHA_FP_REGNUM || regno == ALPHA_ZERO_REGNUM);
+  return regno == ALPHA_ZERO_REGNUM;
 }
 
 static int
 alpha_cannot_store_register (int regno)
 {
-  return (regno == ALPHA_FP_REGNUM || regno == ALPHA_ZERO_REGNUM);
+  return regno == ALPHA_ZERO_REGNUM;
 }
 
-static int
-alpha_register_convertible (int regno)
+static struct type *
+alpha_register_type (struct gdbarch *gdbarch, int regno)
 {
-  return (regno >= FP0_REGNUM && regno <= FP0_REGNUM + 31);
+  if (regno == ALPHA_SP_REGNUM || regno == ALPHA_GP_REGNUM)
+    return builtin_type_void_data_ptr;
+  if (regno == ALPHA_PC_REGNUM)
+    return builtin_type_void_func_ptr;
+
+  /* Don't need to worry about little vs big endian until 
+     some jerk tries to port to alpha-unicosmk.  */
+  if (regno >= ALPHA_FP0_REGNUM && regno < ALPHA_FP0_REGNUM + 31)
+    return builtin_type_ieee_double_little;
+
+  return builtin_type_int64;
 }
 
-static struct type *
-alpha_register_virtual_type (int regno)
+/* Is REGNUM a member of REGGROUP?  */
+
+static int
+alpha_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                          struct reggroup *group)
 {
-  return ((regno >= FP0_REGNUM && regno < (FP0_REGNUM+31))
-         ? builtin_type_double : builtin_type_long);
+  /* Filter out any registers eliminated, but whose regnum is 
+     reserved for backward compatibility, e.g. the vfp.  */
+  if (REGISTER_NAME (regnum) == NULL || *REGISTER_NAME (regnum) == '\0')
+    return 0;
+
+  if (group == all_reggroup)
+    return 1;
+
+  /* Zero should not be saved or restored.  Technically it is a general
+     register (just as $f31 would be a float if we represented it), but
+     there's no point displaying it during "info regs", so leave it out
+     of all groups except for "all".  */
+  if (regnum == ALPHA_ZERO_REGNUM)
+    return 0;
+
+  /* All other registers are saved and restored.  */
+  if (group == save_reggroup || group == restore_reggroup)
+    return 1;
+
+  /* All other groups are non-overlapping.  */
+
+  /* Since this is really a PALcode memory slot...  */
+  if (regnum == ALPHA_UNIQUE_REGNUM)
+    return group == system_reggroup;
+
+  /* Force the FPCR to be considered part of the floating point state.  */
+  if (regnum == ALPHA_FPCR_REGNUM)
+    return group == float_reggroup;
+
+  if (regnum >= ALPHA_FP0_REGNUM && regnum < ALPHA_FP0_REGNUM + 31)
+    return group == float_reggroup;
+  else
+    return group == general_reggroup;
 }
 
 static int
@@ -110,65 +156,97 @@ alpha_register_virtual_size (int regno)
   return 8;
 }
 
-/* The alpha needs a conversion between register and memory format if the
-   register is a floating point register and memory format is float, as the
-   register format must be double or memory format is an integer with 4
-   bytes or less, as the representation of integers in floating point
-   registers is different. */
+/* The following represents exactly the conversion performed by
+   the LDS instruction.  This applies to both single-precision
+   floating point and 32-bit integers.  */
 
 static void
-alpha_register_convert_to_virtual (int regnum, struct type *valtype,
-                                  char *raw_buffer, char *virtual_buffer)
+alpha_lds (void *out, const void *in)
 {
-  if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
-    {
-      memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
-      return;
-    }
-
-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+  ULONGEST mem     = extract_unsigned_integer (in, 4);
+  ULONGEST frac    = (mem >>  0) & 0x7fffff;
+  ULONGEST sign    = (mem >> 31) & 1;
+  ULONGEST exp_msb = (mem >> 30) & 1;
+  ULONGEST exp_low = (mem >> 23) & 0x7f;
+  ULONGEST exp, reg;
+
+  exp = (exp_msb << 10) | exp_low;
+  if (exp_msb)
     {
-      double d = deprecated_extract_floating (raw_buffer, REGISTER_RAW_SIZE (regnum));
-      deprecated_store_floating (virtual_buffer, TYPE_LENGTH (valtype), d);
+      if (exp_low == 0x7f)
+       exp = 0x7ff;
     }
-  else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
+  else
     {
-      ULONGEST l;
-      l = extract_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum));
-      l = ((l >> 32) & 0xc0000000) | ((l >> 29) & 0x3fffffff);
-      store_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype), l);
+      if (exp_low != 0x00)
+       exp |= 0x380;
     }
-  else
-    error ("Cannot retrieve value from floating point register");
+
+  reg = (sign << 63) | (exp << 52) | (frac << 29);
+  store_unsigned_integer (out, 8, reg);
+}
+
+/* Similarly, this represents exactly the conversion performed by
+   the STS instruction.  */
+
+static inline void
+alpha_sts (void *out, const void *in)
+{
+  ULONGEST reg, mem;
+
+  reg = extract_unsigned_integer (in, 8);
+  mem = ((reg >> 32) & 0xc0000000) | ((reg >> 29) & 0x3fffffff);
+  store_unsigned_integer (out, 4, mem);
+}
+
+/* The alpha needs a conversion between register and memory format if the
+   register is a floating point register and memory format is float, as the
+   register format must be double or memory format is an integer with 4
+   bytes or less, as the representation of integers in floating point
+   registers is different. */
+
+static int
+alpha_convert_register_p (int regno, struct type *type)
+{
+  return (regno >= ALPHA_FP0_REGNUM && regno < ALPHA_FP0_REGNUM + 31);
 }
 
 static void
-alpha_register_convert_to_raw (struct type *valtype, int regnum,
-                              char *virtual_buffer, char *raw_buffer)
+alpha_register_to_value (struct frame_info *frame, int regnum,
+                        struct type *valtype, void *out)
 {
-  if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
+  char in[MAX_REGISTER_SIZE];
+  frame_register_read (frame, regnum, in);
+  switch (TYPE_LENGTH (valtype))
     {
-      memcpy (raw_buffer, virtual_buffer, REGISTER_RAW_SIZE (regnum));
-      return;
+    case 4:
+      alpha_sts (out, in);
+      break;
+    case 8:
+      memcpy (out, in, 8);
+      break;
+    default:
+      error ("Cannot retrieve value from floating point register");
     }
+}
 
-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
-    {
-      double d = deprecated_extract_floating (virtual_buffer, TYPE_LENGTH (valtype));
-      deprecated_store_floating (raw_buffer, REGISTER_RAW_SIZE (regnum), d);
-    }
-  else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
+static void
+alpha_value_to_register (struct frame_info *frame, int regnum,
+                        struct type *valtype, const void *in)
+{
+  char out[MAX_REGISTER_SIZE];
+  switch (TYPE_LENGTH (valtype))
     {
-      ULONGEST l;
-      if (TYPE_UNSIGNED (valtype))
-       l = extract_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype));
-      else
-       l = extract_signed_integer (virtual_buffer, TYPE_LENGTH (valtype));
-      l = ((l & 0xc0000000) << 32) | ((l & 0x3fffffff) << 29);
-      store_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum), l);
+    case 4:
+      alpha_lds (out, in);
+      break;
+    case 8:
+      memcpy (out, in, 8);
+      break;
+    default:
+      error ("Cannot store value in floating point register");
     }
-  else
-    error ("Cannot store value in floating point register");
+  put_frame_register (frame, regnum, out);
 }
 
 \f
@@ -225,19 +303,27 @@ alpha_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
        case TYPE_CODE_CHAR:
        case TYPE_CODE_RANGE:
        case TYPE_CODE_ENUM:
-         if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
+         if (TYPE_LENGTH (arg_type) == 4)
+           {
+             /* 32-bit values must be sign-extended to 64 bits
+                even if the base data type is unsigned.  */
+             arg_type = builtin_type_int32;
+             arg = value_cast (arg_type, arg);
+           }
+         if (TYPE_LENGTH (arg_type) < ALPHA_REGISTER_SIZE)
            {
-             arg_type = builtin_type_long;
+             arg_type = builtin_type_int64;
              arg = value_cast (arg_type, arg);
            }
          break;
+
        case TYPE_CODE_FLT:
          /* "float" arguments loaded in registers must be passed in
             register format, aka "double".  */
          if (accumulate_size < sizeof (arg_reg_buffer)
              && TYPE_LENGTH (arg_type) == 4)
            {
-             arg_type = builtin_type_double;
+             arg_type = builtin_type_ieee_double_little;
              arg = value_cast (arg_type, arg);
            }
          /* Tru64 5.1 has a 128-bit long double, and passes this by
@@ -255,6 +341,28 @@ alpha_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
              arg = value_from_pointer (arg_type, sp);
            }
          break;
+
+       case TYPE_CODE_COMPLEX:
+         /* ??? The ABI says that complex values are passed as two
+            separate scalar values.  This distinction only matters
+            for complex float.  However, GCC does not implement this.  */
+
+         /* Tru64 5.1 has a 128-bit long double, and passes this by
+            invisible reference.  */
+         if (TYPE_LENGTH (arg_type) == 32)
+           {
+             /* Allocate aligned storage.  */
+             sp = (sp & -16) - 16;
+
+             /* Write the real data into the stack.  */
+             write_memory (sp, VALUE_CONTENTS (arg), 32);
+
+             /* Construct the indirection.  */
+             arg_type = lookup_pointer_type (arg_type);
+             arg = value_from_pointer (arg_type, sp);
+           }
+         break;
+
        default:
          break;
        }
@@ -314,74 +422,167 @@ alpha_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   /* Load the argument registers.  */
   for (i = 0; i < required_arg_regs; i++)
     {
-      LONGEST val;
-
-      val = extract_unsigned_integer (arg_reg_buffer + i*ALPHA_REGISTER_SIZE,
-                                     ALPHA_REGISTER_SIZE);
-      regcache_cooked_write_signed (regcache, ALPHA_A0_REGNUM + i, val);
-      regcache_cooked_write_signed (regcache, ALPHA_FPA0_REGNUM + i, val);
+      regcache_cooked_write (regcache, ALPHA_A0_REGNUM + i,
+                            arg_reg_buffer + i*ALPHA_REGISTER_SIZE);
+      regcache_cooked_write (regcache, ALPHA_FPA0_REGNUM + i,
+                            arg_reg_buffer + i*ALPHA_REGISTER_SIZE);
     }
 
-  return sp;
-}
-
-/* Given a return value in `regbuf' with a type `valtype', 
-   extract and copy its value into `valbuf'.  */
+  /* Finally, update the stack pointer.  */
+  regcache_cooked_write_signed (regcache, ALPHA_SP_REGNUM, sp);
 
-static void
-alpha_extract_return_value (struct type *valtype,
-                           char regbuf[ALPHA_REGISTER_BYTES], char *valbuf)
-{
-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
-    alpha_register_convert_to_virtual (FP0_REGNUM, valtype,
-                                      regbuf + REGISTER_BYTE (FP0_REGNUM),
-                                      valbuf);
-  else
-    memcpy (valbuf, regbuf + REGISTER_BYTE (ALPHA_V0_REGNUM),
-            TYPE_LENGTH (valtype));
+  return sp;
 }
 
-/* Given a return value in `regbuf' with a type `valtype', 
-   write its value into the appropriate register.  */
+/* Extract from REGCACHE the value about to be returned from a function
+   and copy it into VALBUF.  */
 
 static void
-alpha_store_return_value (struct type *valtype, char *valbuf)
+alpha_extract_return_value (struct type *valtype, struct regcache *regcache,
+                           void *valbuf)
 {
-  char raw_buffer[ALPHA_MAX_REGISTER_RAW_SIZE];
-  int regnum = ALPHA_V0_REGNUM;
   int length = TYPE_LENGTH (valtype);
+  char raw_buffer[ALPHA_REGISTER_SIZE];
+  ULONGEST l;
 
-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+  switch (TYPE_CODE (valtype))
     {
-      regnum = FP0_REGNUM;
-      length = REGISTER_RAW_SIZE (regnum);
-      alpha_register_convert_to_raw (valtype, regnum, valbuf, raw_buffer);
-    }
-  else
-    memcpy (raw_buffer, valbuf, length);
+    case TYPE_CODE_FLT:
+      switch (length)
+       {
+       case 4:
+         regcache_cooked_read (regcache, ALPHA_FP0_REGNUM, raw_buffer);
+         alpha_sts (valbuf, raw_buffer);
+         break;
 
-  deprecated_write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, length);
+       case 8:
+         regcache_cooked_read (regcache, ALPHA_FP0_REGNUM, valbuf);
+         break;
+
+       case 16:
+         regcache_cooked_read_unsigned (regcache, ALPHA_V0_REGNUM, &l);
+         read_memory (l, valbuf, 16);
+         break;
+
+       default:
+         internal_error (__FILE__, __LINE__, "unknown floating point width");
+       }
+      break;
+
+    case TYPE_CODE_COMPLEX:
+      switch (length)
+       {
+       case 8:
+         /* ??? This isn't correct wrt the ABI, but it's what GCC does.  */
+         regcache_cooked_read (regcache, ALPHA_FP0_REGNUM, valbuf);
+         break;
+
+       case 16:
+         regcache_cooked_read (regcache, ALPHA_FP0_REGNUM, valbuf);
+         regcache_cooked_read (regcache, ALPHA_FP0_REGNUM+1,
+                               (char *)valbuf + 8);
+         break;
+
+       case 32:
+         regcache_cooked_read_signed (regcache, ALPHA_V0_REGNUM, &l);
+         read_memory (l, valbuf, 32);
+         break;
+
+       default:
+         internal_error (__FILE__, __LINE__, "unknown floating point width");
+       }
+      break;
+
+    default:
+      /* Assume everything else degenerates to an integer.  */
+      regcache_cooked_read_unsigned (regcache, ALPHA_V0_REGNUM, &l);
+      store_unsigned_integer (valbuf, length, l);
+      break;
+    }
 }
 
-static int
-alpha_use_struct_convention (int gcc_p, struct type *type)
+/* Extract from REGCACHE the address of a structure about to be returned
+   from a function.  */
+
+static CORE_ADDR
+alpha_extract_struct_value_address (struct regcache *regcache)
 {
-  /* Structures are returned by ref in extra arg0.  */
-  return 1;
+  ULONGEST addr;
+  regcache_cooked_read_unsigned (regcache, ALPHA_V0_REGNUM, &addr);
+  return addr;
 }
 
+/* Insert the given value into REGCACHE as if it was being 
+   returned by a function.  */
+
 static void
-alpha_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+alpha_store_return_value (struct type *valtype, struct regcache *regcache,
+                         const void *valbuf)
 {
-  /* Store the address of the place in which to copy the structure the
-     subroutine will return.  Handled by alpha_push_arguments.  */
-}
+  int length = TYPE_LENGTH (valtype);
+  char raw_buffer[ALPHA_REGISTER_SIZE];
+  ULONGEST l;
 
-static CORE_ADDR
-alpha_extract_struct_value_address (char *regbuf)
-{
-  return (extract_address (regbuf + REGISTER_BYTE (ALPHA_V0_REGNUM),
-                          REGISTER_RAW_SIZE (ALPHA_V0_REGNUM)));
+  switch (TYPE_CODE (valtype))
+    {
+    case TYPE_CODE_FLT:
+      switch (length)
+       {
+       case 4:
+         alpha_lds (raw_buffer, valbuf);
+         regcache_cooked_write (regcache, ALPHA_FP0_REGNUM, raw_buffer);
+         break;
+
+       case 8:
+         regcache_cooked_write (regcache, ALPHA_FP0_REGNUM, valbuf);
+         break;
+
+       case 16:
+         /* FIXME: 128-bit long doubles are returned like structures:
+            by writing into indirect storage provided by the caller
+            as the first argument.  */
+         error ("Cannot set a 128-bit long double return value.");
+
+       default:
+         internal_error (__FILE__, __LINE__, "unknown floating point width");
+       }
+      break;
+
+    case TYPE_CODE_COMPLEX:
+      switch (length)
+       {
+       case 8:
+         /* ??? This isn't correct wrt the ABI, but it's what GCC does.  */
+         regcache_cooked_write (regcache, ALPHA_FP0_REGNUM, valbuf);
+         break;
+
+       case 16:
+         regcache_cooked_write (regcache, ALPHA_FP0_REGNUM, valbuf);
+         regcache_cooked_write (regcache, ALPHA_FP0_REGNUM+1,
+                                (const char *)valbuf + 8);
+         break;
+
+       case 32:
+         /* FIXME: 128-bit long doubles are returned like structures:
+            by writing into indirect storage provided by the caller
+            as the first argument.  */
+         error ("Cannot set a 128-bit long double return value.");
+
+       default:
+         internal_error (__FILE__, __LINE__, "unknown floating point width");
+       }
+      break;
+
+    default:
+      /* Assume everything else degenerates to an integer.  */
+      /* 32-bit values must be sign-extended to 64 bits
+        even if the base data type is unsigned.  */
+      if (length == 4)
+       valtype = builtin_type_int32;
+      l = unpack_long (valtype, valbuf);
+      regcache_cooked_write_unsigned (regcache, ALPHA_V0_REGNUM, l);
+      break;
+    }
 }
 
 \f
@@ -509,7 +710,7 @@ alpha_get_longjmp_target (CORE_ADDR *pc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
   CORE_ADDR jb_addr;
-  char raw_buffer[ALPHA_MAX_REGISTER_RAW_SIZE];
+  char raw_buffer[ALPHA_REGISTER_SIZE];
 
   jb_addr = read_register (ALPHA_A0_REGNUM);
 
@@ -517,7 +718,7 @@ alpha_get_longjmp_target (CORE_ADDR *pc)
                          raw_buffer, tdep->jb_elt_size))
     return 0;
 
-  *pc = extract_address (raw_buffer, tdep->jb_elt_size);
+  *pc = extract_unsigned_integer (raw_buffer, tdep->jb_elt_size);
   return 1;
 }
 
@@ -552,24 +753,20 @@ alpha_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
   return info;
 }
 
-/* Return the address of REGNO in a sigtramp frame.  Since this is all
-   arithmetic, it doesn't seem worthwhile to cache it.  */
-
-#ifndef SIGFRAME_PC_OFF
-#define SIGFRAME_PC_OFF                (2 * 8)
-#define SIGFRAME_REGSAVE_OFF   (4 * 8)
-#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8)
-#endif
+/* Return the address of REGNUM in a sigtramp frame.  Since this is
+   all arithmetic, it doesn't seem worthwhile to cache it.  */
 
 static CORE_ADDR
-alpha_sigtramp_register_address (CORE_ADDR sigcontext_addr, unsigned int regno)
+alpha_sigtramp_register_address (CORE_ADDR sigcontext_addr, int regnum)
 { 
-  if (regno < 32)
-    return sigcontext_addr + SIGFRAME_REGSAVE_OFF + regno * 8;
-  if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
-    return sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + regno * 8;
-  if (regno == PC_REGNUM)
-    return sigcontext_addr + SIGFRAME_PC_OFF; 
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  if (regnum >= 0 && regnum < 32)
+    return sigcontext_addr + tdep->sc_regs_offset + regnum * 8;
+  else if (regnum >= ALPHA_FP0_REGNUM && regnum < ALPHA_FP0_REGNUM + 32)
+    return sigcontext_addr + tdep->sc_fpregs_offset + regnum * 8;
+  else if (regnum == ALPHA_PC_REGNUM)
+    return sigcontext_addr + tdep->sc_pc_offset; 
 
   return 0;
 }
@@ -611,7 +808,8 @@ alpha_sigtramp_frame_this_id (struct frame_info *next_frame,
   /* The stack address is trivially read from the sigcontext.  */
   stack_addr = alpha_sigtramp_register_address (info->sigcontext_addr,
                                                ALPHA_SP_REGNUM);
-  stack_addr = read_memory_unsigned_integer (stack_addr, ALPHA_REGISTER_SIZE);
+  stack_addr = get_frame_memory_unsigned (next_frame, stack_addr,
+                                         ALPHA_REGISTER_SIZE);
 
   *this_id = frame_id_build (stack_addr, code_addr);
 }
@@ -640,7 +838,7 @@ alpha_sigtramp_frame_prev_register (struct frame_info *next_frame,
          *addrp = addr;
          *realnump = -1;
          if (bufferp != NULL)
-           read_memory (addr, bufferp, ALPHA_REGISTER_SIZE);
+           get_frame_memory (next_frame, addr, bufferp, ALPHA_REGISTER_SIZE);
          return;
        }
     }
@@ -972,7 +1170,7 @@ alpha_heuristic_frame_prev_register (struct frame_info *next_frame,
       *addrp = info->saved_regs[regnum];
       *realnump = -1;
       if (bufferp != NULL)
-       read_memory (*addrp, bufferp, ALPHA_REGISTER_SIZE);
+       get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
       return;
     }
 
@@ -1078,6 +1276,73 @@ alpha_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
   return pc;
 }
 
+\f
+/* Helper routines for alpha*-nat.c files to move register sets to and
+   from core files.  The UNIQUE pointer is allowed to be NULL, as most
+   targets don't supply this value in their core files.  */
+
+void
+alpha_supply_int_regs (int regno, const void *r0_r30,
+                      const void *pc, const void *unique)
+{
+  int i;
+
+  for (i = 0; i < 31; ++i)
+    if (regno == i || regno == -1)
+      supply_register (i, (const char *)r0_r30 + i*8);
+
+  if (regno == ALPHA_ZERO_REGNUM || regno == -1)
+    supply_register (ALPHA_ZERO_REGNUM, NULL);
+
+  if (regno == ALPHA_PC_REGNUM || regno == -1)
+    supply_register (ALPHA_PC_REGNUM, pc);
+
+  if (regno == ALPHA_UNIQUE_REGNUM || regno == -1)
+    supply_register (ALPHA_UNIQUE_REGNUM, unique);
+}
+
+void
+alpha_fill_int_regs (int regno, void *r0_r30, void *pc, void *unique)
+{
+  int i;
+
+  for (i = 0; i < 31; ++i)
+    if (regno == i || regno == -1)
+      regcache_collect (i, (char *)r0_r30 + i*8);
+
+  if (regno == ALPHA_PC_REGNUM || regno == -1)
+    regcache_collect (ALPHA_PC_REGNUM, pc);
+
+  if (unique && (regno == ALPHA_UNIQUE_REGNUM || regno == -1))
+    regcache_collect (ALPHA_UNIQUE_REGNUM, unique);
+}
+
+void
+alpha_supply_fp_regs (int regno, const void *f0_f30, const void *fpcr)
+{
+  int i;
+
+  for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; ++i)
+    if (regno == i || regno == -1)
+      supply_register (i, (const char *)f0_f30 + (i - ALPHA_FP0_REGNUM) * 8);
+
+  if (regno == ALPHA_FPCR_REGNUM || regno == -1)
+    supply_register (ALPHA_FPCR_REGNUM, fpcr);
+}
+
+void
+alpha_fill_fp_regs (int regno, void *f0_f30, void *fpcr)
+{
+  int i;
+
+  for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; ++i)
+    if (regno == i || regno == -1)
+      regcache_collect (i, (char *)f0_f30 + (i - ALPHA_FP0_REGNUM) * 8);
+
+  if (regno == ALPHA_FPCR_REGNUM || regno == -1)
+    regcache_collect (ALPHA_FPCR_REGNUM, fpcr);
+}
+
 \f
 /* alpha_software_single_step() is called just before we want to resume
    the inferior, if we want to single-step it but there is no hardware
@@ -1095,7 +1360,7 @@ alpha_next_pc (CORE_ADDR pc)
   int offset;
   LONGEST rav;
 
-  insn = read_memory_unsigned_integer (pc, sizeof (insn));
+  insn = alpha_read_insn (pc);
 
   /* Opcode is top 6 bits. */
   op = (insn >> 26) & 0x3f;
@@ -1226,6 +1491,9 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   tdep->dynamic_sigtramp_offset = NULL;
   tdep->sigcontext_addr = NULL;
+  tdep->sc_pc_offset = 2 * 8;
+  tdep->sc_regs_offset = 4 * 8;
+  tdep->sc_fpregs_offset = tdep->sc_regs_offset + 32 * 8 + 8;
 
   tdep->jb_pc = -1;    /* longjmp support not enabled by default  */
 
@@ -1242,42 +1510,38 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Register info */
   set_gdbarch_num_regs (gdbarch, ALPHA_NUM_REGS);
   set_gdbarch_sp_regnum (gdbarch, ALPHA_SP_REGNUM);
-  set_gdbarch_deprecated_fp_regnum (gdbarch, ALPHA_FP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, ALPHA_PC_REGNUM);
   set_gdbarch_fp0_regnum (gdbarch, ALPHA_FP0_REGNUM);
 
   set_gdbarch_register_name (gdbarch, alpha_register_name);
-  set_gdbarch_deprecated_register_size (gdbarch, ALPHA_REGISTER_SIZE);
-  set_gdbarch_deprecated_register_bytes (gdbarch, ALPHA_REGISTER_BYTES);
-  set_gdbarch_register_byte (gdbarch, alpha_register_byte);
-  set_gdbarch_register_raw_size (gdbarch, alpha_register_raw_size);
-  set_gdbarch_deprecated_max_register_raw_size (gdbarch, ALPHA_MAX_REGISTER_RAW_SIZE);
-  set_gdbarch_register_virtual_size (gdbarch, alpha_register_virtual_size);
-  set_gdbarch_deprecated_max_register_virtual_size (gdbarch,
-                                         ALPHA_MAX_REGISTER_VIRTUAL_SIZE);
-  set_gdbarch_register_virtual_type (gdbarch, alpha_register_virtual_type);
+  set_gdbarch_deprecated_register_byte (gdbarch, alpha_register_byte);
+  set_gdbarch_deprecated_register_raw_size (gdbarch, alpha_register_raw_size);
+  set_gdbarch_deprecated_register_virtual_size (gdbarch, alpha_register_virtual_size);
+  set_gdbarch_register_type (gdbarch, alpha_register_type);
 
   set_gdbarch_cannot_fetch_register (gdbarch, alpha_cannot_fetch_register);
   set_gdbarch_cannot_store_register (gdbarch, alpha_cannot_store_register);
 
-  set_gdbarch_register_convertible (gdbarch, alpha_register_convertible);
-  set_gdbarch_register_convert_to_virtual (gdbarch,
-                                           alpha_register_convert_to_virtual);
-  set_gdbarch_register_convert_to_raw (gdbarch, alpha_register_convert_to_raw);
+  set_gdbarch_convert_register_p (gdbarch, alpha_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch, alpha_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, alpha_value_to_register);
+
+  set_gdbarch_register_reggroup_p (gdbarch, alpha_register_reggroup_p);
 
   /* Prologue heuristics.  */
   set_gdbarch_skip_prologue (gdbarch, alpha_skip_prologue);
 
+  /* Disassembler.  */
+  set_gdbarch_print_insn (gdbarch, print_insn_alpha);
+
   /* Call info.  */
-  set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
   set_gdbarch_frameless_function_invocation (gdbarch,
                                     generic_frameless_function_invocation_not);
 
-  set_gdbarch_use_struct_convention (gdbarch, alpha_use_struct_convention);
-  set_gdbarch_deprecated_extract_return_value (gdbarch, alpha_extract_return_value);
-  set_gdbarch_deprecated_store_struct_return (gdbarch, alpha_store_struct_return);
-  set_gdbarch_deprecated_store_return_value (gdbarch, alpha_store_return_value);
-  set_gdbarch_deprecated_extract_struct_value_address (gdbarch,
+  set_gdbarch_use_struct_convention (gdbarch, always_use_struct_convention);
+  set_gdbarch_extract_return_value (gdbarch, alpha_extract_return_value);
+  set_gdbarch_store_return_value (gdbarch, alpha_store_return_value);
+  set_gdbarch_extract_struct_value_address (gdbarch,
                                            alpha_extract_struct_value_address);
 
   /* Settings for calling functions in the inferior.  */
@@ -1285,7 +1549,6 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Methods for saving / extracting a dummy frame's ID.  */
   set_gdbarch_unwind_dummy_id (gdbarch, alpha_unwind_dummy_id);
-  set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
 
   /* Return the unwound PC value.  */
   set_gdbarch_unwind_pc (gdbarch, alpha_unwind_pc);
@@ -1316,13 +1579,22 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   return gdbarch;
 }
 
+void
+alpha_dwarf2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  frame_unwind_append_predicate (gdbarch, dwarf2_frame_p);
+  frame_base_append_predicate (gdbarch, dwarf2_frame_base_p);
+  set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info);
+}
+
+extern initialize_file_ftype _initialize_alpha_tdep; /* -Wmissing-prototypes */
+
 void
 _initialize_alpha_tdep (void)
 {
   struct cmd_list_element *c;
 
   gdbarch_register (bfd_arch_alpha, alpha_gdbarch_init, NULL);
-  deprecated_tm_print_insn = print_insn_alpha;
 
   /* Let the user set the fence post for heuristic_proc_start.  */
 
This page took 0.034476 seconds and 4 git commands to generate.