2014-06-27 Luis Machado * ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Explicitly handle passing of complex arguments. (do_ppc_sysv_return_value): Explicitly handle return of complex types. diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 1a880a6..7e18be5 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -269,6 +269,44 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, greg += 4; } } + else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) + { + int type_size = TYPE_LENGTH (type); + int ngpr = type_size / tdep->wordsize; + + /* The PowerPC Unified 32-bit ABI specifies two mutually + conflicting conventions for passing and returning complex + floating-point values. These values are either treated as if + they were represented as a structure containing an array of + size two of the corresponding floating-point types (as + identified by the ATR-PASS-COMPLEX-AS-STRUCT ABI attribute) or + passed in the GPRs (as identified by the + ATR-PASS-COMPLEX-IN-GPRS ABI attribute). Since the latter + convention is the default in GCC, and mandated by the Linux + ABI, that's what we implement. */ + if (ngpr + greg > 11) + { + /* Pass parameter in the stack. */ + argoffset = align_up (argoffset, 8); + if (write_pass) + write_memory (sp + argoffset, val, len); + argoffset += len; + } + else + { + /* Pass the parameter in registers. */ + if (write_pass) + { + int i; + + for (i = 0; i < ngpr; i++) + regcache_cooked_write (regcache, + tdep->ppc_gp0_regnum + greg + i, + val + i * 4); + } + greg += ngpr; + } + } else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len <= 8 && !tdep->soft_float) { @@ -724,6 +762,30 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, } return RETURN_VALUE_REGISTER_CONVENTION; } + + /* The PowerPC Unified 32-bit specifies that complex + floating-point values are returned in the GPRs for + ATR-PASS-COMPLEX-IN-GPRS. */ + if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) + { + int i, nregs; + int return_reg = tdep->ppc_gp0_regnum + 3; + + nregs = TYPE_LENGTH (type) / tdep->wordsize; + + for (i = 0; i < nregs; i++) + { + if (readbuf) + regcache_cooked_read (regcache, return_reg + i, + readbuf + i * tdep->wordsize); + if (writebuf) + regcache_cooked_write (regcache, return_reg + i, + writebuf + i * tdep->wordsize); + } + + return RETURN_VALUE_REGISTER_CONVENTION; + } + if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 16 && !tdep->soft_float