This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Fix complex argument handling in ppc64 dummy function call
- From: Tiago Stürmer Daitx <tdaitx at linux dot vnet dot ibm dot com>
- To: Sergio Durigan Junior <sergiodj at redhat dot com>
- Cc: gdb-patches at sourceware dot org
- Date: Fri, 1 Mar 2013 11:08:11 -0600 (CST)
- Subject: Re: [PATCH] Fix complex argument handling in ppc64 dummy function call
Sergio, many thanks for the thorough review and the tips. There's no better
way to get these rules to stick in my head. ^_^
Let me know if there is still something amiss.
Cheers,
Tiago
gdb/ChangeLog
2013-03-01 Tiago Stürmer Daitx <tdaitx@linux.vnet.ibm.com>
* ppc-sysv-tdep.c (ppc64_sysv_abi_push_float): New function.
(ppc64_sysv_abi_push_dummy_call): Handle complex arguments.
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index 0ffeab9..cb9fe3b 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -1101,6 +1101,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.
@@ -1218,53 +1295,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++;
@@ -1276,36 +1309,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)
- {
- 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));
- }
+ 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 (write_pass)
+ {
+ 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);
+ }
+ 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);
+ }
+ }
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
&& TYPE_LENGTH (type) <= 8)
{