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); |
} |
} |
} |