gdb/
[deliverable/binutils-gdb.git] / gdb / ppc-sysv-tdep.c
index c2952f5c8b8b4a57865c32ca7c3dc747b2bd09eb..b3a7ec361fc5ee5be4c61951899df5c781b9ec3a 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for PowerPC systems using the SVR4 ABI
    for GDB, the GNU debugger.
 
-   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2007, 2008
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    This file is part of GDB.
@@ -49,6 +49,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                              int struct_return, CORE_ADDR struct_addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   ULONGEST saved_sp;
   int argspace = 0;            /* 0 is an initial wrong guess.  */
   int write_pass;
@@ -129,17 +130,21 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                }
              else
                {
-                 /* SysV ABI converts floats to doubles before
-                    writing them to an 8 byte aligned stack location.  */
-                 argoffset = align_up (argoffset, 8);
+                 /* The SysV ABI tells us to convert floats to
+                    doubles before writing them to an 8 byte aligned
+                    stack location.  Unfortunately GCC does not do
+                    that, and stores floats into 4 byte aligned
+                    locations without converting them to doubles.
+                    Since there is no know compiler that actually
+                    follows the ABI here, we implement the GCC
+                    convention.  */
+
+                 /* Align to 4 bytes or 8 bytes depending on the type of
+                    the argument (float or double).  */
+                 argoffset = align_up (argoffset, len);
                  if (write_pass)
-                   {
-                     char memval[8];
-                     convert_typed_floating (val, type, memval,
-                                             builtin_type_ieee_double);
                      write_memory (sp + argoffset, val, len);
-                   }
-                 argoffset += 8;
+                 argoffset += len;
                }
            }
          else if (TYPE_CODE (type) == TYPE_CODE_FLT
@@ -173,13 +178,16 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            }
          else if (len == 8
                   && (TYPE_CODE (type) == TYPE_CODE_INT        /* long long */
-                      || TYPE_CODE (type) == TYPE_CODE_FLT))   /* double */
+                      || TYPE_CODE (type) == TYPE_CODE_FLT     /* double */
+                      || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
+                          && tdep->soft_float)))
            {
-             /* "long long" or soft-float "double" passed in an odd/even
-                register pair with the low addressed word in the odd
-                register and the high addressed word in the even
-                register, or when the registers run out an 8 byte
-                aligned stack location.  */
+             /* "long long" or soft-float "double" or "_Decimal64"
+                passed in an odd/even register pair with the low
+                addressed word in the odd register and the high
+                addressed word in the even register, or when the
+                registers run out an 8 byte aligned stack
+                location.  */
              if (greg > 9)
                {
                  /* Just in case GREG was 10.  */
@@ -206,13 +214,16 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  greg += 2;
                }
            }
-         else if (len == 16 && TYPE_CODE (type) == TYPE_CODE_FLT
-                  && (gdbarch_long_double_format (gdbarch)
-                      == floatformats_ibm_long_double))
+         else if (len == 16
+                  && ((TYPE_CODE (type) == TYPE_CODE_FLT
+                       && (gdbarch_long_double_format (gdbarch)
+                           == floatformats_ibm_long_double))
+                      || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
+                          && tdep->soft_float)))
            {
-             /* Soft-float IBM long double passed in four consecutive
-                registers, or on the stack.  The registers are not
-                necessarily odd/even pairs.  */
+             /* Soft-float IBM long double or _Decimal128 passed in
+                four consecutive registers, or on the stack.  The
+                registers are not necessarily odd/even pairs.  */
              if (greg > 7)
                {
                  greg = 11;
@@ -241,6 +252,81 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  greg += 4;
                }
            }
+         else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len <= 8
+                  && !tdep->soft_float)
+           {
+             /* 32-bit and 64-bit decimal floats go in f1 .. f8.  They can
+                end up in memory.  */
+
+             if (freg <= 8)
+               {
+                 if (write_pass)
+                   {
+                     gdb_byte regval[MAX_REGISTER_SIZE];
+                     const gdb_byte *p;
+
+                     /* 32-bit decimal floats are right aligned in the
+                        doubleword.  */
+                     if (TYPE_LENGTH (type) == 4)
+                     {
+                       memcpy (regval + 4, val, 4);
+                       p = regval;
+                     }
+                     else
+                       p = val;
+
+                     regcache_cooked_write (regcache,
+                         tdep->ppc_fp0_regnum + freg, p);
+                   }
+
+                 freg++;
+               }
+             else
+               {
+                 argoffset = align_up (argoffset, len);
+
+                 if (write_pass)
+                   /* Write value in the stack's parameter save area.  */
+                   write_memory (sp + argoffset, val, len);
+
+                 argoffset += len;
+               }
+           }
+         else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len == 16
+                  && !tdep->soft_float)
+           {
+             /* 128-bit decimal floats go in f2 .. f7, always in even/odd
+                pairs.  They can end up in memory, using two doublewords.  */
+
+             if (freg <= 6)
+               {
+                 /* Make sure freg is even.  */
+                 freg += freg & 1;
+
+                 if (write_pass)
+                   {
+                     regcache_cooked_write (regcache,
+                                            tdep->ppc_fp0_regnum + freg, val);
+                     regcache_cooked_write (regcache,
+                         tdep->ppc_fp0_regnum + freg + 1, val + 8);
+                   }
+               }
+             else
+               {
+                 argoffset = align_up (argoffset, 8);
+
+                 if (write_pass)
+                   write_memory (sp + argoffset, val, 16);
+
+                 argoffset += 16;
+               }
+
+             /* If a 128-bit decimal float goes to the stack because only f7
+                and f8 are free (thus there's no even/odd register pair
+                available), these registers should be marked as occupied.
+                Hence we increase freg even when writing to memory.  */
+             freg += 2;
+           }
          else if (len == 16
                   && TYPE_CODE (type) == TYPE_CODE_ARRAY
                   && TYPE_VECTOR (type)
@@ -313,13 +399,13 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                    write_memory (sp + structoffset, val, len);
                  /* ... and then a "word" pointing to that address is
                     passed as the parameter.  */
-                 store_unsigned_integer (word, tdep->wordsize,
+                 store_unsigned_integer (word, tdep->wordsize, byte_order,
                                          sp + structoffset);
                  structoffset += len;
                }
              else if (TYPE_CODE (type) == TYPE_CODE_INT)
                /* Sign or zero extend the "int" into a "word".  */
-               store_unsigned_integer (word, tdep->wordsize,
+               store_unsigned_integer (word, tdep->wordsize, byte_order,
                                        unpack_long (type, val));
              else
                /* Always goes in the low address.  */
@@ -377,7 +463,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   regcache_cooked_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
 
   /* Write the backchain (it occupies WORDSIZED bytes).  */
-  write_memory_signed_integer (sp, tdep->wordsize, saved_sp);
+  write_memory_signed_integer (sp, tdep->wordsize, byte_order, saved_sp);
 
   /* Point the inferior function call's return address at the dummy's
      breakpoint.  */
@@ -386,6 +472,70 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   return sp;
 }
 
+/* Handle the return-value conventions for Decimal Floating Point values
+   in both ppc32 and ppc64, which are the same.  */
+static int
+get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
+                               struct regcache *regcache, gdb_byte *readbuf,
+                               const gdb_byte *writebuf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  gdb_assert (TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT);
+
+  /* 32-bit and 64-bit decimal floats in f1.  */
+  if (TYPE_LENGTH (valtype) <= 8)
+    {
+      if (writebuf != NULL)
+       {
+         gdb_byte regval[MAX_REGISTER_SIZE];
+         const gdb_byte *p;
+
+         /* 32-bit decimal float is right aligned in the doubleword.  */
+         if (TYPE_LENGTH (valtype) == 4)
+           {
+             memcpy (regval + 4, writebuf, 4);
+             p = regval;
+           }
+         else
+           p = writebuf;
+
+         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, p);
+       }
+      if (readbuf != NULL)
+       {
+         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf);
+
+         /* Left align 32-bit decimal float.  */
+         if (TYPE_LENGTH (valtype) == 4)
+           memcpy (readbuf, readbuf + 4, 4);
+       }
+    }
+  /* 128-bit decimal floats in f2,f3.  */
+  else if (TYPE_LENGTH (valtype) == 16)
+    {
+      if (writebuf != NULL || readbuf != NULL)
+       {
+         int i;
+
+         for (i = 0; i < 2; i++)
+           {
+             if (writebuf != NULL)
+               regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2 + i,
+                                      writebuf + i * 8);
+             if (readbuf != NULL)
+               regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 2 + i,
+                                     readbuf + i * 8);
+           }
+       }
+    }
+  else
+    /* Can't happen.  */
+    internal_error (__FILE__, __LINE__, "Unknown decimal float size.");
+
+  return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
 /* Handle the return-value conventions specified by the SysV 32-bit
    PowerPC ABI (including all the supplements):
 
@@ -407,6 +557,7 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
                          const gdb_byte *writebuf, int broken_gcc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_assert (tdep->wordsize == 4);
   if (TYPE_CODE (type) == TYPE_CODE_FLT
       && TYPE_LENGTH (type) <= 8
@@ -453,11 +604,13 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
-  if (TYPE_CODE (type) == TYPE_CODE_FLT
-      && TYPE_LENGTH (type) == 16
-      && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double))
+  if (TYPE_LENGTH (type) == 16
+      && ((TYPE_CODE (type) == TYPE_CODE_FLT
+          && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double))
+         || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && tdep->soft_float)))
     {
-      /* Soft-float IBM long double stored in r3, r4, r5, r6.  */
+      /* Soft-float IBM long double or _Decimal128 stored in r3, r4,
+        r5, r6.  */
       if (readbuf)
        {
          regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf);
@@ -481,11 +634,14 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
   if ((TYPE_CODE (type) == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
-      || (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
+      || (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
+      || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && TYPE_LENGTH (type) == 8
+         && tdep->soft_float))
     {
       if (readbuf)
        {
-         /* A long long, or a double stored in the 32 bit r3/r4.  */
+         /* A long long, double or _Decimal64 stored in the 32 bit
+            r3/r4.  */
          regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
                                readbuf + 0);
          regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
@@ -493,7 +649,8 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
        }
       if (writebuf)
        {
-         /* A long long, or a double stored in the 32 bit r3/r4.  */
+         /* A long long, double or _Decimal64 stored in the 32 bit
+            r3/r4.  */
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
                                 writebuf + 0);
          regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
@@ -501,6 +658,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
+  if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && !tdep->soft_float)
+    return get_decimal_float_return_value (gdbarch, type, regcache, readbuf,
+                                          writebuf);
   else if ((TYPE_CODE (type) == TYPE_CODE_INT
            || TYPE_CODE (type) == TYPE_CODE_CHAR
            || TYPE_CODE (type) == TYPE_CODE_BOOL
@@ -517,7 +677,8 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
          ULONGEST regval;
          regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
                                         &regval);
-         store_unsigned_integer (readbuf, TYPE_LENGTH (type), regval);
+         store_unsigned_integer (readbuf, TYPE_LENGTH (type), byte_order,
+                                 regval);
        }
       if (writebuf)
        {
@@ -659,9 +820,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
 }
 
 enum return_value_convention
-ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
-                          struct regcache *regcache, gdb_byte *readbuf,
-                          const gdb_byte *writebuf)
+ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                          struct type *valtype, struct regcache *regcache,
+                          gdb_byte *readbuf, const gdb_byte *writebuf)
 {
   return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf,
                                   writebuf, 0);
@@ -669,6 +830,7 @@ ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
 
 enum return_value_convention
 ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
+                                 struct type *func_type,
                                  struct type *valtype,
                                  struct regcache *regcache,
                                  gdb_byte *readbuf, const gdb_byte *writebuf)
@@ -733,6 +895,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 {
   CORE_ADDR func_addr = find_function_addr (function, NULL);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   ULONGEST back_chain;
   /* See for-loop comment below.  */
   int write_pass;
@@ -792,7 +955,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
        {
          /* During the first pass, GPARAM and VPARAM are more like
             offsets (start address zero) than addresses.  That way
-            the accumulate the total stack space each region
+            they accumulate the total stack space each region
             requires.  */
          gparam = 0;
          vparam = 0;
@@ -829,6 +992,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          struct value *arg = args[argno];
          struct type *type = check_typedef (value_type (arg));
          const bfd_byte *val = value_contents (arg);
+
          if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8)
            {
              /* Floats and Doubles go in f1 .. f13.  They also
@@ -836,40 +1000,53 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 memory.  */
              if (write_pass)
                {
+                 gdb_byte regval[MAX_REGISTER_SIZE];
+                 const gdb_byte *p;
+
+                 /* Version 1.7 of the 64-bit PowerPC ELF ABI says:
+
+                    "Single precision floating point values are mapped to
+                    the first word in a single doubleword."
+
+                    And version 1.9 says:
+
+                    "Single precision floating point values are mapped to
+                    the second word in a single doubleword."
+
+                    GDB then writes single precision floating point values
+                    at both words in a doubleword, to support both ABIs.  */
+                 if (TYPE_LENGTH (type) == 4)
+                   {
+                     memcpy (regval, val, 4);
+                     memcpy (regval + 4, val, 4);
+                     p = regval;
+                   }
+                 else
+                   p = val;
+
+                 /* Write value in the stack's parameter save area.  */
+                 write_memory (gparam, p, 8);
+
                  if (freg <= 13)
                    {
-                     gdb_byte regval[MAX_REGISTER_SIZE];
                      struct type *regtype
                         = register_type (gdbarch, tdep->ppc_fp0_regnum);
+
                      convert_typed_floating (val, type, regval, regtype);
                      regcache_cooked_write (regcache,
                                              tdep->ppc_fp0_regnum + freg,
                                             regval);
                    }
                  if (greg <= 10)
-                   {
-                     /* The ABI states "Single precision floating
-                        point values are mapped to the first word in
-                        a single doubleword" and "... floating point
-                        values mapped to the first eight doublewords
-                        of the parameter save area are also passed in
-                        general registers").
-
-                        This code interprets that to mean: store it,
-                        left aligned, in the general register.  */
-                     gdb_byte regval[MAX_REGISTER_SIZE];
-                     memset (regval, 0, sizeof regval);
-                     memcpy (regval, val, TYPE_LENGTH (type));
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_gp0_regnum + greg,
-                                            regval);
-                   }
-                 write_memory (gparam, val, TYPE_LENGTH (type));
+                   regcache_cooked_write (regcache,
+                                          tdep->ppc_gp0_regnum + greg,
+                                          regval);
                }
-             /* Always consume parameter stack space.  */
+
              freg++;
              greg++;
-             gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
+             /* Always consume parameter stack space.  */
+             gparam = align_up (gparam + 8, tdep->wordsize);
            }
          else if (TYPE_CODE (type) == TYPE_CODE_FLT
                   && TYPE_LENGTH (type) == 16
@@ -906,6 +1083,63 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              greg += 2;
              gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
            }
+         else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
+                  && TYPE_LENGTH (type) <= 8)
+           {
+             /* 32-bit and 64-bit decimal floats go in f1 .. f13.  They can
+                end up in memory.  */
+             if (write_pass)
+               {
+                 gdb_byte regval[MAX_REGISTER_SIZE];
+                 const gdb_byte *p;
+
+                 /* 32-bit decimal floats are right aligned in the
+                    doubleword.  */
+                 if (TYPE_LENGTH (type) == 4)
+                   {
+                     memcpy (regval + 4, val, 4);
+                     p = regval;
+                   }
+                 else
+                   p = val;
+
+                 /* Write value in the stack's parameter save area.  */
+                 write_memory (gparam, p, 8);
+
+                 if (freg <= 13)
+                   regcache_cooked_write (regcache,
+                                          tdep->ppc_fp0_regnum + freg, p);
+               }
+
+             freg++;
+             greg++;
+             /* Always consume parameter stack space.  */
+             gparam = align_up (gparam + 8, tdep->wordsize);
+           }
+         else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT &&
+                  TYPE_LENGTH (type) == 16)
+           {
+             /* 128-bit decimal floats go in f2 .. f12, always in even/odd
+                pairs.  They can end up in memory, using two doublewords.  */
+             if (write_pass)
+               {
+                 if (freg <= 12)
+                   {
+                     /* Make sure freg is even.  */
+                     freg += freg & 1;
+                     regcache_cooked_write (regcache,
+                                             tdep->ppc_fp0_regnum + freg, val);
+                     regcache_cooked_write (regcache,
+                         tdep->ppc_fp0_regnum + freg + 1, val + 8);
+                   }
+
+                 write_memory (gparam, val, TYPE_LENGTH (type));
+               }
+
+             freg += 2;
+             greg += 2;
+             gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
+           }
          else if (TYPE_LENGTH (type) == 16 && TYPE_VECTOR (type)
                   && TYPE_CODE (type) == TYPE_CODE_ARRAY
                   && tdep->ppc_vr0_regnum >= 0)
@@ -931,7 +1165,10 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            }
          else if ((TYPE_CODE (type) == TYPE_CODE_INT
                    || TYPE_CODE (type) == TYPE_CODE_ENUM
-                   || TYPE_CODE (type) == TYPE_CODE_PTR)
+                   || TYPE_CODE (type) == TYPE_CODE_BOOL
+                   || TYPE_CODE (type) == TYPE_CODE_CHAR
+                   || TYPE_CODE (type) == TYPE_CODE_PTR
+                   || TYPE_CODE (type) == TYPE_CODE_REF)
                   && TYPE_LENGTH (type) <= 8)
            {
              /* Scalars and Pointers get sign[un]extended and go in
@@ -943,18 +1180,25 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  /* Convert any function code addresses into
                     descriptors.  */
                  if (TYPE_CODE (type) == TYPE_CODE_PTR
-                     && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)
+                     || TYPE_CODE (type) == TYPE_CODE_REF)
                    {
-                     CORE_ADDR desc = word;
-                     convert_code_addr_to_desc_addr (word, &desc);
-                     word = desc;
+                     struct type *target_type;
+                     target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+                     if (TYPE_CODE (target_type) == TYPE_CODE_FUNC
+                         || TYPE_CODE (target_type) == TYPE_CODE_METHOD)
+                       {
+                         CORE_ADDR desc = word;
+                         convert_code_addr_to_desc_addr (word, &desc);
+                         word = desc;
+                       }
                    }
                  if (greg <= 10)
                    regcache_cooked_write_unsigned (regcache,
                                                    tdep->ppc_gp0_regnum +
                                                    greg, word);
                  write_memory_unsigned_integer (gparam, tdep->wordsize,
-                                                word);
+                                                byte_order, word);
                }
              greg++;
              gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
@@ -988,14 +1232,20 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  greg++;
                }
              if (write_pass)
-               /* WARNING: cagney/2003-09-21: Strictly speaking, this
-                  isn't necessary, unfortunately, GCC appears to get
-                  "struct convention" parameter passing wrong putting
-                  odd sized structures in memory instead of in a
-                  register.  Work around this by always writing the
-                  value to memory.  Fortunately, doing this
-                  simplifies the code.  */
-               write_memory (gparam, val, TYPE_LENGTH (type));
+               {
+                 /* WARNING: cagney/2003-09-21: Strictly speaking, this
+                    isn't necessary, unfortunately, GCC appears to get
+                    "struct convention" parameter passing wrong putting
+                    odd sized structures in memory instead of in a
+                    register.  Work around this by always writing the
+                    value to memory.  Fortunately, doing this
+                    simplifies the code.  */
+                 int len = TYPE_LENGTH (type);
+                 if (len < tdep->wordsize)
+                   write_memory (gparam + tdep->wordsize - len, val, len);
+                 else
+                   write_memory (gparam, val, len);
+               }
              if (freg <= 13
                  && TYPE_CODE (type) == TYPE_CODE_STRUCT
                  && TYPE_NFIELDS (type) == 1
@@ -1069,22 +1319,26 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   regcache_cooked_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
 
   /* Write the backchain (it occupies WORDSIZED bytes).  */
-  write_memory_signed_integer (sp, tdep->wordsize, back_chain);
+  write_memory_signed_integer (sp, tdep->wordsize, byte_order, back_chain);
 
   /* Point the inferior function call's return address at the dummy's
      breakpoint.  */
   regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
 
   /* Use the func_addr to find the descriptor, and use that to find
-     the TOC.  */
+     the TOC.  If we're calling via a function pointer, the pointer
+     itself identifies the descriptor.  */
   {
-    CORE_ADDR desc_addr;
-    if (convert_code_addr_to_desc_addr (func_addr, &desc_addr))
+    struct type *ftype = check_typedef (value_type (function));
+    CORE_ADDR desc_addr = value_as_address (function);
+
+    if (TYPE_CODE (ftype) == TYPE_CODE_PTR
+       || convert_code_addr_to_desc_addr (func_addr, &desc_addr))
       {
        /* The TOC is the second double word in the descriptor.  */
        CORE_ADDR toc =
          read_memory_unsigned_integer (desc_addr + tdep->wordsize,
-                                       tdep->wordsize);
+                                       tdep->wordsize, byte_order);
        regcache_cooked_write_unsigned (regcache,
                                        tdep->ppc_gp0_regnum + 2, toc);
       }
@@ -1105,11 +1359,12 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
    location; when READBUF is non-NULL, fill the buffer from the
    corresponding register return-value location.  */
 enum return_value_convention
-ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
-                            struct regcache *regcache, gdb_byte *readbuf,
-                            const gdb_byte *writebuf)
+ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                            struct type *valtype, struct regcache *regcache,
+                            gdb_byte *readbuf, const gdb_byte *writebuf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   /* This function exists to support a calling convention that
      requires floating-point registers.  It shouldn't be used on
@@ -1133,9 +1388,14 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
+  if (TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
+    return get_decimal_float_return_value (gdbarch, valtype, regcache, readbuf,
+                                          writebuf);
   /* Integers in r3.  */
   if ((TYPE_CODE (valtype) == TYPE_CODE_INT
-       || TYPE_CODE (valtype) == TYPE_CODE_ENUM)
+       || TYPE_CODE (valtype) == TYPE_CODE_ENUM
+       || TYPE_CODE (valtype) == TYPE_CODE_CHAR
+       || TYPE_CODE (valtype) == TYPE_CODE_BOOL)
       && TYPE_LENGTH (valtype) <= 8)
     {
       if (writebuf != NULL)
@@ -1151,12 +1411,14 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
          ULONGEST regval;
          regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
                                         &regval);
-         store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval);
+         store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order,
+                                 regval);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
   /* All pointers live in r3.  */
-  if (TYPE_CODE (valtype) == TYPE_CODE_PTR)
+  if (TYPE_CODE (valtype) == TYPE_CODE_PTR
+      || TYPE_CODE (valtype) == TYPE_CODE_REF)
     {
       /* All pointers live in r3.  */
       if (writebuf != NULL)
@@ -1270,20 +1532,3 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
   return RETURN_VALUE_STRUCT_CONVENTION;
 }
 
-CORE_ADDR
-ppc64_sysv_abi_adjust_breakpoint_address (struct gdbarch *gdbarch,
-                                         CORE_ADDR bpaddr)
-{
-  /* PPC64 SYSV specifies that the minimal-symbol "FN" should point at
-     a function-descriptor while the corresponding minimal-symbol
-     ".FN" should point at the entry point.  Consequently, a command
-     like "break FN" applied to an object file with only minimal
-     symbols, will insert the breakpoint into the descriptor at "FN"
-     and not the function at ".FN".  Avoid this confusion by adjusting
-     any attempt to set a descriptor breakpoint into a corresponding
-     function breakpoint.  Note that GDB warns the user when this
-     adjustment is applied - that's ok as otherwise the user will have
-     no way of knowing why their breakpoint at "FN" resulted in the
-     program stopping at ".FN".  */
-  return gdbarch_convert_from_func_ptr_addr (gdbarch, bpaddr, &current_target);
-}
This page took 0.034984 seconds and 4 git commands to generate.