* hppa-tdep.c (read_unwind_info): Fix typo in comment.
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index 46a7b080192ea63eebc796efe060d064688f059f..a10437152640e057e85f346200eded4708596904 100644 (file)
@@ -1,8 +1,8 @@
-/* Target-dependent code for the HP PA architecture, for GDB.
+/* Target-dependent code for the HP PA-RISC architecture.
 
    Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
-   1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
-   Foundation, Inc.
+   1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
 
    Contributed by the Center for Software Science at the
    University of Utah (pa-gdb-bugs@cs.utah.edu).
@@ -72,102 +72,6 @@ const struct objfile_data *hppa_objfile_priv_data = NULL;
    following functions static, once we hppa is partially multiarched.  */
 int hppa_pc_requires_run_before_use (CORE_ADDR pc);
 
-/* Handle 32/64-bit struct return conventions.  */
-
-static enum return_value_convention
-hppa32_return_value (struct gdbarch *gdbarch,
-                    struct type *type, struct regcache *regcache,
-                    void *readbuf, const void *writebuf)
-{
-  if (TYPE_LENGTH (type) <= 2 * 4)
-    {
-      /* The value always lives in the right hand end of the register
-        (or register pair)?  */
-      int b;
-      int reg = TYPE_CODE (type) == TYPE_CODE_FLT ? HPPA_FP4_REGNUM : 28;
-      int part = TYPE_LENGTH (type) % 4;
-      /* The left hand register contains only part of the value,
-        transfer that first so that the rest can be xfered as entire
-        4-byte registers.  */
-      if (part > 0)
-       {
-         if (readbuf != NULL)
-           regcache_cooked_read_part (regcache, reg, 4 - part,
-                                      part, readbuf);
-         if (writebuf != NULL)
-           regcache_cooked_write_part (regcache, reg, 4 - part,
-                                       part, writebuf);
-         reg++;
-       }
-      /* Now transfer the remaining register values.  */
-      for (b = part; b < TYPE_LENGTH (type); b += 4)
-       {
-         if (readbuf != NULL)
-           regcache_cooked_read (regcache, reg, (char *) readbuf + b);
-         if (writebuf != NULL)
-           regcache_cooked_write (regcache, reg, (const char *) writebuf + b);
-         reg++;
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-  else
-    return RETURN_VALUE_STRUCT_CONVENTION;
-}
-
-static enum return_value_convention
-hppa64_return_value (struct gdbarch *gdbarch,
-                    struct type *type, struct regcache *regcache,
-                    void *readbuf, const void *writebuf)
-{
-  /* RM: Floats are returned in FR4R, doubles in FR4.  Integral values
-     are in r28, padded on the left.  Aggregates less that 65 bits are
-     in r28, right padded.  Aggregates upto 128 bits are in r28 and
-     r29, right padded.  */ 
-  if (TYPE_CODE (type) == TYPE_CODE_FLT
-      && TYPE_LENGTH (type) <= 8)
-    {
-      /* Floats are right aligned?  */
-      int offset = register_size (gdbarch, HPPA_FP4_REGNUM) - TYPE_LENGTH (type);
-      if (readbuf != NULL)
-       regcache_cooked_read_part (regcache, HPPA_FP4_REGNUM, offset,
-                                  TYPE_LENGTH (type), readbuf);
-      if (writebuf != NULL)
-       regcache_cooked_write_part (regcache, HPPA_FP4_REGNUM, offset,
-                                   TYPE_LENGTH (type), writebuf);
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-  else if (TYPE_LENGTH (type) <= 8 && is_integral_type (type))
-    {
-      /* Integrals are right aligned.  */
-      int offset = register_size (gdbarch, HPPA_FP4_REGNUM) - TYPE_LENGTH (type);
-      if (readbuf != NULL)
-       regcache_cooked_read_part (regcache, 28, offset,
-                                  TYPE_LENGTH (type), readbuf);
-      if (writebuf != NULL)
-       regcache_cooked_write_part (regcache, 28, offset,
-                                   TYPE_LENGTH (type), writebuf);
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-  else if (TYPE_LENGTH (type) <= 2 * 8)
-    {
-      /* Composite values are left aligned.  */
-      int b;
-      for (b = 0; b < TYPE_LENGTH (type); b += 8)
-       {
-         int part = min (8, TYPE_LENGTH (type) - b);
-         if (readbuf != NULL)
-           regcache_cooked_read_part (regcache, 28 + b / 8, 0, part,
-                                      (char *) readbuf + b);
-         if (writebuf != NULL)
-           regcache_cooked_write_part (regcache, 28 + b / 8, 0, part,
-                                       (const char *) writebuf + b);
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-  else
-    return RETURN_VALUE_STRUCT_CONVENTION;
-}
-
 /* Routines to extract various sized constants out of hppa 
    instructions. */
 
@@ -273,6 +177,20 @@ hppa_symbol_address(const char *sym)
   else
     return (CORE_ADDR)-1;
 }
+
+struct hppa_objfile_private *
+hppa_init_objfile_priv_data (struct objfile *objfile)
+{
+  struct hppa_objfile_private *priv;
+
+  priv = (struct hppa_objfile_private *)
+        obstack_alloc (&objfile->objfile_obstack,
+                       sizeof (struct hppa_objfile_private));
+  set_objfile_data (objfile, hppa_objfile_priv_data, priv);
+  memset (priv, 0, sizeof (*priv));
+
+  return priv;
+}
 \f
 
 /* Compare the start address for two unwind entries returning 1 if 
@@ -446,7 +364,7 @@ read_unwind_info (struct objfile *objfile)
     }
 
   /* Now compute the size of the stub unwinds.  Note the ELF tools do not
-     use stub unwinds at the curren time.  */
+     use stub unwinds at the current time.  */
   stub_unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_END$");
 
   if (stub_unwind_sec)
@@ -529,15 +447,8 @@ read_unwind_info (struct objfile *objfile)
   obj_private = (struct hppa_objfile_private *) 
                objfile_data (objfile, hppa_objfile_priv_data);
   if (obj_private == NULL)
-    {
-      obj_private = (struct hppa_objfile_private *)
-       obstack_alloc (&objfile->objfile_obstack, 
-                       sizeof (struct hppa_objfile_private));
-      set_objfile_data (objfile, hppa_objfile_priv_data, obj_private);
-      obj_private->unwind_info = NULL;
-      obj_private->so_info = NULL;
-      obj_private->dp = 0;
-    }
+    obj_private = hppa_init_objfile_priv_data (objfile);
+
   obj_private->unwind_info = ui;
 }
 
@@ -578,7 +489,7 @@ find_unwind_entry (CORE_ADDR pc)
        read_unwind_info (objfile);
         priv = objfile_data (objfile, hppa_objfile_priv_data);
        if (priv == NULL)
-         error ("Internal error reading unwind information.");
+         error (_("Internal error reading unwind information."));
         ui = ((struct hppa_objfile_private *) priv)->unwind_info;
       }
 
@@ -812,7 +723,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              param_len = 4;
              struct_ptr += align_up (TYPE_LENGTH (type), 8);
              if (write_pass)
-               write_memory (struct_end - struct_ptr, VALUE_CONTENTS (arg),
+               write_memory (struct_end - struct_ptr, value_contents (arg),
                              TYPE_LENGTH (type));
              store_unsigned_integer (param_val, 4, struct_end - struct_ptr);
            }
@@ -824,13 +735,13 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              param_len = align_up (TYPE_LENGTH (type), 4);
              store_unsigned_integer (param_val, param_len,
                                      unpack_long (type,
-                                                  VALUE_CONTENTS (arg)));
+                                                  value_contents (arg)));
            }
          else if (TYPE_CODE (type) == TYPE_CODE_FLT)
             {
              /* Floating point value store, right aligned.  */
              param_len = align_up (TYPE_LENGTH (type), 4);
-             memcpy (param_val, VALUE_CONTENTS (arg), param_len);
+             memcpy (param_val, value_contents (arg), param_len);
             }
          else
            {
@@ -838,7 +749,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
              /* Small struct value are stored right-aligned.  */
              memcpy (param_val + param_len - TYPE_LENGTH (type),
-                     VALUE_CONTENTS (arg), TYPE_LENGTH (type));
+                     value_contents (arg), TYPE_LENGTH (type));
 
              /* Structures of size 5, 6 and 7 bytes are special in that
                 the higher-ordered word is stored in the lower-ordered
@@ -912,7 +823,8 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     write_register (19, gp);
 
   /* Set the return address.  */
-  regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
+  if (!gdbarch_push_dummy_code_p (gdbarch))
+    regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
 
   /* Update the Stack Pointer.  */
   regcache_cooked_write_unsigned (regcache, HPPA_SP_REGNUM, param_end);
@@ -920,140 +832,347 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   return param_end;
 }
 
-/* This function pushes a stack frame with arguments as part of the
-   inferior function calling mechanism.
+/* The 64-bit PA-RISC calling conventions are documented in "64-Bit
+   Runtime Architecture for PA-RISC 2.0", which is distributed as part
+   as of the HP-UX Software Transition Kit (STK).  This implementation
+   is based on version 3.3, dated October 6, 1997.  */
 
-   This is the version for the PA64, in which later arguments appear
-   at higher addresses.  (The stack always grows towards higher
-   addresses.)
+/* Check whether TYPE is an "Integral or Pointer Scalar Type".  */
 
-   We simply allocate the appropriate amount of stack space and put
-   arguments into their proper slots.
+static int
+hppa64_integral_or_pointer_p (const struct type *type)
+{
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_INT:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_RANGE:
+      {
+       int len = TYPE_LENGTH (type);
+       return (len == 1 || len == 2 || len == 4 || len == 8);
+      }
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_REF:
+      return (TYPE_LENGTH (type) == 8);
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+/* Check whether TYPE is a "Floating Scalar Type".  */
+
+static int
+hppa64_floating_p (const struct type *type)
+{
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_FLT:
+      {
+       int len = TYPE_LENGTH (type);
+       return (len == 4 || len == 8 || len == 16);
+      }
+    default:
+      break;
+    }
+
+  return 0;
+}
 
-   This ABI also requires that the caller provide an argument pointer
-   to the callee, so we do that too.  */
-   
 static CORE_ADDR
 hppa64_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)
 {
-  /* NOTE: cagney/2004-02-27: This is a guess - its implemented by
-     reverse engineering testsuite failures.  */
-
-  /* Stack base address at which any pass-by-reference parameters are
-     stored.  */
-  CORE_ADDR struct_end = 0;
-  /* Stack base address at which the first parameter is stored.  */
-  CORE_ADDR param_end = 0;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int i, offset = 0;
+  CORE_ADDR gp;
 
-  /* The inner most end of the stack after all the parameters have
-     been pushed.  */
-  CORE_ADDR new_sp = 0;
+  /* "The outgoing parameter area [...] must be aligned at a 16-byte
+     boundary."  */
+  sp = align_up (sp, 16);
 
-  /* Two passes.  First pass computes the location of everything,
-     second pass writes the bytes out.  */
-  int write_pass;
-  for (write_pass = 0; write_pass < 2; write_pass++)
+  for (i = 0; i < nargs; i++)
     {
-      CORE_ADDR struct_ptr = 0;
-      CORE_ADDR param_ptr = 0;
-      int i;
-      for (i = 0; i < nargs; i++)
+      struct value *arg = args[i];
+      struct type *type = value_type (arg);
+      int len = TYPE_LENGTH (type);
+      const bfd_byte *valbuf;
+      int regnum;
+
+      /* "Each parameter begins on a 64-bit (8-byte) boundary."  */
+      offset = align_up (offset, 8);
+
+      if (hppa64_integral_or_pointer_p (type))
        {
-         struct value *arg = args[i];
-         struct type *type = check_typedef (value_type (arg));
-         if ((TYPE_CODE (type) == TYPE_CODE_INT
-              || TYPE_CODE (type) == TYPE_CODE_ENUM)
-             && TYPE_LENGTH (type) <= 8)
+         /* "Integral scalar parameters smaller than 64 bits are
+             padded on the left (i.e., the value is in the
+             least-significant bits of the 64-bit storage unit, and
+             the high-order bits are undefined)."  Therefore we can
+             safely sign-extend them.  */
+         if (len < 8)
            {
-             /* Integer value store, right aligned.  "unpack_long"
-                takes care of any sign-extension problems.  */
-             param_ptr += 8;
-             if (write_pass)
-               {
-                 ULONGEST val = unpack_long (type, VALUE_CONTENTS (arg));
-                 int reg = 27 - param_ptr / 8;
-                 write_memory_unsigned_integer (param_end - param_ptr,
-                                                val, 8);
-                 if (reg >= 19)
-                   regcache_cooked_write_unsigned (regcache, reg, val);
-               }
+             arg = value_cast (builtin_type_int64, arg);
+             len = 8;
+           }
+       }
+      else if (hppa64_floating_p (type))
+       {
+         if (len > 8)
+           {
+             /* "Quad-precision (128-bit) floating-point scalar
+                parameters are aligned on a 16-byte boundary."  */
+             offset = align_up (offset, 16);
+
+             /* "Double-extended- and quad-precision floating-point
+                 parameters within the first 64 bytes of the parameter
+                 list are always passed in general registers."  */
            }
          else
            {
-             /* Small struct value, store left aligned?  */
-             int reg;
-             if (TYPE_LENGTH (type) > 8)
-               {
-                 param_ptr = align_up (param_ptr, 16);
-                 reg = 26 - param_ptr / 8;
-                 param_ptr += align_up (TYPE_LENGTH (type), 16);
-               }
-             else
+             if (len == 4)
                {
-                 param_ptr = align_up (param_ptr, 8);
-                 reg = 26 - param_ptr / 8;
-                 param_ptr += align_up (TYPE_LENGTH (type), 8);
+                 /* "Single-precision (32-bit) floating-point scalar
+                    parameters are padded on the left with 32 bits of
+                    garbage (i.e., the floating-point value is in the
+                    least-significant 32 bits of a 64-bit storage
+                    unit)."  */
+                 offset += 4;
                }
-             if (write_pass)
+
+             /* "Single- and double-precision floating-point
+                 parameters in this area are passed according to the
+                 available formal parameter information in a function
+                 prototype.  [...]  If no prototype is in scope,
+                 floating-point parameters must be passed both in the
+                 corresponding general registers and in the
+                 corresponding floating-point registers."  */
+             regnum = HPPA64_FP4_REGNUM + offset / 8;
+
+             if (regnum < HPPA64_FP4_REGNUM + 8)
                {
-                 int byte;
-                 write_memory (param_end - param_ptr, VALUE_CONTENTS (arg),
-                               TYPE_LENGTH (type));
-                 for (byte = 0; byte < TYPE_LENGTH (type); byte += 8)
-                   {
-                     if (reg >= 19)
-                       {
-                         int len = min (8, TYPE_LENGTH (type) - byte);
-                         regcache_cooked_write_part (regcache, reg, 0, len,
-                                                     VALUE_CONTENTS (arg) + byte);
-                       }
-                     reg--;
-                   }
+                 /* "Single-precision floating-point parameters, when
+                    passed in floating-point registers, are passed in
+                    the right halves of the floating point registers;
+                    the left halves are unused."  */
+                 regcache_cooked_write_part (regcache, regnum, offset % 8,
+                                             len, value_contents (arg));
                }
            }
        }
-      /* Update the various stack pointers.  */
-      if (!write_pass)
+      else
        {
-         struct_end = sp + struct_ptr;
-         /* PARAM_PTR already accounts for all the arguments passed
-            by the user.  However, the ABI mandates minimum stack
-            space allocations for outgoing arguments.  The ABI also
-            mandates minimum stack alignments which we must
-            preserve.  */
-         param_end = struct_end + max (align_up (param_ptr, 16), 64);
+         if (len > 8)
+           {
+             /* "Aggregates larger than 8 bytes are aligned on a
+                16-byte boundary, possibly leaving an unused argument
+                slot, which is filled with garbage. If necessary,
+                they are padded on the right (with garbage), to a
+                multiple of 8 bytes."  */
+             offset = align_up (offset, 16);
+           }
+       }
+
+      /* Always store the argument in memory.  */
+      write_memory (sp + offset, value_contents (arg), len);
+
+      valbuf = value_contents (arg);
+      regnum = HPPA_ARG0_REGNUM - offset / 8;
+      while (regnum > HPPA_ARG0_REGNUM - 8 && len > 0)
+       {
+         regcache_cooked_write_part (regcache, regnum,
+                                     offset % 8, min (len, 8), valbuf);
+         offset += min (len, 8);
+         valbuf += min (len, 8);
+         len -= min (len, 8);
+         regnum--;
        }
+
+      offset += len;
     }
 
-  /* If a structure has to be returned, set up register 28 to hold its
-     address */
+  /* Set up GR29 (%ret1) to hold the argument pointer (ap).  */
+  regcache_cooked_write_unsigned (regcache, HPPA_RET1_REGNUM, sp + 64);
+
+  /* Allocate the outgoing parameter area.  Make sure the outgoing
+     parameter area is multiple of 16 bytes in length.  */
+  sp += max (align_up (offset, 16), 64);
+
+  /* Allocate 32-bytes of scratch space.  The documentation doesn't
+     mention this, but it seems to be needed.  */
+  sp += 32;
+
+  /* Allocate the frame marker area.  */
+  sp += 16;
+
+  /* If a structure has to be returned, set up GR 28 (%ret0) to hold
+     its address.  */
   if (struct_return)
-    write_register (28, struct_addr);
+    regcache_cooked_write_unsigned (regcache, HPPA_RET0_REGNUM, struct_addr);
 
-  /* Set the return address.  */
-  regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
+  /* Set up GR27 (%dp) to hold the global pointer (gp).  */
+  gp = tdep->find_global_pointer (function);
+  if (gp != 0)
+    regcache_cooked_write_unsigned (regcache, HPPA_DP_REGNUM, gp);
 
-  /* Update the Stack Pointer.  */
-  regcache_cooked_write_unsigned (regcache, HPPA_SP_REGNUM, param_end + 64);
+  /* Set up GR2 (%rp) to hold the return pointer (rp).  */
+  if (!gdbarch_push_dummy_code_p (gdbarch))
+    regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
+
+  /* Set up GR30 to hold the stack pointer (sp).  */
+  regcache_cooked_write_unsigned (regcache, HPPA_SP_REGNUM, sp);
+
+  return sp;
+}
+\f
+
+/* Handle 32/64-bit struct return conventions.  */
+
+static enum return_value_convention
+hppa32_return_value (struct gdbarch *gdbarch,
+                    struct type *type, struct regcache *regcache,
+                    gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  if (TYPE_LENGTH (type) <= 2 * 4)
+    {
+      /* The value always lives in the right hand end of the register
+        (or register pair)?  */
+      int b;
+      int reg = TYPE_CODE (type) == TYPE_CODE_FLT ? HPPA_FP4_REGNUM : 28;
+      int part = TYPE_LENGTH (type) % 4;
+      /* The left hand register contains only part of the value,
+        transfer that first so that the rest can be xfered as entire
+        4-byte registers.  */
+      if (part > 0)
+       {
+         if (readbuf != NULL)
+           regcache_cooked_read_part (regcache, reg, 4 - part,
+                                      part, readbuf);
+         if (writebuf != NULL)
+           regcache_cooked_write_part (regcache, reg, 4 - part,
+                                       part, writebuf);
+         reg++;
+       }
+      /* Now transfer the remaining register values.  */
+      for (b = part; b < TYPE_LENGTH (type); b += 4)
+       {
+         if (readbuf != NULL)
+           regcache_cooked_read (regcache, reg, readbuf + b);
+         if (writebuf != NULL)
+           regcache_cooked_write (regcache, reg, writebuf + b);
+         reg++;
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else
+    return RETURN_VALUE_STRUCT_CONVENTION;
+}
+
+static enum return_value_convention
+hppa64_return_value (struct gdbarch *gdbarch,
+                    struct type *type, struct regcache *regcache,
+                    gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  int len = TYPE_LENGTH (type);
+  int regnum, offset;
+
+  if (len > 16)
+    {
+      /* All return values larget than 128 bits must be aggregate
+         return values.  */
+      gdb_assert (!hppa64_integral_or_pointer_p (type));
+      gdb_assert (!hppa64_floating_p (type));
+
+      /* "Aggregate return values larger than 128 bits are returned in
+        a buffer allocated by the caller.  The address of the buffer
+        must be passed in GR 28."  */
+      return RETURN_VALUE_STRUCT_CONVENTION;
+    }
+
+  if (hppa64_integral_or_pointer_p (type))
+    {
+      /* "Integral return values are returned in GR 28.  Values
+         smaller than 64 bits are padded on the left (with garbage)."  */
+      regnum = HPPA_RET0_REGNUM;
+      offset = 8 - len;
+    }
+  else if (hppa64_floating_p (type))
+    {
+      if (len > 8)
+       {
+         /* "Double-extended- and quad-precision floating-point
+            values are returned in GRs 28 and 29.  The sign,
+            exponent, and most-significant bits of the mantissa are
+            returned in GR 28; the least-significant bits of the
+            mantissa are passed in GR 29.  For double-extended
+            precision values, GR 29 is padded on the right with 48
+            bits of garbage."  */
+         regnum = HPPA_RET0_REGNUM;
+         offset = 0;
+       }
+      else
+       {
+         /* "Single-precision and double-precision floating-point
+            return values are returned in FR 4R (single precision) or
+            FR 4 (double-precision)."  */
+         regnum = HPPA64_FP4_REGNUM;
+         offset = 8 - len;
+       }
+    }
+  else
+    {
+      /* "Aggregate return values up to 64 bits in size are returned
+         in GR 28.  Aggregates smaller than 64 bits are left aligned
+         in the register; the pad bits on the right are undefined."
+
+        "Aggregate return values between 65 and 128 bits are returned
+        in GRs 28 and 29.  The first 64 bits are placed in GR 28, and
+        the remaining bits are placed, left aligned, in GR 29.  The
+        pad bits on the right of GR 29 (if any) are undefined."  */
+      regnum = HPPA_RET0_REGNUM;
+      offset = 0;
+    }
+
+  if (readbuf)
+    {
+      while (len > 0)
+       {
+         regcache_cooked_read_part (regcache, regnum, offset,
+                                    min (len, 8), readbuf);
+         readbuf += min (len, 8);
+         len -= min (len, 8);
+         regnum++;
+       }
+    }
+
+  if (writebuf)
+    {
+      while (len > 0)
+       {
+         regcache_cooked_write_part (regcache, regnum, offset,
+                                     min (len, 8), writebuf);
+         writebuf += min (len, 8);
+         len -= min (len, 8);
+         regnum++;
+       }
+    }
 
-  /* The stack will have 32 bytes of additional space for a frame marker.  */
-  return param_end + 64;
+  return RETURN_VALUE_REGISTER_CONVENTION;
 }
+\f
 
 static CORE_ADDR
-hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
-                                  CORE_ADDR addr,
+hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
                                   struct target_ops *targ)
 {
   if (addr & 2)
     {
-      CORE_ADDR plabel;
-
-      plabel = addr & ~3;
-      target_read_memory(plabel, (char *)&addr, 4);
+      CORE_ADDR plabel = addr & ~3;
+      return read_memory_typed_address (plabel, builtin_type_void_func_ptr);
     }
 
   return addr;
@@ -1161,9 +1280,9 @@ prologue_inst_adjust_sp (unsigned long inst)
   if ((inst & 0xffe00008) == 0x73c00008)
     return (inst & 0x1 ? -1 << 13 : 0) | (((inst >> 4) & 0x3ff) << 3);
 
-  /* addil high21,%r1; ldo low11,(%r1),%r30)
+  /* addil high21,%r30; ldo low11,(%r1),%r30)
      save high bits in save_high21 for later use.  */
-  if ((inst & 0xffe00000) == 0x28200000)
+  if ((inst & 0xffe00000) == 0x2bc00000)
     {
       save_high21 = hppa_extract_21 (inst);
       return 0;
@@ -1706,7 +1825,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
        if (!safe_frame_unwind_memory (next_frame, pc, buf4, 
                                       sizeof buf4)) 
          {
-           error ("Cannot read instruction at 0x%s\n", paddr_nz (pc));
+           error (_("Cannot read instruction at 0x%s."), paddr_nz (pc));
            return (*this_cache);
          }
 
@@ -1985,7 +2104,7 @@ hppa_frame_prev_register (struct frame_info *next_frame,
                          void **this_cache,
                          int regnum, int *optimizedp,
                          enum lval_type *lvalp, CORE_ADDR *addrp,
-                         int *realnump, void *valuep)
+                         int *realnump, gdb_byte *valuep)
 {
   struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache);
   hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
@@ -2022,72 +2141,65 @@ static struct hppa_frame_cache *
 hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
   struct hppa_frame_cache *cache;
-  unsigned int frame_size;
-  int found_rp;
-  CORE_ADDR pc, start_pc, end_pc, cur_pc;
+  unsigned int frame_size = 0;
+  int found_rp = 0;
+  CORE_ADDR start_pc;
 
   if (hppa_debug)
-    fprintf_unfiltered (gdb_stdlog, "{ hppa_fallback_frame_cache (frame=%d)-> ",
-      frame_relative_level(next_frame));
+    fprintf_unfiltered (gdb_stdlog,
+                       "{ hppa_fallback_frame_cache (frame=%d) -> ",
+                       frame_relative_level (next_frame));
 
   cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
   (*this_cache) = cache;
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
 
-  pc = frame_func_unwind (next_frame);
-  cur_pc = frame_pc_unwind (next_frame);
-  frame_size = 0;
-  found_rp = 0;
-
-  find_pc_partial_function (pc, NULL, &start_pc, &end_pc);
-
-  if (start_pc == 0 || end_pc == 0)
+  start_pc = frame_func_unwind (next_frame);
+  if (start_pc)
     {
-      error ("Cannot find bounds of current function (@0x%s), unwinding will "
-            "fail.", paddr_nz (pc));
-      return cache;
-    }
-
-  if (end_pc > cur_pc)
-    end_pc = cur_pc;
+      CORE_ADDR cur_pc = frame_pc_unwind (next_frame);
+      CORE_ADDR pc;
 
-  for (pc = start_pc; pc < end_pc; pc += 4)
-    {
-      unsigned int insn;
-
-      insn = read_memory_unsigned_integer (pc, 4);
+      for (pc = start_pc; pc < cur_pc; pc += 4)
+       {
+         unsigned int insn;
 
-      frame_size += prologue_inst_adjust_sp (insn);
+         insn = read_memory_unsigned_integer (pc, 4);
+         frame_size += prologue_inst_adjust_sp (insn);
 
-      /* There are limited ways to store the return pointer into the
-        stack.  */
-      if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
-        {
-          cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
-          found_rp = 1;
-        }
-      else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
-        {
-          cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
-          found_rp = 1;
-        }
+         /* There are limited ways to store the return pointer into the
+            stack.  */
+         if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
+           {
+             cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
+             found_rp = 1;
+           }
+         else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
+           {
+             cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
+             found_rp = 1;
+           }
+       }
     }
 
   if (hppa_debug)
-    fprintf_unfiltered (gdb_stdlog, " frame_size = %d, found_rp = %d }\n",
-      frame_size, found_rp);
+    fprintf_unfiltered (gdb_stdlog, " frame_size=%d, found_rp=%d }\n",
+                       frame_size, found_rp);
 
-  cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM) - frame_size;
+  cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+  cache->base -= frame_size;
   trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
 
   if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
     {
       cache->saved_regs[HPPA_RP_REGNUM].addr += cache->base;
-      cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM];
+      cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = 
+       cache->saved_regs[HPPA_RP_REGNUM];
     }
   else
     {
-      ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM);
+      ULONGEST rp;
+      rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM);
       trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp);
     }
 
@@ -2108,7 +2220,7 @@ hppa_fallback_frame_prev_register (struct frame_info *next_frame,
                          void **this_cache,
                          int regnum, int *optimizedp,
                          enum lval_type *lvalp, CORE_ADDR *addrp,
-                         int *realnump, void *valuep)
+                         int *realnump, gdb_byte *valuep)
 {
   struct hppa_frame_cache *info = 
     hppa_fallback_frame_cache (next_frame, this_cache);
@@ -2193,7 +2305,7 @@ hppa_stub_frame_prev_register (struct frame_info *next_frame,
                               void **this_prologue_cache,
                               int regnum, int *optimizedp,
                               enum lval_type *lvalp, CORE_ADDR *addrp,
-                              int *realnump, void *valuep)
+                              int *realnump, gdb_byte *valuep)
 {
   struct hppa_stub_unwind_cache *info
     = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache);
@@ -2203,7 +2315,7 @@ hppa_stub_frame_prev_register (struct frame_info *next_frame,
                                     optimizedp, lvalp, addrp, realnump, 
                                     valuep);
   else
-    error ("Requesting registers from null frame.\n");
+    error (_("Requesting registers from null frame."));
 }
 
 static const struct frame_unwind hppa_stub_frame_unwind = {
@@ -2280,16 +2392,6 @@ hppa_lookup_stub_minimal_symbol (const char *name,
   return NULL;
 }
 
-/* Instead of this nasty cast, add a method pvoid() that prints out a
-   host VOID data type (remember %p isn't portable).  */
-
-static CORE_ADDR
-hppa_pointer_to_address_hack (void *ptr)
-{
-  gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr));
-  return POINTER_TO_ADDRESS (builtin_type_void_data_ptr, &ptr);
-}
-
 static void
 unwind_command (char *exp, int from_tty)
 {
@@ -2311,8 +2413,7 @@ unwind_command (char *exp, int from_tty)
       return;
     }
 
-  printf_unfiltered ("unwind_table_entry (0x%s):\n",
-                    paddr_nz (hppa_pointer_to_address_hack (u)));
+  printf_unfiltered ("unwind_table_entry (0x%lx):\n", (unsigned long)u);
 
   printf_unfiltered ("\tregion_start = ");
   print_address (u->region_start, gdb_stdout);
@@ -2405,44 +2506,49 @@ hppa_pc_requires_run_before_use (CORE_ADDR pc)
      minimal symbols, I'm resorting to the gross hack of checking the
      top byte of the address for all 1's.  Sigh.  */
 
-  return (!target_has_stack && (pc & 0xFF000000));
+  return (!target_has_stack && (pc & 0xFF000000) == 0xFF000000);
 }
 
-/* Return the GDB type object for the "standard" data type of data
-   in register N.  */
+/* Return the GDB type object for the "standard" data type of data in
+   register REGNUM.  */
 
 static struct type *
-hppa32_register_type (struct gdbarch *gdbarch, int reg_nr)
+hppa32_register_type (struct gdbarch *gdbarch, int regnum)
 {
-   if (reg_nr < HPPA_FP4_REGNUM)
+   if (regnum < HPPA_FP4_REGNUM)
      return builtin_type_uint32;
    else
      return builtin_type_ieee_single_big;
 }
 
-/* Return the GDB type object for the "standard" data type of data
-   in register N.  hppa64 version.  */
-
 static struct type *
-hppa64_register_type (struct gdbarch *gdbarch, int reg_nr)
+hppa64_register_type (struct gdbarch *gdbarch, int regnum)
 {
-   if (reg_nr < HPPA_FP4_REGNUM)
+   if (regnum < HPPA64_FP4_REGNUM)
      return builtin_type_uint64;
    else
      return builtin_type_ieee_double_big;
 }
 
-/* Return True if REGNUM is not a register available to the user
-   through ptrace().  */
+/* Return non-zero if REGNUM is not a register available to the user
+   through ptrace/ttrace.  */
 
 static int
-hppa_cannot_store_register (int regnum)
+hppa32_cannot_store_register (int regnum)
 {
   return (regnum == 0
           || regnum == HPPA_PCSQ_HEAD_REGNUM
           || (regnum >= HPPA_PCSQ_TAIL_REGNUM && regnum < HPPA_IPSW_REGNUM)
           || (regnum > HPPA_IPSW_REGNUM && regnum < HPPA_FP4_REGNUM));
+}
 
+static int
+hppa64_cannot_store_register (int regnum)
+{
+  return (regnum == 0
+          || regnum == HPPA_PCSQ_HEAD_REGNUM
+          || (regnum >= HPPA_PCSQ_TAIL_REGNUM && regnum < HPPA_IPSW_REGNUM)
+          || (regnum > HPPA_IPSW_REGNUM && regnum < HPPA64_FP4_REGNUM));
 }
 
 static CORE_ADDR
@@ -2458,26 +2564,25 @@ hppa_smash_text_address (CORE_ADDR addr)
   return (addr &= ~0x3);
 }
 
-/* Get the ith function argument for the current function.  */
+/* Get the ARGIth function argument for the current function.  */
+
 static CORE_ADDR
 hppa_fetch_pointer_argument (struct frame_info *frame, int argi, 
                             struct type *type)
 {
-  CORE_ADDR addr;
-  get_frame_register (frame, HPPA_R0_REGNUM + 26 - argi, &addr);
-  return addr;
+  return get_frame_register_unsigned (frame, HPPA_R0_REGNUM + 26 - argi);
 }
 
 static void
 hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-                          int regnum, void *buf)
+                          int regnum, gdb_byte *buf)
 {
     ULONGEST tmp;
 
     regcache_raw_read_unsigned (regcache, regnum, &tmp);
     if (regnum == HPPA_PCOQ_HEAD_REGNUM || regnum == HPPA_PCOQ_TAIL_REGNUM)
       tmp &= ~0x3;
-    store_unsigned_integer (buf, sizeof(tmp), tmp);
+    store_unsigned_integer (buf, sizeof tmp, tmp);
 }
 
 static CORE_ADDR
@@ -2491,20 +2596,23 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame,
                                 struct trad_frame_saved_reg saved_regs[],
                                 int regnum, int *optimizedp,
                                 enum lval_type *lvalp, CORE_ADDR *addrp,
-                                int *realnump, void *valuep)
+                                int *realnump, gdb_byte *valuep)
 {
+  struct gdbarch *arch = get_frame_arch (next_frame);
+
   if (regnum == HPPA_PCOQ_TAIL_REGNUM)
     {
       if (valuep)
        {
+         int size = register_size (arch, HPPA_PCOQ_HEAD_REGNUM);
          CORE_ADDR pc;
 
          trad_frame_get_prev_register (next_frame, saved_regs,
                                        HPPA_PCOQ_HEAD_REGNUM, optimizedp,
                                        lvalp, addrp, realnump, valuep);
 
-         pc = extract_unsigned_integer (valuep, 4);
-         store_unsigned_integer (valuep, 4, pc + 4);
+         pc = extract_unsigned_integer (valuep, size);
+         store_unsigned_integer (valuep, size, pc + 4);
        }
 
       /* It's a computed value.  */
@@ -2523,10 +2631,7 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame,
   if (regnum == HPPA_FLAGS_REGNUM)
     {
       if (valuep)
-       store_unsigned_integer (valuep, 
-                               register_size (get_frame_arch (next_frame), 
-                                              regnum), 
-                               0);
+       store_unsigned_integer (valuep, register_size (arch, regnum), 0);
 
       /* It's a computed value.  */
       *optimizedp = 0;
@@ -2618,14 +2723,22 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
         set_gdbarch_num_regs (gdbarch, hppa32_num_regs);
         set_gdbarch_register_name (gdbarch, hppa32_register_name);
         set_gdbarch_register_type (gdbarch, hppa32_register_type);
+       set_gdbarch_cannot_store_register (gdbarch,
+                                          hppa32_cannot_store_register);
+       set_gdbarch_cannot_fetch_register (gdbarch,
+                                          hppa32_cannot_store_register);
         break;
       case 8:
         set_gdbarch_num_regs (gdbarch, hppa64_num_regs);
         set_gdbarch_register_name (gdbarch, hppa64_register_name);
         set_gdbarch_register_type (gdbarch, hppa64_register_type);
+       set_gdbarch_cannot_store_register (gdbarch,
+                                          hppa64_cannot_store_register);
+       set_gdbarch_cannot_fetch_register (gdbarch,
+                                          hppa64_cannot_store_register);
         break;
       default:
-        internal_error (__FILE__, __LINE__, "Unsupported address size: %d",
+        internal_error (__FILE__, __LINE__, _("Unsupported address size: %d"),
                         tdep->bytes_per_address);
     }
 
@@ -2646,8 +2759,6 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_inner_than (gdbarch, core_addr_greaterthan);
   set_gdbarch_sp_regnum (gdbarch, HPPA_SP_REGNUM);
   set_gdbarch_fp0_regnum (gdbarch, HPPA_FP0_REGNUM);
-  set_gdbarch_cannot_store_register (gdbarch, hppa_cannot_store_register);
-  set_gdbarch_cannot_fetch_register (gdbarch, hppa_cannot_store_register);
   set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address);
   set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address);
   set_gdbarch_believe_pcc_promotion (gdbarch, 1);
@@ -2679,7 +2790,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_frame_align (gdbarch, hppa64_frame_align);
       break;
     default:
-      internal_error (__FILE__, __LINE__, "bad switch");
+      internal_error (__FILE__, __LINE__, _("bad switch"));
     }
       
   /* Struct return methods.  */
@@ -2692,7 +2803,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_return_value (gdbarch, hppa64_return_value);
       break;
     default:
-      internal_error (__FILE__, __LINE__, "bad switch");
+      internal_error (__FILE__, __LINE__, _("bad switch"));
     }
       
   set_gdbarch_breakpoint_from_pc (gdbarch, hppa_breakpoint_from_pc);
@@ -2733,15 +2844,18 @@ _initialize_hppa_tdep (void)
   hppa_objfile_priv_data = register_objfile_data ();
 
   add_cmd ("unwind", class_maintenance, unwind_command,
-          "Print unwind table entry at given address.",
+          _("Print unwind table entry at given address."),
           &maintenanceprintlist);
 
   /* Debug this files internals. */
-  add_setshow_boolean_cmd ("hppa", class_maintenance, &hppa_debug, "\
-Set whether hppa target specific debugging information should be displayed.", "\
-Show whether hppa target specific debugging information is displayed.", "\
+  add_setshow_boolean_cmd ("hppa", class_maintenance, &hppa_debug, _("\
+Set whether hppa target specific debugging information should be displayed."),
+                          _("\
+Show whether hppa target specific debugging information is displayed."), _("\
 This flag controls whether hppa target specific debugging information is\n\
 displayed.  This information is particularly useful for debugging frame\n\
-unwinding problems.", "hppa debug flag is %s.",
-                          NULL, NULL, &setdebuglist, &showdebuglist);
+unwinding problems."),
+                          NULL,
+                          NULL, /* FIXME: i18n: hppa debug flag is %s.  */
+                          &setdebuglist, &showdebuglist);
 }
This page took 0.040818 seconds and 4 git commands to generate.