| Index: gdb/ppc-sysv-tdep.c
|
| diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
|
| index a221b705e4bb728fc837fd0c84bf6feabdedcb08..665128b4b3342baf6f2ed9b5615630306e047f66 100644
|
| --- a/gdb/ppc-sysv-tdep.c
|
| +++ b/gdb/ppc-sysv-tdep.c
|
| @@ -1,8 +1,7 @@
|
| /* Target-dependent code for PowerPC systems using the SVR4 ABI
|
| for GDB, the GNU debugger.
|
|
|
| - Copyright (C) 2000-2003, 2005, 2007-2012 Free Software Foundation,
|
| - Inc.
|
| + Copyright (C) 2000-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -24,7 +23,7 @@
|
| #include "inferior.h"
|
| #include "regcache.h"
|
| #include "value.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "gdb_assert.h"
|
| #include "ppc-tdep.h"
|
| #include "target.h"
|
| @@ -1077,12 +1076,13 @@ static int
|
| convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
|
| {
|
| struct obj_section *dot_fn_section;
|
| - struct minimal_symbol *dot_fn;
|
| + struct bound_minimal_symbol dot_fn;
|
| struct minimal_symbol *fn;
|
| +
|
| /* Find the minimal symbol that corresponds to CODE_ADDR (should
|
| have a name of the form ".FN"). */
|
| dot_fn = lookup_minimal_symbol_by_pc (code_addr);
|
| - if (dot_fn == NULL || SYMBOL_LINKAGE_NAME (dot_fn)[0] != '.')
|
| + if (dot_fn.minsym == NULL || SYMBOL_LINKAGE_NAME (dot_fn.minsym)[0] != '.')
|
| return 0;
|
| /* Get the section that contains CODE_ADDR. Need this for the
|
| "objfile" that it contains. */
|
| @@ -1093,7 +1093,7 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
|
| address. Only look for the minimal symbol in ".FN"'s object file
|
| - avoids problems when two object files (i.e., shared libraries)
|
| contain a minimal symbol with the same name. */
|
| - fn = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn) + 1, NULL,
|
| + fn = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn.minsym) + 1, NULL,
|
| dot_fn_section->objfile);
|
| if (fn == NULL)
|
| return 0;
|
| @@ -1102,6 +1102,83 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
|
| return 1;
|
| }
|
|
|
| +/* Push a float in either registers, or in the stack. Using the ppc 64 bit
|
| + SysV ABI.
|
| +
|
| + This implements a dumbed down version of the ABI. It always writes
|
| + values to memory, GPR and FPR, even when not necessary. Doing this
|
| + greatly simplifies the logic. */
|
| +
|
| +static void
|
| +ppc64_sysv_abi_push_float (struct gdbarch *gdbarch, struct regcache *regcache,
|
| + struct gdbarch_tdep *tdep, struct type *type,
|
| + const bfd_byte *val, int freg, int greg,
|
| + CORE_ADDR gparam)
|
| +{
|
| + gdb_byte regval[MAX_REGISTER_SIZE];
|
| + const gdb_byte *p;
|
| +
|
| + if (TYPE_LENGTH (type) <= 8)
|
| + {
|
| + /* 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);
|
| +
|
| + /* Floats and Doubles go in f1 .. f13. They also consume a left aligned
|
| + GREG, and can end up in memory. */
|
| + if (freg <= 13)
|
| + {
|
| + struct type *regtype;
|
| +
|
| + regtype = register_type (gdbarch, tdep->ppc_fp0_regnum + freg);
|
| + convert_typed_floating (val, type, regval, regtype);
|
| + regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, regval);
|
| + }
|
| + if (greg <= 10)
|
| + regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, regval);
|
| + }
|
| + else
|
| + {
|
| + /* IBM long double stored in two doublewords of the
|
| + parameter save area and corresponding registers. */
|
| + if (!tdep->soft_float && freg <= 13)
|
| + {
|
| + regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, val);
|
| + if (freg <= 12)
|
| + regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg + 1,
|
| + val + 8);
|
| + }
|
| + if (greg <= 10)
|
| + {
|
| + regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, val);
|
| + if (greg <= 9)
|
| + regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 1,
|
| + val + 8);
|
| + }
|
| + write_memory (gparam, val, TYPE_LENGTH (type));
|
| + }
|
| +}
|
| +
|
| /* Pass the arguments in either registers, or in the stack. Using the
|
| ppc 64 bit SysV ABI.
|
|
|
| @@ -1219,53 +1296,9 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
|
|
|
| if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8)
|
| {
|
| - /* Floats and Doubles go in f1 .. f13. They also
|
| - consume a left aligned GREG,, and can end up in
|
| - 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)
|
| - {
|
| - 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)
|
| - regcache_cooked_write (regcache,
|
| - tdep->ppc_gp0_regnum + greg,
|
| - regval);
|
| - }
|
| + ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, type,
|
| + val, freg, greg, gparam);
|
|
|
| freg++;
|
| greg++;
|
| @@ -1277,35 +1310,58 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
|
| && (gdbarch_long_double_format (gdbarch)
|
| == floatformats_ibm_long_double))
|
| {
|
| - /* IBM long double stored in two doublewords of the
|
| - parameter save area and corresponding registers. */
|
| if (write_pass)
|
| + ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, type,
|
| + val, freg, greg, gparam);
|
| + freg += 2;
|
| + greg += 2;
|
| + gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
|
| + }
|
| + else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX
|
| + && (TYPE_LENGTH (type) == 8 || TYPE_LENGTH (type) == 16))
|
| + {
|
| + int i;
|
| +
|
| + for (i = 0; i < 2; i++)
|
| {
|
| - if (!tdep->soft_float && freg <= 13)
|
| - {
|
| - regcache_cooked_write (regcache,
|
| - tdep->ppc_fp0_regnum + freg,
|
| - val);
|
| - if (freg <= 12)
|
| - regcache_cooked_write (regcache,
|
| - tdep->ppc_fp0_regnum + freg + 1,
|
| - val + 8);
|
| - }
|
| - if (greg <= 10)
|
| + if (write_pass)
|
| {
|
| - regcache_cooked_write (regcache,
|
| - tdep->ppc_gp0_regnum + greg,
|
| - val);
|
| - if (greg <= 9)
|
| - regcache_cooked_write (regcache,
|
| - tdep->ppc_gp0_regnum + greg + 1,
|
| - val + 8);
|
| + struct type *target_type;
|
| +
|
| + target_type = check_typedef (TYPE_TARGET_TYPE (type));
|
| + ppc64_sysv_abi_push_float (gdbarch, regcache, tdep,
|
| + target_type, val + i *
|
| + TYPE_LENGTH (target_type),
|
| + freg, greg, gparam);
|
| }
|
| - write_memory (gparam, val, TYPE_LENGTH (type));
|
| + freg++;
|
| + greg++;
|
| + /* Always consume parameter stack space. */
|
| + gparam = align_up (gparam + 8, tdep->wordsize);
|
| + }
|
| + }
|
| + else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX
|
| + && TYPE_LENGTH (type) == 32
|
| + && (gdbarch_long_double_format (gdbarch)
|
| + == floatformats_ibm_long_double))
|
| + {
|
| + int i;
|
| +
|
| + for (i = 0; i < 2; i++)
|
| + {
|
| + struct type *target_type;
|
| +
|
| + target_type = check_typedef (TYPE_TARGET_TYPE (type));
|
| + if (write_pass)
|
| + ppc64_sysv_abi_push_float (gdbarch, regcache, tdep,
|
| + target_type, val + i *
|
| + TYPE_LENGTH (target_type),
|
| + freg, greg, gparam);
|
| + freg += 2;
|
| + greg += 2;
|
| + gparam = align_up (gparam + TYPE_LENGTH (target_type),
|
| + tdep->wordsize);
|
| }
|
| - freg += 2;
|
| - greg += 2;
|
| - gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
|
| }
|
| else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
|
| && TYPE_LENGTH (type) <= 8)
|
| @@ -1921,11 +1977,13 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
|
| gdb_byte regval[MAX_REGISTER_SIZE];
|
| struct type *regtype =
|
| register_type (gdbarch, tdep->ppc_fp0_regnum);
|
| + struct type *target_type;
|
| + target_type = check_typedef (TYPE_TARGET_TYPE (valtype));
|
| if (writebuf != NULL)
|
| {
|
| convert_typed_floating ((const bfd_byte *) writebuf +
|
| - i * (TYPE_LENGTH (valtype) / 2),
|
| - valtype, regval, regtype);
|
| + i * TYPE_LENGTH (target_type),
|
| + target_type, regval, regtype);
|
| regcache_cooked_write (regcache,
|
| tdep->ppc_fp0_regnum + 1 + i,
|
| regval);
|
| @@ -1937,8 +1995,8 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
|
| regval);
|
| convert_typed_floating (regval, regtype,
|
| (bfd_byte *) readbuf +
|
| - i * (TYPE_LENGTH (valtype) / 2),
|
| - valtype);
|
| + i * TYPE_LENGTH (target_type),
|
| + target_type);
|
| }
|
| }
|
| }
|
|
|