X-Git-Url: https://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fppc-sysv-tdep.c;h=f0f618c5eba5e7e85a442df925bb733d876f362d;hb=3c8ea5be24ecc76600b6cea36240449a84c0fc22;hp=e4313633c8d0cba2d91293aff45aa63e1e74c175;hpb=24e9cda06816c3952f81c930777710da5870b5fd;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index e4313633c8..f0f618c5eb 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, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -24,13 +23,29 @@ #include "inferior.h" #include "regcache.h" #include "value.h" -#include "gdb_string.h" -#include "gdb_assert.h" #include "ppc-tdep.h" #include "target.h" #include "objfiles.h" #include "infcall.h" #include "dwarf2.h" +#include "target-float.h" +#include + + +/* Check whether FTPYE is a (pointer to) function type that should use + the OpenCL vector ABI. */ + +static int +ppc_sysv_use_opencl_abi (struct type *ftype) +{ + ftype = check_typedef (ftype); + + if (ftype->code () == TYPE_CODE_PTR) + ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); + + return (ftype->code () == TYPE_CODE_FUNC + && TYPE_CALLING_CONVENTION (ftype) == DW_CC_GDB_IBM_OpenCL); +} /* Pass the arguments in either registers, or in the stack. Using the ppc sysv ABI, the first eight words of the argument list (that might @@ -40,19 +55,19 @@ are passed in user stack. If the function is returning a structure, then the return address is passed - in r3, then the first 7 words of the parametes can be passed in registers, + in r3, then the first 7 words of the parameters can be passed in registers, starting from r4. */ CORE_ADDR ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) + function_call_return_method return_method, + CORE_ADDR struct_addr) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct type *ftype; - int opencl_abi = 0; + int opencl_abi = ppc_sysv_use_opencl_abi (value_type (function)); ULONGEST saved_sp; int argspace = 0; /* 0 is an initial wrong guess. */ int write_pass; @@ -62,13 +77,6 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch), &saved_sp); - ftype = check_typedef (value_type (function)); - if (TYPE_CODE (ftype) == TYPE_CODE_PTR) - ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); - if (TYPE_CODE (ftype) == TYPE_CODE_FUNC - && TYPE_CALLING_CONVENTION (ftype) == DW_CC_GDB_IBM_OpenCL) - opencl_abi = 1; - /* Go through the argument list twice. Pass 1: Figure out how much new stack space is required for @@ -100,7 +108,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, (which will be passed in r3) is used for struct return address. In that case we should advance one word and start from r4 register to copy parameters. */ - if (struct_return) + if (return_method == return_method_struct) { if (write_pass) regcache_cooked_write_signed (regcache, @@ -116,7 +124,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, int len = TYPE_LENGTH (type); const bfd_byte *val = value_contents (arg); - if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8 + if (type->code () == TYPE_CODE_FLT && len <= 8 && !tdep->soft_float) { /* Floating point value converted to "double" then @@ -128,13 +136,12 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { /* Always store the floating point value using the register's floating-point format. */ - gdb_byte regval[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; struct type *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); + target_float_convert (val, type, regval, regtype); + regcache->cooked_write (tdep->ppc_fp0_regnum + freg, + regval); } freg++; } @@ -157,7 +164,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, argoffset += len; } } - else if (TYPE_CODE (type) == TYPE_CODE_FLT + else if (type->code () == TYPE_CODE_FLT && len == 16 && !tdep->soft_float && (gdbarch_long_double_format (gdbarch) @@ -169,12 +176,9 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { 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); + regcache->cooked_write (tdep->ppc_fp0_regnum + freg, val); + regcache->cooked_write (tdep->ppc_fp0_regnum + freg + 1, + val + 8); } freg += 2; } @@ -187,9 +191,9 @@ 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_DECFLOAT + && (type->code () == TYPE_CODE_INT /* long long */ + || type->code () == TYPE_CODE_FLT /* double */ + || (type->code () == TYPE_CODE_DECFLOAT && tdep->soft_float))) { /* "long long" or soft-float "double" or "_Decimal64" @@ -214,21 +218,19 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, greg++; if (write_pass) { - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg + 0, - val + 0); - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg + 1, - val + 4); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 0, + val + 0); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 1, + val + 4); } greg += 2; } } else if (len == 16 - && ((TYPE_CODE (type) == TYPE_CODE_FLT + && ((type->code () == TYPE_CODE_FLT && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double)) - || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT + || (type->code () == TYPE_CODE_DECFLOAT && tdep->soft_float))) { /* Soft-float IBM long double or _Decimal128 passed in @@ -246,23 +248,19 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { if (write_pass) { - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg + 0, - val + 0); - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg + 1, - val + 4); - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg + 2, - val + 8); - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg + 3, - val + 12); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 0, + val + 0); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 1, + val + 4); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 2, + val + 8); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 3, + val + 12); } greg += 4; } } - else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len <= 8 + else if (type->code () == TYPE_CODE_DECFLOAT && len <= 8 && !tdep->soft_float) { /* 32-bit and 64-bit decimal floats go in f1 .. f8. They can @@ -272,7 +270,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { if (write_pass) { - gdb_byte regval[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; const gdb_byte *p; /* 32-bit decimal floats are right aligned in the @@ -285,8 +283,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, else p = val; - regcache_cooked_write (regcache, - tdep->ppc_fp0_regnum + freg, p); + regcache->cooked_write (tdep->ppc_fp0_regnum + freg, p); } freg++; @@ -302,7 +299,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, argoffset += len; } } - else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len == 16 + else if (type->code () == TYPE_CODE_DECFLOAT && len == 16 && !tdep->soft_float) { /* 128-bit decimal floats go in f2 .. f7, always in even/odd @@ -315,10 +312,9 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, 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); + regcache->cooked_write (tdep->ppc_fp0_regnum + freg, val); + regcache->cooked_write (tdep->ppc_fp0_regnum + freg + 1, + val + 8); } } else @@ -338,7 +334,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, freg += 2; } else if (len < 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY + && type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && opencl_abi) { @@ -351,19 +347,19 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { const gdb_byte *elval = val + i * TYPE_LENGTH (eltype); - if (TYPE_CODE (eltype) == TYPE_CODE_FLT && !tdep->soft_float) + if (eltype->code () == TYPE_CODE_FLT && !tdep->soft_float) { if (freg <= 8) { if (write_pass) { int regnum = tdep->ppc_fp0_regnum + freg; - gdb_byte regval[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; struct type *regtype = register_type (gdbarch, regnum); - convert_typed_floating (elval, eltype, - regval, regtype); - regcache_cooked_write (regcache, regnum, regval); + target_float_convert (elval, eltype, + regval, regtype); + regcache->cooked_write (regnum, regval); } freg++; } @@ -395,26 +391,23 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, if (write_pass) { int regnum = tdep->ppc_gp0_regnum + greg; - regcache_cooked_write (regcache, - regnum + 0, elval + 0); - regcache_cooked_write (regcache, - regnum + 1, elval + 4); + regcache->cooked_write (regnum + 0, elval + 0); + regcache->cooked_write (regnum + 1, elval + 4); } greg += 2; } } else { - gdb_byte word[MAX_REGISTER_SIZE]; + gdb_byte word[PPC_MAX_REGISTER_SIZE]; store_unsigned_integer (word, tdep->wordsize, byte_order, unpack_long (eltype, elval)); if (greg <= 10) { if (write_pass) - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg, - word); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg, + word); greg++; } else @@ -428,7 +421,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } } else if (len >= 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY + && type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && opencl_abi) { @@ -443,9 +436,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, if (vreg <= 13) { if (write_pass) - regcache_cooked_write (regcache, - tdep->ppc_vr0_regnum + vreg, - elval); + regcache->cooked_write (tdep->ppc_vr0_regnum + vreg, + elval); vreg++; } else @@ -458,7 +450,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } } else if (len == 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY + && type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && tdep->vector_abi == POWERPC_VEC_ALTIVEC) { @@ -467,8 +459,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, if (vreg <= 13) { if (write_pass) - regcache_cooked_write (regcache, - tdep->ppc_vr0_regnum + vreg, val); + regcache->cooked_write (tdep->ppc_vr0_regnum + vreg, val); vreg++; } else @@ -480,7 +471,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } } else if (len == 8 - && TYPE_CODE (type) == TYPE_CODE_ARRAY + && type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && tdep->vector_abi == POWERPC_VEC_SPE) { @@ -494,8 +485,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, if (greg <= 10) { if (write_pass) - regcache_cooked_write (regcache, - tdep->ppc_ev0_regnum + greg, val); + regcache->cooked_write (tdep->ppc_ev0_regnum + greg, val); greg++; } else @@ -510,15 +500,15 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { /* Reduce the parameter down to something that fits in a "word". */ - gdb_byte word[MAX_REGISTER_SIZE]; - memset (word, 0, MAX_REGISTER_SIZE); + gdb_byte word[PPC_MAX_REGISTER_SIZE]; + memset (word, 0, PPC_MAX_REGISTER_SIZE); if (len > tdep->wordsize - || TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) + || type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION) { /* Structs and large values are put in an aligned stack slot ... */ - if (TYPE_CODE (type) == TYPE_CODE_ARRAY + if (type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && len >= 16) structoffset = align_up (structoffset, 16); @@ -533,7 +523,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, sp + structoffset); structoffset += len; } - else if (TYPE_CODE (type) == TYPE_CODE_INT) + else if (type->code () == TYPE_CODE_INT) /* Sign or zero extend the "int" into a "word". */ store_unsigned_integer (word, tdep->wordsize, byte_order, unpack_long (type, val)); @@ -545,8 +535,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, if (greg <= 10) { if (write_pass) - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg, word); + regcache->cooked_write (tdep->ppc_gp0_regnum + greg, word); greg++; } else @@ -602,23 +591,22 @@ 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 +/* Handle the return-value conventions for Decimal Floating Point values. */ +static enum return_value_convention 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); + gdb_assert (valtype->code () == 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]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; const gdb_byte *p; /* 32-bit decimal float is right aligned in the doubleword. */ @@ -630,11 +618,11 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype, else p = writebuf; - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, p); + regcache->cooked_write (tdep->ppc_fp0_regnum + 1, p); } if (readbuf != NULL) { - regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf); + regcache->cooked_read (tdep->ppc_fp0_regnum + 1, readbuf); /* Left align 32-bit decimal float. */ if (TYPE_LENGTH (valtype) == 4) @@ -651,11 +639,11 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype, for (i = 0; i < 2; i++) { if (writebuf != NULL) - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2 + i, - writebuf + i * 8); + regcache->cooked_write (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); + regcache->cooked_read (tdep->ppc_fp0_regnum + 2 + i, + readbuf + i * 8); } } } @@ -689,15 +677,11 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int opencl_abi = 0; - - if (func_type - && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GDB_IBM_OpenCL) - opencl_abi = 1; + int opencl_abi = func_type? ppc_sysv_use_opencl_abi (func_type) : 0; gdb_assert (tdep->wordsize == 4); - if (TYPE_CODE (type) == TYPE_CODE_FLT + if (type->code () == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8 && !tdep->soft_float) { @@ -705,24 +689,24 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, { /* Floats and doubles stored in "f1". Convert the value to the required type. */ - gdb_byte regval[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum + 1); - regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval); - convert_typed_floating (regval, regtype, readbuf, type); + regcache->cooked_read (tdep->ppc_fp0_regnum + 1, regval); + target_float_convert (regval, regtype, readbuf, type); } if (writebuf) { /* Floats and doubles stored in "f1". Convert the value to the register's "double" type. */ - gdb_byte regval[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum); - convert_typed_floating (writebuf, type, regval, regtype); - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval); + target_float_convert (writebuf, type, regval, regtype); + regcache->cooked_write (tdep->ppc_fp0_regnum + 1, regval); } return RETURN_VALUE_REGISTER_CONVENTION; } - if (TYPE_CODE (type) == TYPE_CODE_FLT + if (type->code () == TYPE_CODE_FLT && TYPE_LENGTH (type) == 16 && !tdep->soft_float && (gdbarch_long_double_format (gdbarch) @@ -731,82 +715,70 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, /* IBM long double stored in f1 and f2. */ if (readbuf) { - regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf); - regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 2, - readbuf + 8); + regcache->cooked_read (tdep->ppc_fp0_regnum + 1, readbuf); + regcache->cooked_read (tdep->ppc_fp0_regnum + 2, readbuf + 8); } if (writebuf) { - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, writebuf); - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2, - writebuf + 8); + regcache->cooked_write (tdep->ppc_fp0_regnum + 1, writebuf); + regcache->cooked_write (tdep->ppc_fp0_regnum + 2, writebuf + 8); } return RETURN_VALUE_REGISTER_CONVENTION; } if (TYPE_LENGTH (type) == 16 - && ((TYPE_CODE (type) == TYPE_CODE_FLT + && ((type->code () == TYPE_CODE_FLT && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double)) - || (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && tdep->soft_float))) + || (type->code () == TYPE_CODE_DECFLOAT && tdep->soft_float))) { /* 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); - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4, - readbuf + 4); - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5, - readbuf + 8); - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6, - readbuf + 12); + regcache->cooked_read (tdep->ppc_gp0_regnum + 3, readbuf); + regcache->cooked_read (tdep->ppc_gp0_regnum + 4, readbuf + 4); + regcache->cooked_read (tdep->ppc_gp0_regnum + 5, readbuf + 8); + regcache->cooked_read (tdep->ppc_gp0_regnum + 6, readbuf + 12); } if (writebuf) { - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4, - writebuf + 4); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5, - writebuf + 8); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6, - writebuf + 12); + regcache->cooked_write (tdep->ppc_gp0_regnum + 3, writebuf); + regcache->cooked_write (tdep->ppc_gp0_regnum + 4, writebuf + 4); + regcache->cooked_write (tdep->ppc_gp0_regnum + 5, writebuf + 8); + regcache->cooked_write (tdep->ppc_gp0_regnum + 6, writebuf + 12); } 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_DECFLOAT && TYPE_LENGTH (type) == 8 + if ((type->code () == TYPE_CODE_INT && TYPE_LENGTH (type) == 8) + || (type->code () == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8) + || (type->code () == TYPE_CODE_DECFLOAT && TYPE_LENGTH (type) == 8 && tdep->soft_float)) { if (readbuf) { /* 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, - readbuf + 4); + regcache->cooked_read (tdep->ppc_gp0_regnum + 3, readbuf + 0); + regcache->cooked_read (tdep->ppc_gp0_regnum + 4, readbuf + 4); } if (writebuf) { /* 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, - writebuf + 4); + regcache->cooked_write (tdep->ppc_gp0_regnum + 3, writebuf + 0); + regcache->cooked_write (tdep->ppc_gp0_regnum + 4, writebuf + 4); } return RETURN_VALUE_REGISTER_CONVENTION; } - if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && !tdep->soft_float) + if (type->code () == 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 - || TYPE_CODE (type) == TYPE_CODE_PTR - || TYPE_CODE (type) == TYPE_CODE_REF - || TYPE_CODE (type) == TYPE_CODE_ENUM) + else if ((type->code () == TYPE_CODE_INT + || type->code () == TYPE_CODE_CHAR + || type->code () == TYPE_CODE_BOOL + || type->code () == TYPE_CODE_PTR + || TYPE_IS_REFERENCE (type) + || type->code () == TYPE_CODE_ENUM) && TYPE_LENGTH (type) <= tdep->wordsize) { if (readbuf) @@ -831,7 +803,7 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, } /* OpenCL vectors < 16 bytes are returned as distinct scalars in f1..f2 or r3..r10. */ - if (TYPE_CODE (type) == TYPE_CODE_ARRAY + if (type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && TYPE_LENGTH (type) < 16 && opencl_abi) @@ -843,23 +815,23 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, { int offset = i * TYPE_LENGTH (eltype); - if (TYPE_CODE (eltype) == TYPE_CODE_FLT) + if (eltype->code () == TYPE_CODE_FLT) { int regnum = tdep->ppc_fp0_regnum + 1 + i; - gdb_byte regval[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; struct type *regtype = register_type (gdbarch, regnum); if (writebuf != NULL) { - convert_typed_floating (writebuf + offset, eltype, - regval, regtype); - regcache_cooked_write (regcache, regnum, regval); + target_float_convert (writebuf + offset, eltype, + regval, regtype); + regcache->cooked_write (regnum, regval); } if (readbuf != NULL) { - regcache_cooked_read (regcache, regnum, regval); - convert_typed_floating (regval, regtype, - readbuf + offset, eltype); + regcache->cooked_read (regnum, regval); + target_float_convert (regval, regtype, + readbuf + offset, eltype); } } else @@ -885,7 +857,7 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, return RETURN_VALUE_REGISTER_CONVENTION; } /* OpenCL vectors >= 16 bytes are returned in v2..v9. */ - if (TYPE_CODE (type) == TYPE_CODE_ARRAY + if (type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && TYPE_LENGTH (type) >= 16 && opencl_abi) @@ -899,32 +871,32 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, int regnum = tdep->ppc_vr0_regnum + 2 + i; if (writebuf != NULL) - regcache_cooked_write (regcache, regnum, writebuf + offset); + regcache->cooked_write (regnum, writebuf + offset); if (readbuf != NULL) - regcache_cooked_read (regcache, regnum, readbuf + offset); + regcache->cooked_read (regnum, readbuf + offset); } return RETURN_VALUE_REGISTER_CONVENTION; } if (TYPE_LENGTH (type) == 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY + && type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && tdep->vector_abi == POWERPC_VEC_ALTIVEC) { if (readbuf) { /* Altivec places the return value in "v2". */ - regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf); + regcache->cooked_read (tdep->ppc_vr0_regnum + 2, readbuf); } if (writebuf) { /* Altivec places the return value in "v2". */ - regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf); + regcache->cooked_write (tdep->ppc_vr0_regnum + 2, writebuf); } return RETURN_VALUE_REGISTER_CONVENTION; } if (TYPE_LENGTH (type) == 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY + && type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && tdep->vector_abi == POWERPC_VEC_GENERIC) { @@ -933,30 +905,22 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, ABI risks in that case; we don't try to support it. */ if (readbuf) { - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, - readbuf + 0); - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4, - readbuf + 4); - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5, - readbuf + 8); - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6, - readbuf + 12); + regcache->cooked_read (tdep->ppc_gp0_regnum + 3, readbuf + 0); + regcache->cooked_read (tdep->ppc_gp0_regnum + 4, readbuf + 4); + regcache->cooked_read (tdep->ppc_gp0_regnum + 5, readbuf + 8); + regcache->cooked_read (tdep->ppc_gp0_regnum + 6, readbuf + 12); } if (writebuf) { - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, - writebuf + 0); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4, - writebuf + 4); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5, - writebuf + 8); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6, - writebuf + 12); + regcache->cooked_write (tdep->ppc_gp0_regnum + 3, writebuf + 0); + regcache->cooked_write (tdep->ppc_gp0_regnum + 4, writebuf + 4); + regcache->cooked_write (tdep->ppc_gp0_regnum + 5, writebuf + 8); + regcache->cooked_write (tdep->ppc_gp0_regnum + 6, writebuf + 12); } return RETURN_VALUE_REGISTER_CONVENTION; } if (TYPE_LENGTH (type) == 8 - && TYPE_CODE (type) == TYPE_CODE_ARRAY + && type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) && tdep->vector_abi == POWERPC_VEC_SPE) { @@ -966,9 +930,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, only corresponds to the least significant 32-bits. So place the 64-bit DSP type's value in ev3. */ if (readbuf) - regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 3, readbuf); + regcache->cooked_read (tdep->ppc_ev0_regnum + 3, readbuf); if (writebuf) - regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 3, writebuf); + regcache->cooked_write (tdep->ppc_ev0_regnum + 3, writebuf); return RETURN_VALUE_REGISTER_CONVENTION; } if (broken_gcc && TYPE_LENGTH (type) <= 8) @@ -976,28 +940,28 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, /* GCC screwed up for structures or unions whose size is less than or equal to 8 bytes.. Instead of left-aligning, it right-aligns the data into the buffer formed by r3, r4. */ - gdb_byte regvals[MAX_REGISTER_SIZE * 2]; + gdb_byte regvals[PPC_MAX_REGISTER_SIZE * 2]; int len = TYPE_LENGTH (type); int offset = (2 * tdep->wordsize - len) % tdep->wordsize; if (readbuf) { - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, - regvals + 0 * tdep->wordsize); + regcache->cooked_read (tdep->ppc_gp0_regnum + 3, + regvals + 0 * tdep->wordsize); if (len > tdep->wordsize) - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4, - regvals + 1 * tdep->wordsize); + regcache->cooked_read (tdep->ppc_gp0_regnum + 4, + regvals + 1 * tdep->wordsize); memcpy (readbuf, regvals + offset, len); } if (writebuf) { memset (regvals, 0, sizeof regvals); memcpy (regvals + offset, writebuf, len); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, - regvals + 0 * tdep->wordsize); + regcache->cooked_write (tdep->ppc_gp0_regnum + 3, + regvals + 0 * tdep->wordsize); if (len > tdep->wordsize) - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4, - regvals + 1 * tdep->wordsize); + regcache->cooked_write (tdep->ppc_gp0_regnum + 4, + regvals + 1 * tdep->wordsize); } return RETURN_VALUE_REGISTER_CONVENTION; @@ -1009,12 +973,12 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, /* This matches SVr4 PPC, it does not match GCC. */ /* The value is right-padded to 8 bytes and then loaded, as two "words", into r3/r4. */ - gdb_byte regvals[MAX_REGISTER_SIZE * 2]; - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, - regvals + 0 * tdep->wordsize); + gdb_byte regvals[PPC_MAX_REGISTER_SIZE * 2]; + regcache->cooked_read (tdep->ppc_gp0_regnum + 3, + regvals + 0 * tdep->wordsize); if (TYPE_LENGTH (type) > tdep->wordsize) - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4, - regvals + 1 * tdep->wordsize); + regcache->cooked_read (tdep->ppc_gp0_regnum + 4, + regvals + 1 * tdep->wordsize); memcpy (readbuf, regvals, TYPE_LENGTH (type)); } if (writebuf) @@ -1022,14 +986,14 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, /* This matches SVr4 PPC, it does not match GCC. */ /* The value is padded out to 8 bytes and then loaded, as two "words" into r3/r4. */ - gdb_byte regvals[MAX_REGISTER_SIZE * 2]; + gdb_byte regvals[PPC_MAX_REGISTER_SIZE * 2]; memset (regvals, 0, sizeof regvals); memcpy (regvals, writebuf, TYPE_LENGTH (type)); - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, - regvals + 0 * tdep->wordsize); + regcache->cooked_write (tdep->ppc_gp0_regnum + 3, + regvals + 0 * tdep->wordsize); if (TYPE_LENGTH (type) > tdep->wordsize) - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4, - regvals + 1 * tdep->wordsize); + regcache->cooked_write (tdep->ppc_gp0_regnum + 4, + regvals + 1 * tdep->wordsize); } return RETURN_VALUE_REGISTER_CONVENTION; } @@ -1037,23 +1001,25 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, } enum return_value_convention -ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type, +ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { - return do_ppc_sysv_return_value (gdbarch, func_type, valtype, regcache, - readbuf, writebuf, 0); + return do_ppc_sysv_return_value (gdbarch, + function ? value_type (function) : NULL, + valtype, regcache, readbuf, writebuf, 0); } enum return_value_convention ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch, - struct type *func_type, + struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { - return do_ppc_sysv_return_value (gdbarch, func_type, valtype, regcache, - readbuf, writebuf, 1); + return do_ppc_sysv_return_value (gdbarch, + function ? value_type (function) : NULL, + valtype, regcache, readbuf, writebuf, 1); } /* The helper function for 64-bit SYSV push_dummy_call. Converts the @@ -1071,13 +1037,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 minimal_symbol *fn; - CORE_ADDR toc; + struct bound_minimal_symbol dot_fn; + struct bound_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 || dot_fn.minsym->linkage_name ()[0] != '.') return 0; /* Get the section that contains CODE_ADDR. Need this for the "objfile" that it contains. */ @@ -1088,15 +1054,481 @@ 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 (dot_fn.minsym->linkage_name () + 1, NULL, dot_fn_section->objfile); - if (fn == NULL) + if (fn.minsym == NULL) return 0; /* Found a descriptor. */ - (*desc_addr) = SYMBOL_VALUE_ADDRESS (fn); + (*desc_addr) = BMSYMBOL_VALUE_ADDRESS (fn); return 1; } +/* Walk down the type tree of TYPE counting consecutive base elements. + If *FIELD_TYPE is NULL, then set it to the first valid floating point + or vector type. If a non-floating point or vector type is found, or + if a floating point or vector type that doesn't match a non-NULL + *FIELD_TYPE is found, then return -1, otherwise return the count in the + sub-tree. */ + +static LONGEST +ppc64_aggregate_candidate (struct type *type, + struct type **field_type) +{ + type = check_typedef (type); + + switch (type->code ()) + { + case TYPE_CODE_FLT: + case TYPE_CODE_DECFLOAT: + if (!*field_type) + *field_type = type; + if ((*field_type)->code () == type->code () + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 1; + break; + + case TYPE_CODE_COMPLEX: + type = TYPE_TARGET_TYPE (type); + if (type->code () == TYPE_CODE_FLT + || type->code () == TYPE_CODE_DECFLOAT) + { + if (!*field_type) + *field_type = type; + if ((*field_type)->code () == type->code () + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 2; + } + break; + + case TYPE_CODE_ARRAY: + if (TYPE_VECTOR (type)) + { + if (!*field_type) + *field_type = type; + if ((*field_type)->code () == type->code () + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 1; + } + else + { + LONGEST count, low_bound, high_bound; + + count = ppc64_aggregate_candidate + (TYPE_TARGET_TYPE (type), field_type); + if (count == -1) + return -1; + + if (!get_array_bounds (type, &low_bound, &high_bound)) + return -1; + count *= high_bound - low_bound; + + /* There must be no padding. */ + if (count == 0) + return TYPE_LENGTH (type) == 0 ? 0 : -1; + else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type)) + return -1; + + return count; + } + break; + + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + { + LONGEST count = 0; + int i; + + for (i = 0; i < type->num_fields (); i++) + { + LONGEST sub_count; + + if (field_is_static (&type->field (i))) + continue; + + sub_count = ppc64_aggregate_candidate + (type->field (i).type (), field_type); + if (sub_count == -1) + return -1; + + if (type->code () == TYPE_CODE_STRUCT) + count += sub_count; + else + count = std::max (count, sub_count); + } + + /* There must be no padding. */ + if (count == 0) + return TYPE_LENGTH (type) == 0 ? 0 : -1; + else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type)) + return -1; + + return count; + } + break; + + default: + break; + } + + return -1; +} + +/* If an argument of type TYPE is a homogeneous float or vector aggregate + that shall be passed in FP/vector registers according to the ELFv2 ABI, + return the homogeneous element type in *ELT_TYPE and the number of + elements in *N_ELTS, and return non-zero. Otherwise, return zero. */ + +static int +ppc64_elfv2_abi_homogeneous_aggregate (struct type *type, + struct type **elt_type, int *n_elts) +{ + /* Complex types at the top level are treated separately. However, + complex types can be elements of homogeneous aggregates. */ + if (type->code () == TYPE_CODE_STRUCT + || type->code () == TYPE_CODE_UNION + || (type->code () == TYPE_CODE_ARRAY && !TYPE_VECTOR (type))) + { + struct type *field_type = NULL; + LONGEST field_count = ppc64_aggregate_candidate (type, &field_type); + + if (field_count > 0) + { + int n_regs = ((field_type->code () == TYPE_CODE_FLT + || field_type->code () == TYPE_CODE_DECFLOAT)? + (TYPE_LENGTH (field_type) + 7) >> 3 : 1); + + /* The ELFv2 ABI allows homogeneous aggregates to occupy + up to 8 registers. */ + if (field_count * n_regs <= 8) + { + if (elt_type) + *elt_type = field_type; + if (n_elts) + *n_elts = (int) field_count; + /* Note that field_count is LONGEST since it may hold the size + of an array, while *n_elts is int since its value is bounded + by the number of registers used for argument passing. The + cast cannot overflow due to the bounds checking above. */ + return 1; + } + } + } + + return 0; +} + +/* Structure holding the next argument position. */ +struct ppc64_sysv_argpos + { + /* Register cache holding argument registers. If this is NULL, + we only simulate argument processing without actually updating + any registers or memory. */ + struct regcache *regcache; + /* Next available general-purpose argument register. */ + int greg; + /* Next available floating-point argument register. */ + int freg; + /* Next available vector argument register. */ + int vreg; + /* The address, at which the next general purpose parameter + (integer, struct, float, vector, ...) should be saved. */ + CORE_ADDR gparam; + /* The address, at which the next by-reference parameter + (non-Altivec vector, variably-sized type) should be saved. */ + CORE_ADDR refparam; + }; + +/* VAL is a value of length LEN. Store it into the argument area on the + stack and load it into the corresponding general-purpose registers + required by the ABI, and update ARGPOS. + + If ALIGN is nonzero, it specifies the minimum alignment required + for the on-stack copy of the argument. */ + +static void +ppc64_sysv_abi_push_val (struct gdbarch *gdbarch, + const bfd_byte *val, int len, int align, + struct ppc64_sysv_argpos *argpos) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int offset = 0; + + /* Enforce alignment of stack location, if requested. */ + if (align > tdep->wordsize) + { + CORE_ADDR aligned_gparam = align_up (argpos->gparam, align); + + argpos->greg += (aligned_gparam - argpos->gparam) / tdep->wordsize; + argpos->gparam = aligned_gparam; + } + + /* The ABI (version 1.9) specifies that values smaller than one + doubleword are right-aligned and those larger are left-aligned. + GCC versions before 3.4 implemented this incorrectly; see + . */ + if (len < tdep->wordsize + && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = tdep->wordsize - len; + + if (argpos->regcache) + write_memory (argpos->gparam + offset, val, len); + argpos->gparam = align_up (argpos->gparam + len, tdep->wordsize); + + while (len >= tdep->wordsize) + { + if (argpos->regcache && argpos->greg <= 10) + argpos->regcache->cooked_write (tdep->ppc_gp0_regnum + argpos->greg, + val); + argpos->greg++; + len -= tdep->wordsize; + val += tdep->wordsize; + } + + if (len > 0) + { + if (argpos->regcache && argpos->greg <= 10) + argpos->regcache->cooked_write_part + (tdep->ppc_gp0_regnum + argpos->greg, offset, len, val); + argpos->greg++; + } +} + +/* The same as ppc64_sysv_abi_push_val, but using a single-word integer + value VAL as argument. */ + +static void +ppc64_sysv_abi_push_integer (struct gdbarch *gdbarch, ULONGEST val, + struct ppc64_sysv_argpos *argpos) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + gdb_byte buf[PPC_MAX_REGISTER_SIZE]; + + if (argpos->regcache) + store_unsigned_integer (buf, tdep->wordsize, byte_order, val); + ppc64_sysv_abi_push_val (gdbarch, buf, tdep->wordsize, 0, argpos); +} + +/* VAL is a value of TYPE, a (binary or decimal) floating-point type. + Load it into a floating-point register if required by the ABI, + and update ARGPOS. */ + +static void +ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch, + struct type *type, const bfd_byte *val, + struct ppc64_sysv_argpos *argpos) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + if (tdep->soft_float) + return; + + if (TYPE_LENGTH (type) <= 8 + && type->code () == TYPE_CODE_FLT) + { + /* Floats and doubles go in f1 .. f13. 32-bit floats are converted + to double first. */ + if (argpos->regcache && argpos->freg <= 13) + { + int regnum = tdep->ppc_fp0_regnum + argpos->freg; + struct type *regtype = register_type (gdbarch, regnum); + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; + + target_float_convert (val, type, regval, regtype); + argpos->regcache->cooked_write (regnum, regval); + } + + argpos->freg++; + } + else if (TYPE_LENGTH (type) <= 8 + && type->code () == TYPE_CODE_DECFLOAT) + { + /* Floats and doubles go in f1 .. f13. 32-bit decimal floats are + placed in the least significant word. */ + if (argpos->regcache && argpos->freg <= 13) + { + int regnum = tdep->ppc_fp0_regnum + argpos->freg; + int offset = 0; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - TYPE_LENGTH (type); + + argpos->regcache->cooked_write_part (regnum, offset, + TYPE_LENGTH (type), val); + } + + argpos->freg++; + } + else if (TYPE_LENGTH (type) == 16 + && type->code () == TYPE_CODE_FLT + && (gdbarch_long_double_format (gdbarch) + == floatformats_ibm_long_double)) + { + /* IBM long double stored in two consecutive FPRs. */ + if (argpos->regcache && argpos->freg <= 13) + { + int regnum = tdep->ppc_fp0_regnum + argpos->freg; + + argpos->regcache->cooked_write (regnum, val); + if (argpos->freg <= 12) + argpos->regcache->cooked_write (regnum + 1, val + 8); + } + + argpos->freg += 2; + } + else if (TYPE_LENGTH (type) == 16 + && type->code () == TYPE_CODE_DECFLOAT) + { + /* 128-bit decimal floating-point values are stored in and even/odd + pair of FPRs, with the even FPR holding the most significant half. */ + argpos->freg += argpos->freg & 1; + + if (argpos->regcache && argpos->freg <= 12) + { + int regnum = tdep->ppc_fp0_regnum + argpos->freg; + int lopart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 : 0; + int hipart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; + + argpos->regcache->cooked_write (regnum, val + hipart); + argpos->regcache->cooked_write (regnum + 1, val + lopart); + } + + argpos->freg += 2; + } +} + +/* VAL is a value of AltiVec vector type. Load it into a vector register + if required by the ABI, and update ARGPOS. */ + +static void +ppc64_sysv_abi_push_vreg (struct gdbarch *gdbarch, const bfd_byte *val, + struct ppc64_sysv_argpos *argpos) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (argpos->regcache && argpos->vreg <= 13) + argpos->regcache->cooked_write (tdep->ppc_vr0_regnum + argpos->vreg, val); + + argpos->vreg++; +} + +/* VAL is a value of TYPE. Load it into memory and/or registers + as required by the ABI, and update ARGPOS. */ + +static void +ppc64_sysv_abi_push_param (struct gdbarch *gdbarch, + struct type *type, const bfd_byte *val, + struct ppc64_sysv_argpos *argpos) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (type->code () == TYPE_CODE_FLT + || type->code () == TYPE_CODE_DECFLOAT) + { + /* Floating-point scalars are passed in floating-point registers. */ + ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 0, argpos); + ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos); + } + else if (type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) + && tdep->vector_abi == POWERPC_VEC_ALTIVEC + && TYPE_LENGTH (type) == 16) + { + /* AltiVec vectors are passed aligned, and in vector registers. */ + ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 16, argpos); + ppc64_sysv_abi_push_vreg (gdbarch, val, argpos); + } + else if (type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) + && TYPE_LENGTH (type) >= 16) + { + /* Non-Altivec vectors are passed by reference. */ + + /* Copy value onto the stack ... */ + CORE_ADDR addr = align_up (argpos->refparam, 16); + if (argpos->regcache) + write_memory (addr, val, TYPE_LENGTH (type)); + argpos->refparam = align_up (addr + TYPE_LENGTH (type), tdep->wordsize); + + /* ... and pass a pointer to the copy as parameter. */ + ppc64_sysv_abi_push_integer (gdbarch, addr, argpos); + } + else if ((type->code () == TYPE_CODE_INT + || type->code () == TYPE_CODE_ENUM + || type->code () == TYPE_CODE_BOOL + || type->code () == TYPE_CODE_CHAR + || type->code () == TYPE_CODE_PTR + || TYPE_IS_REFERENCE (type)) + && TYPE_LENGTH (type) <= tdep->wordsize) + { + ULONGEST word = 0; + + if (argpos->regcache) + { + /* Sign extend the value, then store it unsigned. */ + word = unpack_long (type, val); + + /* Convert any function code addresses into descriptors. */ + if (tdep->elf_abi == POWERPC_ELF_V1 + && (type->code () == TYPE_CODE_PTR + || type->code () == TYPE_CODE_REF)) + { + struct type *target_type + = check_typedef (TYPE_TARGET_TYPE (type)); + + if (target_type->code () == TYPE_CODE_FUNC + || target_type->code () == TYPE_CODE_METHOD) + { + CORE_ADDR desc = word; + + convert_code_addr_to_desc_addr (word, &desc); + word = desc; + } + } + } + + ppc64_sysv_abi_push_integer (gdbarch, word, argpos); + } + else + { + ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 0, argpos); + + /* The ABI (version 1.9) specifies that structs containing a + single floating-point value, at any level of nesting of + single-member structs, are passed in floating-point registers. */ + if (type->code () == TYPE_CODE_STRUCT + && type->num_fields () == 1) + { + while (type->code () == TYPE_CODE_STRUCT + && type->num_fields () == 1) + type = check_typedef (type->field (0).type ()); + + if (type->code () == TYPE_CODE_FLT) + ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos); + } + + /* In the ELFv2 ABI, homogeneous floating-point or vector + aggregates are passed in a series of registers. */ + if (tdep->elf_abi == POWERPC_ELF_V2) + { + struct type *eltype; + int i, nelt; + + if (ppc64_elfv2_abi_homogeneous_aggregate (type, &eltype, &nelt)) + for (i = 0; i < nelt; i++) + { + const gdb_byte *elval = val + i * TYPE_LENGTH (eltype); + + if (eltype->code () == TYPE_CODE_FLT + || eltype->code () == TYPE_CODE_DECFLOAT) + ppc64_sysv_abi_push_freg (gdbarch, eltype, elval, argpos); + else if (eltype->code () == TYPE_CODE_ARRAY + && TYPE_VECTOR (eltype) + && tdep->vector_abi == POWERPC_VEC_ALTIVEC + && TYPE_LENGTH (eltype) == 16) + ppc64_sysv_abi_push_vreg (gdbarch, elval, argpos); + } + } + } +} + /* Pass the arguments in either registers, or in the stack. Using the ppc 64 bit SysV ABI. @@ -1109,13 +1541,13 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) + function_call_return_method return_method, + CORE_ADDR struct_addr) { 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); - struct type *ftype; - int opencl_abi = 0; + int opencl_abi = ppc_sysv_use_opencl_abi (value_type (function)); ULONGEST back_chain; /* See for-loop comment below. */ int write_pass; @@ -1145,13 +1577,6 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch), &back_chain); - ftype = check_typedef (value_type (function)); - if (TYPE_CODE (ftype) == TYPE_CODE_PTR) - ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); - if (TYPE_CODE (ftype) == TYPE_CODE_FUNC - && TYPE_CALLING_CONVENTION (ftype) == DW_CC_GDB_IBM_OpenCL) - opencl_abi = 1; - /* Go through the argument list twice. Pass 1: Compute the function call's stack space and register @@ -1163,20 +1588,11 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, for (write_pass = 0; write_pass < 2; write_pass++) { int argno; - /* Next available floating point register for float and double - arguments. */ - int freg = 1; - /* Next available general register for non-vector (but possibly - float) arguments. */ - int greg = 3; - /* Next available vector register for vector arguments. */ - int vreg = 2; - /* The address, at which the next general purpose parameter - (integer, struct, float, vector, ...) should be saved. */ - CORE_ADDR gparam; - /* The address, at which the next by-reference parameter - (non-Altivec vector, variably-sized type) should be saved. */ - CORE_ADDR refparam; + + struct ppc64_sysv_argpos argpos; + argpos.greg = 3; + argpos.freg = 1; + argpos.vreg = 2; if (!write_pass) { @@ -1184,19 +1600,25 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, offsets (start address zero) than addresses. That way they accumulate the total stack space each region requires. */ - gparam = 0; - refparam = 0; + argpos.regcache = NULL; + argpos.gparam = 0; + argpos.refparam = 0; } else { /* Decrement the stack pointer making space for the Altivec and general on-stack parameters. Set refparam and gparam to their corresponding regions. */ - refparam = align_down (sp - refparam_size, 16); - gparam = align_down (refparam - gparam_size, 16); - /* Add in space for the TOC, link editor double word, - compiler double word, LR save area, CR save area. */ - sp = align_down (gparam - 48, 16); + argpos.regcache = regcache; + argpos.refparam = align_down (sp - refparam_size, 16); + argpos.gparam = align_down (argpos.refparam - gparam_size, 16); + /* Add in space for the TOC, link editor double word (v1 only), + compiler double word (v1 only), LR save area, CR save area, + and backchain. */ + if (tdep->elf_abi == POWERPC_ELF_V1) + sp = align_down (argpos.gparam - 48, 16); + else + sp = align_down (argpos.gparam - 32, 16); } /* If the function is returning a `struct', then there is an @@ -1204,15 +1626,8 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, containing the address of that struct.. In that case we should advance one word and start from r4 register to copy parameters. This also consumes one on-stack parameter slot. */ - if (struct_return) - { - if (write_pass) - regcache_cooked_write_signed (regcache, - tdep->ppc_gp0_regnum + greg, - struct_addr); - greg++; - gparam = align_up (gparam + tdep->wordsize, tdep->wordsize); - } + if (return_method == return_method_struct) + ppc64_sysv_abi_push_integer (gdbarch, struct_addr, &argpos); for (argno = 0; argno < nargs; argno++) { @@ -1220,488 +1635,260 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, 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) + if (type->code () == TYPE_CODE_COMPLEX) { - /* 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." + /* Complex types are passed as if two independent scalars. */ + struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); - 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; + ppc64_sysv_abi_push_param (gdbarch, eltype, val, &argpos); + ppc64_sysv_abi_push_param (gdbarch, eltype, + val + TYPE_LENGTH (eltype), &argpos); + } + else if (type->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (type) + && opencl_abi) + { + /* OpenCL vectors shorter than 16 bytes are passed as if + a series of independent scalars; OpenCL vectors 16 bytes + or longer are passed as if a series of AltiVec vectors. */ + struct type *eltype; + int i, nelt; - /* Write value in the stack's parameter save area. */ - write_memory (gparam, p, 8); + if (TYPE_LENGTH (type) < 16) + eltype = check_typedef (TYPE_TARGET_TYPE (type)); + else + eltype = register_type (gdbarch, tdep->ppc_vr0_regnum); - if (freg <= 13) - { - struct type *regtype - = register_type (gdbarch, tdep->ppc_fp0_regnum); + nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype); + for (i = 0; i < nelt; i++) + { + const gdb_byte *elval = val + i * TYPE_LENGTH (eltype); - 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_param (gdbarch, eltype, elval, &argpos); } - - freg++; - greg++; - /* Always consume parameter stack space. */ - gparam = align_up (gparam + 8, tdep->wordsize); } - else if (TYPE_CODE (type) == TYPE_CODE_FLT - && TYPE_LENGTH (type) == 16 - && (gdbarch_long_double_format (gdbarch) - == floatformats_ibm_long_double)) + else { - /* 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)); - } - freg += 2; - greg += 2; - gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize); + /* All other types are passed as single arguments. */ + ppc64_sysv_abi_push_param (gdbarch, type, val, &argpos); } - 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; + if (!write_pass) + { + /* Save the true region sizes ready for the second pass. */ + refparam_size = argpos.refparam; + /* Make certain that the general parameter save area is at + least the minimum 8 registers (or doublewords) in size. */ + if (argpos.greg < 8) + gparam_size = 8 * tdep->wordsize; + else + gparam_size = argpos.gparam; + } + } - /* Write value in the stack's parameter save area. */ - write_memory (gparam, p, 8); + /* Update %sp. */ + regcache_cooked_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp); - if (freg <= 13) - regcache_cooked_write (regcache, - tdep->ppc_fp0_regnum + freg, p); - } + /* Write the backchain (it occupies WORDSIZED bytes). */ + write_memory_signed_integer (sp, tdep->wordsize, byte_order, back_chain); - 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); - } + /* Point the inferior function call's return address at the dummy's + breakpoint. */ + regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr); - write_memory (gparam, val, TYPE_LENGTH (type)); - } + /* In the ELFv1 ABI, use the func_addr to find the descriptor, and use + that to find the TOC. If we're calling via a function pointer, + the pointer itself identifies the descriptor. */ + if (tdep->elf_abi == POWERPC_ELF_V1) + { + struct type *ftype = check_typedef (value_type (function)); + CORE_ADDR desc_addr = value_as_address (function); - freg += 2; - greg += 2; - gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize); - } - else if (TYPE_LENGTH (type) < 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type) - && opencl_abi) - { - /* OpenCL vectors shorter than 16 bytes are passed as if - a series of independent scalars. */ - struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); - int i, nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype); - - for (i = 0; i < nelt; i++) - { - const gdb_byte *elval = val + i * TYPE_LENGTH (eltype); - - if (TYPE_CODE (eltype) == TYPE_CODE_FLT) - { - if (write_pass) - { - gdb_byte regval[MAX_REGISTER_SIZE]; - const gdb_byte *p; - - if (TYPE_LENGTH (eltype) == 4) - { - memcpy (regval, elval, 4); - memcpy (regval + 4, elval, 4); - p = regval; - } - else - p = elval; - - write_memory (gparam, p, 8); + if (ftype->code () == 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, byte_order); - if (freg <= 13) - { - int regnum = tdep->ppc_fp0_regnum + freg; - struct type *regtype - = register_type (gdbarch, regnum); + regcache_cooked_write_unsigned (regcache, + tdep->ppc_gp0_regnum + 2, toc); + } + } - convert_typed_floating (elval, eltype, - regval, regtype); - regcache_cooked_write (regcache, regnum, regval); - } + /* In the ELFv2 ABI, we need to pass the target address in r12 since + we may be calling a global entry point. */ + if (tdep->elf_abi == POWERPC_ELF_V2) + regcache_cooked_write_unsigned (regcache, + tdep->ppc_gp0_regnum + 12, func_addr); - if (greg <= 10) - regcache_cooked_write (regcache, - tdep->ppc_gp0_regnum + greg, - regval); - } + return sp; +} - freg++; - greg++; - gparam = align_up (gparam + 8, tdep->wordsize); - } - else - { - if (write_pass) - { - ULONGEST word = unpack_long (eltype, elval); - if (greg <= 10) - regcache_cooked_write_unsigned - (regcache, tdep->ppc_gp0_regnum + greg, word); +/* Subroutine of ppc64_sysv_abi_return_value that handles "base" types: + integer, floating-point, and AltiVec vector types. - write_memory_unsigned_integer - (gparam, tdep->wordsize, byte_order, word); - } + This routine also handles components of aggregate return types; + INDEX describes which part of the aggregate is to be handled. - greg++; - gparam = align_up (gparam + TYPE_LENGTH (eltype), - tdep->wordsize); - } - } - } - else if (TYPE_LENGTH (type) >= 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type) - && opencl_abi) - { - /* OpenCL vectors 16 bytes or longer are passed as if - a series of AltiVec vectors. */ - int i; + Returns true if VALTYPE is some such base type that could be handled, + false otherwise. */ +static int +ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, gdb_byte *readbuf, + const gdb_byte *writebuf, int index) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - for (i = 0; i < TYPE_LENGTH (type) / 16; i++) - { - const gdb_byte *elval = val + i * 16; + /* Integers live in GPRs starting at r3. */ + if ((valtype->code () == TYPE_CODE_INT + || valtype->code () == TYPE_CODE_ENUM + || valtype->code () == TYPE_CODE_CHAR + || valtype->code () == TYPE_CODE_BOOL) + && TYPE_LENGTH (valtype) <= 8) + { + int regnum = tdep->ppc_gp0_regnum + 3 + index; - gparam = align_up (gparam, 16); - greg += greg & 1; + if (writebuf != NULL) + { + /* Be careful to sign extend the value. */ + regcache_cooked_write_unsigned (regcache, regnum, + unpack_long (valtype, writebuf)); + } + if (readbuf != NULL) + { + /* Extract the integer from GPR. Since this is truncating the + value, there isn't a sign extension problem. */ + ULONGEST regval; - if (write_pass) - { - if (vreg <= 13) - regcache_cooked_write (regcache, - tdep->ppc_vr0_regnum + vreg, - elval); + regcache_cooked_read_unsigned (regcache, regnum, ®val); + store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), + gdbarch_byte_order (gdbarch), regval); + } + return 1; + } - write_memory (gparam, elval, 16); - } + /* Floats and doubles go in f1 .. f13. 32-bit floats are converted + to double first. */ + if (TYPE_LENGTH (valtype) <= 8 + && valtype->code () == TYPE_CODE_FLT) + { + int regnum = tdep->ppc_fp0_regnum + 1 + index; + struct type *regtype = register_type (gdbarch, regnum); + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; - greg += 2; - vreg++; - gparam += 16; - } - } - else if (TYPE_LENGTH (type) == 16 && TYPE_VECTOR (type) - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && tdep->vector_abi == POWERPC_VEC_ALTIVEC) - { - /* In the Altivec ABI, vectors go in the vector registers - v2 .. v13, as well as the parameter area -- always at - 16-byte aligned addresses. */ + if (writebuf != NULL) + { + target_float_convert (writebuf, valtype, regval, regtype); + regcache->cooked_write (regnum, regval); + } + if (readbuf != NULL) + { + regcache->cooked_read (regnum, regval); + target_float_convert (regval, regtype, readbuf, valtype); + } + return 1; + } - gparam = align_up (gparam, 16); - greg += greg & 1; + /* Floats and doubles go in f1 .. f13. 32-bit decimal floats are + placed in the least significant word. */ + if (TYPE_LENGTH (valtype) <= 8 + && valtype->code () == TYPE_CODE_DECFLOAT) + { + int regnum = tdep->ppc_fp0_regnum + 1 + index; + int offset = 0; - if (write_pass) - { - if (vreg <= 13) - regcache_cooked_write (regcache, - tdep->ppc_vr0_regnum + vreg, val); + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - TYPE_LENGTH (valtype); - write_memory (gparam, val, TYPE_LENGTH (type)); - } + if (writebuf != NULL) + regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype), + writebuf); + if (readbuf != NULL) + regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype), + readbuf); + return 1; + } - greg += 2; - vreg++; - gparam += 16; - } - else if (TYPE_LENGTH (type) >= 16 && TYPE_VECTOR (type) - && TYPE_CODE (type) == TYPE_CODE_ARRAY) - { - /* Non-Altivec vectors are passed by reference. */ + /* IBM long double stored in two consecutive FPRs. */ + if (TYPE_LENGTH (valtype) == 16 + && valtype->code () == TYPE_CODE_FLT + && (gdbarch_long_double_format (gdbarch) + == floatformats_ibm_long_double)) + { + int regnum = tdep->ppc_fp0_regnum + 1 + 2 * index; - /* Copy value onto the stack ... */ - refparam = align_up (refparam, 16); - if (write_pass) - write_memory (refparam, val, TYPE_LENGTH (type)); + if (writebuf != NULL) + { + regcache->cooked_write (regnum, writebuf); + regcache->cooked_write (regnum + 1, writebuf + 8); + } + if (readbuf != NULL) + { + regcache->cooked_read (regnum, readbuf); + regcache->cooked_read (regnum + 1, readbuf + 8); + } + return 1; + } - /* ... and pass a pointer to the copy as parameter. */ - if (write_pass) - { - if (greg <= 10) - regcache_cooked_write_unsigned (regcache, - tdep->ppc_gp0_regnum + - greg, refparam); - write_memory_unsigned_integer (gparam, tdep->wordsize, - byte_order, refparam); - } - greg++; - gparam = align_up (gparam + tdep->wordsize, tdep->wordsize); - refparam = align_up (refparam + TYPE_LENGTH (type), tdep->wordsize); - } - else if ((TYPE_CODE (type) == TYPE_CODE_INT - || TYPE_CODE (type) == TYPE_CODE_ENUM - || 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 - gpr3 .. gpr10. They can also end up in memory. */ - if (write_pass) - { - /* Sign extend the value, then store it unsigned. */ - ULONGEST word = unpack_long (type, val); - /* Convert any function code addresses into - descriptors. */ - if (TYPE_CODE (type) == TYPE_CODE_PTR - || TYPE_CODE (type) == TYPE_CODE_REF) - { - struct type *target_type; - target_type = check_typedef (TYPE_TARGET_TYPE (type)); + /* 128-bit decimal floating-point values are stored in an even/odd + pair of FPRs, with the even FPR holding the most significant half. */ + if (TYPE_LENGTH (valtype) == 16 + && valtype->code () == TYPE_CODE_DECFLOAT) + { + int regnum = tdep->ppc_fp0_regnum + 2 + 2 * index; + int lopart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 : 0; + int hipart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8; - 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, - byte_order, word); - } - greg++; - gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize); - } - else - { - int byte; - for (byte = 0; byte < TYPE_LENGTH (type); - byte += tdep->wordsize) - { - if (write_pass && greg <= 10) - { - gdb_byte regval[MAX_REGISTER_SIZE]; - int len = TYPE_LENGTH (type) - byte; - if (len > tdep->wordsize) - len = tdep->wordsize; - memset (regval, 0, sizeof regval); - /* The ABI (version 1.9) specifies that values - smaller than one doubleword are right-aligned - and those larger are left-aligned. GCC - versions before 3.4 implemented this - incorrectly; see - . */ - if (byte == 0) - memcpy (regval + tdep->wordsize - len, - val + byte, len); - else - memcpy (regval, val + byte, len); - regcache_cooked_write (regcache, greg, regval); - } - 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. */ - 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 - && TYPE_LENGTH (type) <= 16) - { - /* The ABI (version 1.9) specifies that structs - containing a single floating-point value, at any - level of nesting of single-member structs, are - passed in floating-point registers. */ - while (TYPE_CODE (type) == TYPE_CODE_STRUCT - && TYPE_NFIELDS (type) == 1) - type = check_typedef (TYPE_FIELD_TYPE (type, 0)); - if (TYPE_CODE (type) == TYPE_CODE_FLT) - { - if (TYPE_LENGTH (type) <= 8) - { - if (write_pass) - { - 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); - } - freg++; - } - else if (TYPE_LENGTH (type) == 16 - && (gdbarch_long_double_format (gdbarch) - == floatformats_ibm_long_double)) - { - if (write_pass) - { - 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); - } - freg += 2; - } - } - } - /* Always consume parameter stack space. */ - gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize); - } + if (writebuf != NULL) + { + regcache->cooked_write (regnum, writebuf + hipart); + regcache->cooked_write (regnum + 1, writebuf + lopart); } - - if (!write_pass) + if (readbuf != NULL) { - /* Save the true region sizes ready for the second pass. */ - refparam_size = refparam; - /* Make certain that the general parameter save area is at - least the minimum 8 registers (or doublewords) in size. */ - if (greg < 8) - gparam_size = 8 * tdep->wordsize; - else - gparam_size = gparam; + regcache->cooked_read (regnum, readbuf + hipart); + regcache->cooked_read (regnum + 1, readbuf + lopart); } + return 1; } - /* Update %sp. */ - regcache_cooked_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp); + /* AltiVec vectors are returned in VRs starting at v2. */ + if (TYPE_LENGTH (valtype) == 16 + && valtype->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype) + && tdep->vector_abi == POWERPC_VEC_ALTIVEC) + { + int regnum = tdep->ppc_vr0_regnum + 2 + index; - /* Write the backchain (it occupies WORDSIZED bytes). */ - write_memory_signed_integer (sp, tdep->wordsize, byte_order, back_chain); + if (writebuf != NULL) + regcache->cooked_write (regnum, writebuf); + if (readbuf != NULL) + regcache->cooked_read (regnum, readbuf); + return 1; + } - /* Point the inferior function call's return address at the dummy's - breakpoint. */ - regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr); + /* Short vectors are returned in GPRs starting at r3. */ + if (TYPE_LENGTH (valtype) <= 8 + && valtype->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)) + { + int regnum = tdep->ppc_gp0_regnum + 3 + index; + int offset = 0; - /* Use the func_addr to find the descriptor, and use that to find - the TOC. If we're calling via a function pointer, the pointer - itself identifies the descriptor. */ - { - 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, byte_order); - regcache_cooked_write_unsigned (regcache, - tdep->ppc_gp0_regnum + 2, toc); - } - } + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - TYPE_LENGTH (valtype); - return sp; -} + if (writebuf != NULL) + regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype), + writebuf); + if (readbuf != NULL) + regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype), + readbuf); + return 1; + } + return 0; +} /* The 64 bit ABI return value convention. @@ -1714,260 +1901,173 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, 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 *func_type, +ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, 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); - int opencl_abi = 0; - - if (func_type - && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GDB_IBM_OpenCL) - opencl_abi = 1; + struct type *func_type = function ? value_type (function) : NULL; + int opencl_abi = func_type? ppc_sysv_use_opencl_abi (func_type) : 0; + struct type *eltype; + int nelt, ok; /* This function exists to support a calling convention that requires floating-point registers. It shouldn't be used on processors that lack them. */ gdb_assert (ppc_floating_point_unit_p (gdbarch)); - /* Floats and doubles in F1. */ - if (TYPE_CODE (valtype) == TYPE_CODE_FLT && TYPE_LENGTH (valtype) <= 8) + /* Complex types are returned as if two independent scalars. */ + if (valtype->code () == TYPE_CODE_COMPLEX) { - gdb_byte regval[MAX_REGISTER_SIZE]; - struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum); - if (writebuf != NULL) - { - convert_typed_floating (writebuf, valtype, regval, regtype); - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval); - } - if (readbuf != NULL) + eltype = check_typedef (TYPE_TARGET_TYPE (valtype)); + + for (int i = 0; i < 2; i++) { - regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval); - convert_typed_floating (regval, regtype, readbuf, valtype); + ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache, + readbuf, writebuf, i); + gdb_assert (ok); + + if (readbuf) + readbuf += TYPE_LENGTH (eltype); + if (writebuf) + writebuf += TYPE_LENGTH (eltype); } 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_CHAR - || TYPE_CODE (valtype) == TYPE_CODE_BOOL) - && TYPE_LENGTH (valtype) <= 8) + + /* OpenCL vectors shorter than 16 bytes are returned as if + a series of independent scalars; OpenCL vectors 16 bytes + or longer are returned as if a series of AltiVec vectors. */ + if (valtype->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype) + && opencl_abi) { - if (writebuf != NULL) - { - /* Be careful to sign extend the value. */ - regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3, - unpack_long (valtype, writebuf)); - } - if (readbuf != NULL) + if (TYPE_LENGTH (valtype) < 16) + eltype = check_typedef (TYPE_TARGET_TYPE (valtype)); + else + eltype = register_type (gdbarch, tdep->ppc_vr0_regnum); + + nelt = TYPE_LENGTH (valtype) / TYPE_LENGTH (eltype); + for (int i = 0; i < nelt; i++) { - /* Extract the integer from r3. Since this is truncating the - value, there isn't a sign extension problem. */ - ULONGEST regval; - regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3, - ®val); - store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order, - regval); + ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache, + readbuf, writebuf, i); + gdb_assert (ok); + + if (readbuf) + readbuf += TYPE_LENGTH (eltype); + if (writebuf) + writebuf += TYPE_LENGTH (eltype); } return RETURN_VALUE_REGISTER_CONVENTION; } + /* All pointers live in r3. */ - if (TYPE_CODE (valtype) == TYPE_CODE_PTR - || TYPE_CODE (valtype) == TYPE_CODE_REF) + if (valtype->code () == TYPE_CODE_PTR || TYPE_IS_REFERENCE (valtype)) { - /* All pointers live in r3. */ + int regnum = tdep->ppc_gp0_regnum + 3; + if (writebuf != NULL) - regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf); + regcache->cooked_write (regnum, writebuf); if (readbuf != NULL) - regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf); + regcache->cooked_read (regnum, readbuf); return RETURN_VALUE_REGISTER_CONVENTION; } - /* OpenCL vectors < 16 bytes are returned as distinct - scalars in f1..f2 or r3..r10. */ - if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY - && TYPE_VECTOR (valtype) - && TYPE_LENGTH (valtype) < 16 - && opencl_abi) - { - struct type *eltype = check_typedef (TYPE_TARGET_TYPE (valtype)); - int i, nelt = TYPE_LENGTH (valtype) / TYPE_LENGTH (eltype); - - for (i = 0; i < nelt; i++) - { - int offset = i * TYPE_LENGTH (eltype); - - if (TYPE_CODE (eltype) == TYPE_CODE_FLT) - { - int regnum = tdep->ppc_fp0_regnum + 1 + i; - gdb_byte regval[MAX_REGISTER_SIZE]; - struct type *regtype = register_type (gdbarch, regnum); - if (writebuf != NULL) - { - convert_typed_floating (writebuf + offset, eltype, - regval, regtype); - regcache_cooked_write (regcache, regnum, regval); - } - if (readbuf != NULL) - { - regcache_cooked_read (regcache, regnum, regval); - convert_typed_floating (regval, regtype, - readbuf + offset, eltype); - } - } - else - { - int regnum = tdep->ppc_gp0_regnum + 3 + i; - ULONGEST regval; - - if (writebuf != NULL) - { - regval = unpack_long (eltype, writebuf + offset); - regcache_cooked_write_unsigned (regcache, regnum, regval); - } - if (readbuf != NULL) - { - regcache_cooked_read_unsigned (regcache, regnum, ®val); - store_unsigned_integer (readbuf + offset, - TYPE_LENGTH (eltype), byte_order, - regval); - } - } - } - - return RETURN_VALUE_REGISTER_CONVENTION; - } - /* OpenCL vectors >= 16 bytes are returned in v2..v9. */ - if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY - && TYPE_VECTOR (valtype) - && TYPE_LENGTH (valtype) >= 16 - && opencl_abi) + /* Small character arrays are returned, right justified, in r3. */ + if (valtype->code () == TYPE_CODE_ARRAY + && !TYPE_VECTOR (valtype) + && TYPE_LENGTH (valtype) <= 8 + && TYPE_TARGET_TYPE (valtype)->code () == TYPE_CODE_INT + && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1) { - int n_regs = TYPE_LENGTH (valtype) / 16; - int i; - - for (i = 0; i < n_regs; i++) - { - int offset = i * 16; - int regnum = tdep->ppc_vr0_regnum + 2 + i; - - if (writebuf != NULL) - regcache_cooked_write (regcache, regnum, writebuf + offset); - if (readbuf != NULL) - regcache_cooked_read (regcache, regnum, readbuf + offset); - } + int regnum = tdep->ppc_gp0_regnum + 3; + int offset = (register_size (gdbarch, regnum) - TYPE_LENGTH (valtype)); + if (writebuf != NULL) + regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype), + writebuf); + if (readbuf != NULL) + regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype), + readbuf); return RETURN_VALUE_REGISTER_CONVENTION; } - /* Array type has more than one use. */ - if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY) - { - /* Small character arrays are returned, right justified, in r3. */ - if (TYPE_LENGTH (valtype) <= 8 - && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT - && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1) - { - int offset = (register_size (gdbarch, tdep->ppc_gp0_regnum + 3) - - TYPE_LENGTH (valtype)); - if (writebuf != NULL) - regcache_cooked_write_part (regcache, tdep->ppc_gp0_regnum + 3, - offset, TYPE_LENGTH (valtype), writebuf); - if (readbuf != NULL) - regcache_cooked_read_part (regcache, tdep->ppc_gp0_regnum + 3, - offset, TYPE_LENGTH (valtype), readbuf); - return RETURN_VALUE_REGISTER_CONVENTION; - } - /* A VMX vector is returned in v2. */ - if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY - && TYPE_VECTOR (valtype) - && tdep->vector_abi == POWERPC_VEC_ALTIVEC) - { - if (readbuf) - regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf); - if (writebuf) - regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, - writebuf); - return RETURN_VALUE_REGISTER_CONVENTION; - } - } - /* Big floating point values get stored in adjacent floating - point registers, starting with F1. */ - if (TYPE_CODE (valtype) == TYPE_CODE_FLT - && (TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 32)) + + /* In the ELFv2 ABI, homogeneous floating-point or vector + aggregates are returned in registers. */ + if (tdep->elf_abi == POWERPC_ELF_V2 + && ppc64_elfv2_abi_homogeneous_aggregate (valtype, &eltype, &nelt) + && (eltype->code () == TYPE_CODE_FLT + || eltype->code () == TYPE_CODE_DECFLOAT + || (eltype->code () == TYPE_CODE_ARRAY + && TYPE_VECTOR (eltype) + && tdep->vector_abi == POWERPC_VEC_ALTIVEC + && TYPE_LENGTH (eltype) == 16))) { - if (writebuf || readbuf != NULL) + for (int i = 0; i < nelt; i++) { - int i; - for (i = 0; i < TYPE_LENGTH (valtype) / 8; i++) - { - if (writebuf != NULL) - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i, - (const bfd_byte *) writebuf + i * 8); - if (readbuf != NULL) - regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i, - (bfd_byte *) readbuf + i * 8); - } + ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache, + readbuf, writebuf, i); + gdb_assert (ok); + + if (readbuf) + readbuf += TYPE_LENGTH (eltype); + if (writebuf) + writebuf += TYPE_LENGTH (eltype); } + return RETURN_VALUE_REGISTER_CONVENTION; } - /* Complex values get returned in f1:f2, need to convert. */ - if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX - && (TYPE_LENGTH (valtype) == 8 || TYPE_LENGTH (valtype) == 16)) + + /* In the ELFv2 ABI, aggregate types of up to 16 bytes are + returned in registers r3:r4. */ + if (tdep->elf_abi == POWERPC_ELF_V2 + && TYPE_LENGTH (valtype) <= 16 + && (valtype->code () == TYPE_CODE_STRUCT + || valtype->code () == TYPE_CODE_UNION + || (valtype->code () == TYPE_CODE_ARRAY + && !TYPE_VECTOR (valtype)))) { - if (regcache != NULL) + int n_regs = ((TYPE_LENGTH (valtype) + tdep->wordsize - 1) + / tdep->wordsize); + + for (int i = 0; i < n_regs; i++) { - int i; - for (i = 0; i < 2; i++) + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; + int regnum = tdep->ppc_gp0_regnum + 3 + i; + int offset = i * tdep->wordsize; + int len = TYPE_LENGTH (valtype) - offset; + + if (len > tdep->wordsize) + len = tdep->wordsize; + + if (writebuf != NULL) { - gdb_byte regval[MAX_REGISTER_SIZE]; - struct type *regtype = - register_type (gdbarch, tdep->ppc_fp0_regnum); - if (writebuf != NULL) - { - convert_typed_floating ((const bfd_byte *) writebuf + - i * (TYPE_LENGTH (valtype) / 2), - valtype, regval, regtype); - regcache_cooked_write (regcache, - tdep->ppc_fp0_regnum + 1 + i, - regval); - } - if (readbuf != NULL) - { - regcache_cooked_read (regcache, - tdep->ppc_fp0_regnum + 1 + i, - regval); - convert_typed_floating (regval, regtype, - (bfd_byte *) readbuf + - i * (TYPE_LENGTH (valtype) / 2), - valtype); - } + memset (regval, 0, sizeof regval); + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG + && offset == 0) + memcpy (regval + tdep->wordsize - len, writebuf, len); + else + memcpy (regval, writebuf + offset, len); + regcache->cooked_write (regnum, regval); } - } - return RETURN_VALUE_REGISTER_CONVENTION; - } - /* Big complex values get stored in f1:f4. */ - if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX && TYPE_LENGTH (valtype) == 32) - { - if (regcache != NULL) - { - int i; - for (i = 0; i < 4; i++) + if (readbuf != NULL) { - if (writebuf != NULL) - regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i, - (const bfd_byte *) writebuf + i * 8); - if (readbuf != NULL) - regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i, - (bfd_byte *) readbuf + i * 8); + regcache->cooked_read (regnum, regval); + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG + && offset == 0) + memcpy (readbuf, regval + tdep->wordsize - len, len); + else + memcpy (readbuf + offset, regval, len); } } return RETURN_VALUE_REGISTER_CONVENTION; } + + /* Handle plain base types. */ + if (ppc64_sysv_abi_return_value_base (gdbarch, valtype, regcache, + readbuf, writebuf, 0)) + return RETURN_VALUE_REGISTER_CONVENTION; + return RETURN_VALUE_STRUCT_CONVENTION; }