X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fppc-sysv-tdep.c;h=fb8c9e2fe01f52379587ae567f7d0ac060046f8d;hb=9f71dacbc30de66a7eb693d4deca935514b682bd;hp=23d7a71021434b26dd5c6bfb33a920d86120ffd4;hpb=0df8b4180acb4890d058c92753dafcd4ff0a87d1;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 23d7a71021..fb8c9e2fe0 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-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -24,12 +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 (TYPE_CODE (ftype) == TYPE_CODE_PTR) + ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); + + return (TYPE_CODE (ftype) == 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 @@ -39,17 +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); + 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; @@ -90,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, @@ -118,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++; } @@ -159,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; } @@ -204,12 +218,10 @@ 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; } @@ -236,18 +248,14 @@ 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; } @@ -262,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 @@ -275,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++; @@ -305,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 @@ -327,6 +333,122 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, Hence we increase freg even when writing to memory. */ freg += 2; } + else if (len < 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 && !tdep->soft_float) + { + if (freg <= 8) + { + if (write_pass) + { + int regnum = tdep->ppc_fp0_regnum + freg; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; + struct type *regtype + = register_type (gdbarch, regnum); + target_float_convert (elval, eltype, + regval, regtype); + regcache->cooked_write (regnum, regval); + } + freg++; + } + else + { + argoffset = align_up (argoffset, len); + if (write_pass) + write_memory (sp + argoffset, val, len); + argoffset += len; + } + } + else if (TYPE_LENGTH (eltype) == 8) + { + if (greg > 9) + { + /* Just in case GREG was 10. */ + greg = 11; + argoffset = align_up (argoffset, 8); + if (write_pass) + write_memory (sp + argoffset, elval, + TYPE_LENGTH (eltype)); + argoffset += 8; + } + else + { + /* Must start on an odd register - r3/r4 etc. */ + if ((greg & 1) == 0) + greg++; + if (write_pass) + { + int regnum = tdep->ppc_gp0_regnum + greg; + regcache->cooked_write (regnum + 0, elval + 0); + regcache->cooked_write (regnum + 1, elval + 4); + } + greg += 2; + } + } + else + { + 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 (tdep->ppc_gp0_regnum + greg, + word); + greg++; + } + else + { + argoffset = align_up (argoffset, tdep->wordsize); + if (write_pass) + write_memory (sp + argoffset, word, tdep->wordsize); + argoffset += tdep->wordsize; + } + } + } + } + else if (len >= 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; + + for (i = 0; i < len / 16; i++) + { + const gdb_byte *elval = val + i * 16; + + if (vreg <= 13) + { + if (write_pass) + regcache->cooked_write (tdep->ppc_vr0_regnum + vreg, + elval); + vreg++; + } + else + { + argoffset = align_up (argoffset, 16); + if (write_pass) + write_memory (sp + argoffset, elval, 16); + argoffset += 16; + } + } + } else if (len == 16 && TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) @@ -337,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 @@ -364,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 @@ -380,8 +500,8 @@ 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) @@ -415,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 @@ -472,9 +591,8 @@ 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) @@ -488,7 +606,7 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype, { 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. */ @@ -500,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) @@ -521,17 +639,17 @@ 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); } } } else /* Can't happen. */ - internal_error (__FILE__, __LINE__, "Unknown decimal float size."); + internal_error (__FILE__, __LINE__, _("Unknown decimal float size.")); return RETURN_VALUE_REGISTER_CONVENTION; } @@ -552,13 +670,17 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype, when returned in general-purpose registers. */ static enum return_value_convention -do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf, int broken_gcc) +do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf, + int broken_gcc) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + 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 && TYPE_LENGTH (type) <= 8 && !tdep->soft_float) @@ -567,20 +689,20 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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; } @@ -593,15 +715,13 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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; } @@ -615,23 +735,17 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, 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; } @@ -644,19 +758,15 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, { /* 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; } @@ -667,7 +777,7 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, || 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_IS_REFERENCE (type) || TYPE_CODE (type) == TYPE_CODE_ENUM) && TYPE_LENGTH (type) <= tdep->wordsize) { @@ -691,6 +801,83 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, } return RETURN_VALUE_REGISTER_CONVENTION; } + /* OpenCL vectors < 16 bytes are returned as distinct + scalars in f1..f2 or r3..r10. */ + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && TYPE_VECTOR (type) + && TYPE_LENGTH (type) < 16 + && opencl_abi) + { + struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); + int i, nelt = TYPE_LENGTH (type) / 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[PPC_MAX_REGISTER_SIZE]; + struct type *regtype = register_type (gdbarch, regnum); + + if (writebuf != NULL) + { + target_float_convert (writebuf + offset, eltype, + regval, regtype); + regcache->cooked_write (regnum, regval); + } + if (readbuf != NULL) + { + regcache->cooked_read (regnum, regval); + target_float_convert (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 (type) == TYPE_CODE_ARRAY + && TYPE_VECTOR (type) + && TYPE_LENGTH (type) >= 16 + && opencl_abi) + { + int n_regs = TYPE_LENGTH (type) / 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 (regnum, writebuf + offset); + if (readbuf != NULL) + regcache->cooked_read (regnum, readbuf + offset); + } + + return RETURN_VALUE_REGISTER_CONVENTION; + } if (TYPE_LENGTH (type) == 16 && TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) @@ -699,12 +886,12 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, 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; } @@ -718,25 +905,17 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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; } @@ -751,9 +930,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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) @@ -761,28 +940,28 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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; @@ -794,12 +973,12 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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) @@ -807,14 +986,14 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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; } @@ -822,23 +1001,25 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *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, 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, 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 @@ -856,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. */ @@ -873,448 +1054,635 @@ 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; } -/* Pass the arguments 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. */ +/* 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. */ -CORE_ADDR -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) +static LONGEST +ppc64_aggregate_candidate (struct type *type, + struct type **field_type) { - 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); - ULONGEST back_chain; - /* See for-loop comment below. */ - int write_pass; - /* Size of the Altivec's vector parameter region, the final value is - computed in the for-loop below. */ - LONGEST vparam_size = 0; - /* Size of the general parameter region, the final value is computed - in the for-loop below. */ - LONGEST gparam_size = 0; - /* Kevin writes ... I don't mind seeing tdep->wordsize used in the - calls to align_up(), align_down(), etc. because this makes it - easier to reuse this code (in a copy/paste sense) in the future, - but it is a 64-bit ABI and asserting that the wordsize is 8 bytes - at some point makes it easier to verify that this function is - correct without having to do a non-local analysis to figure out - the possible values of tdep->wordsize. */ - gdb_assert (tdep->wordsize == 8); - - /* 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)); - - /* By this stage in the proceedings, SP has been decremented by "red - zone size" + "struct return size". Fetch the stack-pointer from - before this and use that as the BACK_CHAIN. */ - regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch), - &back_chain); - - /* Go through the argument list twice. - - Pass 1: Compute the function call's stack space and register - requirements. - - Pass 2: Replay the same computation but this time also write the - values out to the target. */ + type = check_typedef (type); - for (write_pass = 0; write_pass < 2; write_pass++) + switch (TYPE_CODE (type)) { - 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, ...) should be saved. */ - CORE_ADDR gparam; - /* Address, at which the next Altivec vector parameter should be - saved. */ - CORE_ADDR vparam; + case TYPE_CODE_FLT: + case TYPE_CODE_DECFLOAT: + if (!*field_type) + *field_type = type; + if (TYPE_CODE (*field_type) == TYPE_CODE (type) + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 1; + break; + + case TYPE_CODE_COMPLEX: + type = TYPE_TARGET_TYPE (type); + if (TYPE_CODE (type) == TYPE_CODE_FLT + || TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + { + if (!*field_type) + *field_type = type; + if (TYPE_CODE (*field_type) == TYPE_CODE (type) + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 2; + } + break; - if (!write_pass) + case TYPE_CODE_ARRAY: + if (TYPE_VECTOR (type)) { - /* During the first pass, GPARAM and VPARAM are more like - offsets (start address zero) than addresses. That way - they accumulate the total stack space each region - requires. */ - gparam = 0; - vparam = 0; + if (!*field_type) + *field_type = type; + if (TYPE_CODE (*field_type) == TYPE_CODE (type) + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 1; } else { - /* Decrement the stack pointer making space for the Altivec - and general on-stack parameters. Set vparam and gparam - to their corresponding regions. */ - vparam = align_down (sp - vparam_size, 16); - gparam = align_down (vparam - 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); - } + LONGEST count, low_bound, high_bound; - /* If the function is returning a `struct', then there is an - extra hidden parameter (which will be passed in r3) - 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); + 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; - for (argno = 0; argno < nargs; argno++) + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: { - struct value *arg = args[argno]; - struct type *type = check_typedef (value_type (arg)); - const bfd_byte *val = value_contents (arg); + LONGEST count = 0; + int i; - if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8) + for (i = 0; i < TYPE_NFIELDS (type); i++) { - /* 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; + LONGEST sub_count; - /* Version 1.7 of the 64-bit PowerPC ELF ABI says: + if (field_is_static (&TYPE_FIELD (type, i))) + continue; - "Single precision floating point values are mapped to - the first word in a single doubleword." + sub_count = ppc64_aggregate_candidate + (TYPE_FIELD_TYPE (type, i), field_type); + if (sub_count == -1) + return -1; - And version 1.9 says: + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + count += sub_count; + else + count = std::max (count, sub_count); + } - "Single precision floating point values are mapped to - the second word in a single doubleword." + /* 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; - 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; + return count; + } + break; - /* Write value in the stack's parameter save area. */ - write_memory (gparam, p, 8); + default: + break; + } - if (freg <= 13) - { - struct type *regtype - = register_type (gdbarch, tdep->ppc_fp0_regnum); + return -1; +} - 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); - } +/* 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. */ - 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)) +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) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION + || (TYPE_CODE (type) == 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 = ((TYPE_CODE (field_type) == TYPE_CODE_FLT + || TYPE_CODE (field_type) == 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) { - /* 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); + 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; } - 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; + return 0; +} - /* Write value in the stack's parameter save area. */ - write_memory (gparam, p, 8); +/* 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; - if (freg <= 13) - regcache_cooked_write (regcache, - tdep->ppc_fp0_regnum + freg, p); - } + /* Enforce alignment of stack location, if requested. */ + if (align > tdep->wordsize) + { + CORE_ADDR aligned_gparam = align_up (argpos->gparam, align); - 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); - } + argpos->greg += (aligned_gparam - argpos->gparam) / tdep->wordsize; + argpos->gparam = aligned_gparam; + } - write_memory (gparam, val, TYPE_LENGTH (type)); - } + /* 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; - freg += 2; - greg += 2; - gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize); - } - else if (TYPE_LENGTH (type) == 16 && TYPE_VECTOR (type) - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && tdep->ppc_vr0_regnum >= 0) - { - /* In the Altivec ABI, vectors go in the vector - registers v2 .. v13, or when that runs out, a vector - annex which goes above all the normal parameters. - NOTE: cagney/2003-09-21: This is a guess based on the - PowerOpen Altivec ABI. */ - if (vreg <= 13) - { - if (write_pass) - regcache_cooked_write (regcache, - tdep->ppc_vr0_regnum + vreg, val); - vreg++; - } - else + 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) == 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) == 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) == 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) == 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) == TYPE_CODE_FLT + || TYPE_CODE (type) == 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) == 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) == 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) == 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_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) == TYPE_CODE_PTR + || TYPE_CODE (type) == TYPE_CODE_REF)) + { + struct type *target_type + = check_typedef (TYPE_TARGET_TYPE (type)); + + if (TYPE_CODE (target_type) == TYPE_CODE_FUNC + || TYPE_CODE (target_type) == TYPE_CODE_METHOD) { - if (write_pass) - write_memory (vparam, val, TYPE_LENGTH (type)); - vparam = align_up (vparam + TYPE_LENGTH (type), 16); + CORE_ADDR desc = word; + + convert_code_addr_to_desc_addr (word, &desc); + word = desc; } } - 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) + } + + 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) == TYPE_CODE_STRUCT + && TYPE_NFIELDS (type) == 1) + { + 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) + 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 (TYPE_CODE (eltype) == TYPE_CODE_FLT + || TYPE_CODE (eltype) == TYPE_CODE_DECFLOAT) + ppc64_sysv_abi_push_freg (gdbarch, eltype, elval, argpos); + else if (TYPE_CODE (eltype) == 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. + + 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. */ + +CORE_ADDR +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, + 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); + int opencl_abi = ppc_sysv_use_opencl_abi (value_type (function)); + ULONGEST back_chain; + /* See for-loop comment below. */ + int write_pass; + /* Size of the by-reference parameter copy region, the final value is + computed in the for-loop below. */ + LONGEST refparam_size = 0; + /* Size of the general parameter region, the final value is computed + in the for-loop below. */ + LONGEST gparam_size = 0; + /* Kevin writes ... I don't mind seeing tdep->wordsize used in the + calls to align_up(), align_down(), etc. because this makes it + easier to reuse this code (in a copy/paste sense) in the future, + but it is a 64-bit ABI and asserting that the wordsize is 8 bytes + at some point makes it easier to verify that this function is + correct without having to do a non-local analysis to figure out + the possible values of tdep->wordsize. */ + gdb_assert (tdep->wordsize == 8); + + /* 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)); + + /* By this stage in the proceedings, SP has been decremented by "red + zone size" + "struct return size". Fetch the stack-pointer from + before this and use that as the BACK_CHAIN. */ + regcache_cooked_read_unsigned (regcache, gdbarch_sp_regnum (gdbarch), + &back_chain); + + /* Go through the argument list twice. + + Pass 1: Compute the function call's stack space and register + requirements. + + Pass 2: Replay the same computation but this time also write the + values out to the target. */ + + for (write_pass = 0; write_pass < 2; write_pass++) + { + int argno; + + struct ppc64_sysv_argpos argpos; + argpos.greg = 3; + argpos.freg = 1; + argpos.vreg = 2; + + if (!write_pass) + { + /* During the first pass, GPARAM and REFPARAM are more like + offsets (start address zero) than addresses. That way + they accumulate the total stack space each region + requires. */ + 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. */ + 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 + extra hidden parameter (which will be passed in r3) + 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 (return_method == return_method_struct) + ppc64_sysv_abi_push_integer (gdbarch, struct_addr, &argpos); + + for (argno = 0; argno < nargs; argno++) + { + struct value *arg = args[argno]; + struct type *type = check_typedef (value_type (arg)); + const bfd_byte *val = value_contents (arg); + + if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) { - /* Scalars and Pointers get sign[un]extended and go in - gpr3 .. gpr10. They can also end up in memory. */ - if (write_pass) + /* Complex types are passed as if two independent scalars. */ + struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); + + 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) == 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; + + if (TYPE_LENGTH (type) < 16) + eltype = check_typedef (TYPE_TARGET_TYPE (type)); + else + eltype = register_type (gdbarch, tdep->ppc_vr0_regnum); + + nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype); + for (i = 0; i < nelt; i++) { - /* 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)); + const gdb_byte *elval = val + i * TYPE_LENGTH (eltype); - 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); + ppc64_sysv_abi_push_param (gdbarch, eltype, elval, &argpos); } - 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); + /* All other types are passed as single arguments. */ + ppc64_sysv_abi_push_param (gdbarch, type, val, &argpos); } } if (!write_pass) { /* Save the true region sizes ready for the second pass. */ - vparam_size = vparam; + refparam_size = argpos.refparam; /* Make certain that the general parameter save area is at least the minimum 8 registers (or doublewords) in size. */ - if (greg < 8) + if (argpos.greg < 8) gparam_size = 8 * tdep->wordsize; else - gparam_size = gparam; + gparam_size = argpos.gparam; } } @@ -1328,28 +1696,199 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, breakpoint. */ regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr); - /* 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); - } - } + /* 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); + + 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); + } + } + + /* 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); return sp; } +/* Subroutine of ppc64_sysv_abi_return_value that handles "base" types: + integer, floating-point, and AltiVec vector types. + + This routine also handles components of aggregate return types; + INDEX describes which part of the aggregate is to be handled. + + 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); + + /* Integers live in GPRs starting at 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) + { + int regnum = tdep->ppc_gp0_regnum + 3 + index; + + 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; + + regcache_cooked_read_unsigned (regcache, regnum, ®val); + store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), + gdbarch_byte_order (gdbarch), regval); + } + return 1; + } + + /* Floats and doubles go in f1 .. f13. 32-bit floats are converted + to double first. */ + if (TYPE_LENGTH (valtype) <= 8 + && TYPE_CODE (valtype) == 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]; + + 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; + } + + /* Floats and doubles go in f1 .. f13. 32-bit decimal floats are + placed in the least significant word. */ + if (TYPE_LENGTH (valtype) <= 8 + && TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT) + { + int regnum = tdep->ppc_fp0_regnum + 1 + index; + int offset = 0; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - 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 1; + } + + /* IBM long double stored in two consecutive FPRs. */ + if (TYPE_LENGTH (valtype) == 16 + && TYPE_CODE (valtype) == TYPE_CODE_FLT + && (gdbarch_long_double_format (gdbarch) + == floatformats_ibm_long_double)) + { + int regnum = tdep->ppc_fp0_regnum + 1 + 2 * index; + + 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; + } + + /* 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 + && TYPE_CODE (valtype) == 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 (writebuf != NULL) + { + regcache->cooked_write (regnum, writebuf + hipart); + regcache->cooked_write (regnum + 1, writebuf + lopart); + } + if (readbuf != NULL) + { + regcache->cooked_read (regnum, readbuf + hipart); + regcache->cooked_read (regnum + 1, readbuf + lopart); + } + return 1; + } + + /* AltiVec vectors are returned in VRs starting at v2. */ + if (TYPE_LENGTH (valtype) == 16 + && TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype) + && tdep->vector_abi == POWERPC_VEC_ALTIVEC) + { + int regnum = tdep->ppc_vr0_regnum + 2 + index; + + if (writebuf != NULL) + regcache->cooked_write (regnum, writebuf); + if (readbuf != NULL) + regcache->cooked_read (regnum, readbuf); + return 1; + } + + /* Short vectors are returned in GPRs starting at r3. */ + if (TYPE_LENGTH (valtype) <= 8 + && TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)) + { + int regnum = tdep->ppc_gp0_regnum + 3 + index; + int offset = 0; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - 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 1; + } + + return 0; +} /* The 64 bit ABI return value convention. @@ -1362,177 +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); + 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 (TYPE_CODE (valtype) == 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 (TYPE_CODE (valtype) == 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 (TYPE_CODE (valtype) == 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; } - /* 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_CODE (valtype) == TYPE_CODE_ARRAY + && !TYPE_VECTOR (valtype) + && TYPE_LENGTH (valtype) <= 8 + && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT + && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1) { - /* 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->ppc_vr0_regnum >= 0) - { - 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; - } + 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; } - /* 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) + && (TYPE_CODE (eltype) == TYPE_CODE_FLT + || TYPE_CODE (eltype) == TYPE_CODE_DECFLOAT + || (TYPE_CODE (eltype) == 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 + && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION + || (TYPE_CODE (valtype) == 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; }