X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fppc-sysv-tdep.c;h=9a3b02f028d360cf99c974026df2e646541fd1b3;hb=ea764154c27a11619ba764a4c92f395ba5007234;hp=77a71bc987a09afa50362a4e276e273d402b381e;hpb=e765b44c3853ed228506fc22c276becd63198238;p=binutils-gdb.git diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 77a71bc987a..9a3b02f028d 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for PowerPC systems using the SVR4 ABI for GDB, the GNU debugger. - Copyright (C) 2000-2014 Free Software Foundation, Inc. + Copyright (C) 2000-2022 Free Software Foundation, Inc. This file is part of GDB. @@ -23,13 +23,13 @@ #include "inferior.h" #include "regcache.h" #include "value.h" -#include -#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 @@ -40,10 +40,10 @@ ppc_sysv_use_opencl_abi (struct type *ftype) { ftype = check_typedef (ftype); - if (TYPE_CODE (ftype) == TYPE_CODE_PTR) + if (ftype->code () == TYPE_CODE_PTR) ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); - return (TYPE_CODE (ftype) == TYPE_CODE_FUNC + return (ftype->code () == TYPE_CODE_FUNC && TYPE_CALLING_CONVENTION (ftype) == DW_CC_GDB_IBM_OpenCL); } @@ -55,16 +55,17 @@ ppc_sysv_use_opencl_abi (struct type *ftype) 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_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; @@ -91,10 +92,10 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { int argno; /* Next available floating point register for float and double - arguments. */ + arguments. */ int freg = 1; /* Next available general register for non-float, non-vector - arguments. */ + arguments. */ int greg = 3; /* Next available vector register for vector arguments. */ int vreg = 2; @@ -104,10 +105,10 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, int structoffset = argoffset + argspace; /* If the function is returning a `struct', then the first word - (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) + (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 (return_method == return_method_struct) { if (write_pass) regcache_cooked_write_signed (regcache, @@ -121,27 +122,26 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct value *arg = args[argno]; struct type *type = check_typedef (value_type (arg)); int len = TYPE_LENGTH (type); - const bfd_byte *val = value_contents (arg); + const bfd_byte *val = value_contents (arg).data (); - 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 - passed in an FP register, when the registers run out, - 8 byte aligned stack is used. */ + passed in an FP register, when the registers run out, + 8 byte aligned stack is used. */ if (freg <= 8) { if (write_pass) { /* Always store the floating point value using - the register's floating-point format. */ - gdb_byte regval[MAX_REGISTER_SIZE]; + the register's floating-point format. */ + 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++; } @@ -164,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) @@ -176,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; } @@ -194,17 +191,17 @@ 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" - passed in an odd/even register pair with the low - addressed word in the odd register and the high - addressed word in the even register, or when the - registers run out an 8 byte aligned stack - location. */ + passed in an odd/even register pair with the low + addressed word in the odd register and the high + addressed word in the even register, or when the + registers run out an 8 byte aligned stack + location. */ if (greg > 9) { /* Just in case GREG was 10. */ @@ -221,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 @@ -253,47 +248,42 @@ 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 - end up in memory. */ + end up in memory. */ if (freg <= 8) { 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 doubleword. */ if (TYPE_LENGTH (type) == 4) - { - memcpy (regval + 4, val, 4); - p = regval; - } + { + memcpy (regval + 4, val, 4); + p = regval; + } else p = val; - regcache_cooked_write (regcache, - tdep->ppc_fp0_regnum + freg, p); + regcache->cooked_write (tdep->ppc_fp0_regnum + freg, p); } freg++; @@ -309,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 @@ -322,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 @@ -339,14 +328,14 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } /* If a 128-bit decimal float goes to the stack because only f7 - and f8 are free (thus there's no even/odd register pair + and f8 are free (thus there's no even/odd register pair available), these registers should be marked as occupied. Hence we increase freg even when writing to memory. */ freg += 2; } else if (len < 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type) + && type->code () == TYPE_CODE_ARRAY + && type->is_vector () && opencl_abi) { /* OpenCL vectors shorter than 16 bytes are passed as if @@ -358,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++; } @@ -402,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 @@ -435,8 +421,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } } else if (len >= 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type) + && type->code () == TYPE_CODE_ARRAY + && type->is_vector () && opencl_abi) { /* OpenCL vectors 16 bytes or longer are passed as if @@ -450,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 @@ -465,17 +450,16 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } } else if (len == 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type) + && type->code () == TYPE_CODE_ARRAY + && type->is_vector () && tdep->vector_abi == POWERPC_VEC_ALTIVEC) { /* Vector parameter passed in an Altivec register, or - when that runs out, 16 byte aligned stack location. */ + when that runs out, 16 byte aligned stack location. */ 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 @@ -487,22 +471,21 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } } else if (len == 8 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type) + && type->code () == TYPE_CODE_ARRAY + && type->is_vector () && tdep->vector_abi == POWERPC_VEC_SPE) { /* Vector parameter passed in an e500 register, or when - that runs out, 8 byte aligned stack location. Note - that since e500 vector and general purpose registers - both map onto the same underlying register set, a - "greg" and not a "vreg" is consumed here. A cooked - write stores the value in the correct locations - within the raw register cache. */ + that runs out, 8 byte aligned stack location. Note + that since e500 vector and general purpose registers + both map onto the same underlying register set, a + "greg" and not a "vreg" is consumed here. A cooked + write stores the value in the correct locations + within the raw register cache. */ 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 @@ -516,17 +499,17 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, else { /* Reduce the parameter down to something that fits in a - "word". */ - gdb_byte word[MAX_REGISTER_SIZE]; - memset (word, 0, MAX_REGISTER_SIZE); + "word". */ + 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 - && TYPE_VECTOR (type) + if (type->code () == TYPE_CODE_ARRAY + && type->is_vector () && len >= 16) structoffset = align_up (structoffset, 16); else @@ -540,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)); @@ -548,12 +531,11 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Always goes in the low address. */ memcpy (word, val, len); /* Store that "word" in a register, or on the stack. - The words have "4" byte alignment. */ + The words have "4" byte alignment. */ 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 @@ -610,21 +592,21 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } /* Handle the return-value conventions for Decimal Floating Point values. */ -static int +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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_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. */ @@ -636,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) @@ -657,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); } } } @@ -693,13 +675,13 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, gdb_byte *readbuf, const gdb_byte *writebuf, int broken_gcc) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_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 + if (type->code () == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8 && !tdep->soft_float) { @@ -707,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); + tdep->ppc_fp0_regnum + 1); + 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) @@ -733,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) @@ -833,8 +803,8 @@ 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 - && TYPE_VECTOR (type) + if (type->code () == TYPE_CODE_ARRAY + && type->is_vector () && TYPE_LENGTH (type) < 16 && opencl_abi) { @@ -845,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 @@ -887,8 +857,8 @@ 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 - && TYPE_VECTOR (type) + if (type->code () == TYPE_CODE_ARRAY + && type->is_vector () && TYPE_LENGTH (type) >= 16 && opencl_abi) { @@ -901,33 +871,33 @@ 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_VECTOR (type) + && type->code () == TYPE_CODE_ARRAY + && type->is_vector () && 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_VECTOR (type) + && type->code () == TYPE_CODE_ARRAY + && type->is_vector () && tdep->vector_abi == POWERPC_VEC_GENERIC) { /* GCC -maltivec -mabi=no-altivec returns vectors in r3/r4/r5/r6. @@ -935,31 +905,23 @@ 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_VECTOR (type) + && type->code () == TYPE_CODE_ARRAY + && type->is_vector () && tdep->vector_abi == POWERPC_VEC_SPE) { /* The e500 ABI places return values for the 64-bit DSP types @@ -968,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) @@ -978,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; @@ -1011,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) @@ -1024,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; } @@ -1076,12 +1038,12 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr) { struct obj_section *dot_fn_section; struct bound_minimal_symbol dot_fn; - struct minimal_symbol *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.minsym == NULL || SYMBOL_LINKAGE_NAME (dot_fn.minsym)[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. */ @@ -1092,15 +1054,169 @@ 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.minsym) + 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->is_vector ()) + { + 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->is_vector ())) + { + 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 { @@ -1134,7 +1250,7 @@ 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); int offset = 0; /* Enforce alignment of stack location, if requested. */ @@ -1150,7 +1266,8 @@ ppc64_sysv_abi_push_val (struct gdbarch *gdbarch, doubleword are right-aligned and those larger are left-aligned. GCC versions before 3.4 implemented this incorrectly; see . */ - if (len < tdep->wordsize) + if (len < tdep->wordsize + && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) offset = tdep->wordsize - len; if (argpos->regcache) @@ -1160,8 +1277,8 @@ ppc64_sysv_abi_push_val (struct gdbarch *gdbarch, while (len >= tdep->wordsize) { if (argpos->regcache && argpos->greg <= 10) - regcache_cooked_write (argpos->regcache, - tdep->ppc_gp0_regnum + argpos->greg, val); + argpos->regcache->cooked_write (tdep->ppc_gp0_regnum + argpos->greg, + val); argpos->greg++; len -= tdep->wordsize; val += tdep->wordsize; @@ -1170,9 +1287,8 @@ ppc64_sysv_abi_push_val (struct gdbarch *gdbarch, if (len > 0) { if (argpos->regcache && argpos->greg <= 10) - regcache_cooked_write_part (argpos->regcache, - tdep->ppc_gp0_regnum + argpos->greg, - offset, len, val); + argpos->regcache->cooked_write_part + (tdep->ppc_gp0_regnum + argpos->greg, offset, len, val); argpos->greg++; } } @@ -1184,9 +1300,9 @@ static void ppc64_sysv_abi_push_integer (struct gdbarch *gdbarch, ULONGEST val, struct ppc64_sysv_argpos *argpos) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[MAX_REGISTER_SIZE]; + gdb_byte buf[PPC_MAX_REGISTER_SIZE]; if (argpos->regcache) store_unsigned_integer (buf, tdep->wordsize, byte_order, val); @@ -1202,45 +1318,48 @@ 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); if (tdep->soft_float) return; if (TYPE_LENGTH (type) <= 8 - && TYPE_CODE (type) == TYPE_CODE_FLT) + && type->code () == TYPE_CODE_FLT) { /* Floats and doubles go in f1 .. f13. 32-bit floats are converted - to double first. */ + 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[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; - convert_typed_floating (val, type, regval, regtype); - regcache_cooked_write (argpos->regcache, regnum, regval); + 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) + && 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 = 8 - TYPE_LENGTH (type); + int offset = 0; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - TYPE_LENGTH (type); - regcache_cooked_write_part (argpos->regcache, regnum, - offset, TYPE_LENGTH (type), val); + 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 + && type->code () == TYPE_CODE_FLT && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double)) { @@ -1249,15 +1368,15 @@ ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch, { int regnum = tdep->ppc_fp0_regnum + argpos->freg; - regcache_cooked_write (argpos->regcache, regnum, val); + argpos->regcache->cooked_write (regnum, val); if (argpos->freg <= 12) - regcache_cooked_write (argpos->regcache, regnum + 1, val + 8); + argpos->regcache->cooked_write (regnum + 1, val + 8); } argpos->freg += 2; } else if (TYPE_LENGTH (type) == 16 - && TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + && 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. */ @@ -1266,9 +1385,11 @@ ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch, 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; - regcache_cooked_write (argpos->regcache, regnum, val); - regcache_cooked_write (argpos->regcache, regnum + 1, val + 8); + argpos->regcache->cooked_write (regnum, val + hipart); + argpos->regcache->cooked_write (regnum + 1, val + lopart); } argpos->freg += 2; @@ -1282,11 +1403,10 @@ 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); if (argpos->regcache && argpos->vreg <= 13) - regcache_cooked_write (argpos->regcache, - tdep->ppc_vr0_regnum + argpos->vreg, val); + argpos->regcache->cooked_write (tdep->ppc_vr0_regnum + argpos->vreg, val); argpos->vreg++; } @@ -1299,16 +1419,16 @@ 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); - if (TYPE_CODE (type) == TYPE_CODE_FLT - || TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + 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) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) + else if (type->code () == TYPE_CODE_ARRAY && type->is_vector () && tdep->vector_abi == POWERPC_VEC_ALTIVEC && TYPE_LENGTH (type) == 16) { @@ -1316,7 +1436,7 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch, 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) + else if (type->code () == TYPE_CODE_ARRAY && type->is_vector () && TYPE_LENGTH (type) >= 16) { /* Non-Altivec vectors are passed by reference. */ @@ -1330,12 +1450,12 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch, /* ... 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_CODE (type) == TYPE_CODE_REF) + 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; @@ -1346,14 +1466,15 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch, 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) + 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 (TYPE_CODE (target_type) == TYPE_CODE_FUNC - || TYPE_CODE (target_type) == TYPE_CODE_METHOD) + if (target_type->code () == TYPE_CODE_FUNC + || target_type->code () == TYPE_CODE_METHOD) { CORE_ADDR desc = word; @@ -1372,16 +1493,39 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch, /* 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) + if (type->code () == TYPE_CODE_STRUCT + && type->num_fields () == 1) { - while (TYPE_CODE (type) == TYPE_CODE_STRUCT - && TYPE_NFIELDS (type) == 1) - type = check_typedef (TYPE_FIELD_TYPE (type, 0)); + while (type->code () == TYPE_CODE_STRUCT + && type->num_fields () == 1) + type = check_typedef (type->field (0).type ()); - if (TYPE_CODE (type) == TYPE_CODE_FLT) + 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 + && eltype->is_vector () + && tdep->vector_abi == POWERPC_VEC_ALTIVEC + && TYPE_LENGTH (eltype) == 16) + ppc64_sysv_abi_push_vreg (gdbarch, elval, argpos); + } + } } } @@ -1397,10 +1541,11 @@ 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_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; @@ -1467,26 +1612,30 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, 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, - compiler double word, LR save area, CR save area. */ - sp = align_down (argpos.gparam - 48, 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 (struct_return) + 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); + const bfd_byte *val = value_contents (arg).data (); - if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) + if (type->code () == TYPE_CODE_COMPLEX) { /* Complex types are passed as if two independent scalars. */ struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type)); @@ -1495,7 +1644,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, ppc64_sysv_abi_push_param (gdbarch, eltype, val + TYPE_LENGTH (eltype), &argpos); } - else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) + else if (type->code () == TYPE_CODE_ARRAY && type->is_vector () && opencl_abi) { /* OpenCL vectors shorter than 16 bytes are passed as if @@ -1547,24 +1696,32 @@ 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 (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); + + 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; } @@ -1582,22 +1739,39 @@ 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_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) + if ((valtype->code () == TYPE_CODE_INT + || valtype->code () == TYPE_CODE_ENUM + || valtype->code () == TYPE_CODE_CHAR + || valtype->code () == TYPE_CODE_BOOL + || valtype->code () == TYPE_CODE_RANGE + || is_fixed_point_type (valtype)) && TYPE_LENGTH (valtype) <= 8) { int regnum = tdep->ppc_gp0_regnum + 3 + index; if (writebuf != NULL) { + LONGEST return_val; + + if (is_fixed_point_type (valtype)) + { + /* Fixed point type values need to be returned unscaled. */ + gdb_mpz unscaled; + + unscaled.read (gdb::make_array_view (writebuf, + TYPE_LENGTH (valtype)), + type_byte_order (valtype), + valtype->is_unsigned ()); + return_val = unscaled.as_integer (); + } + else + return_val = unpack_long (valtype, writebuf); + /* Be careful to sign extend the value. */ - regcache_cooked_write_unsigned (regcache, regnum, - unpack_long (valtype, writebuf)); + regcache_cooked_write_unsigned (regcache, regnum, return_val); } if (readbuf != NULL) { @@ -1615,21 +1789,21 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, /* 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) + && valtype->code () == TYPE_CODE_FLT) { int regnum = tdep->ppc_fp0_regnum + 1 + index; struct type *regtype = register_type (gdbarch, regnum); - gdb_byte regval[MAX_REGISTER_SIZE]; + gdb_byte regval[PPC_MAX_REGISTER_SIZE]; if (writebuf != NULL) { - convert_typed_floating (writebuf, valtype, regval, regtype); - regcache_cooked_write (regcache, regnum, regval); + target_float_convert (writebuf, valtype, regval, regtype); + regcache->cooked_write (regnum, regval); } if (readbuf != NULL) { - regcache_cooked_read (regcache, regnum, regval); - convert_typed_floating (regval, regtype, readbuf, valtype); + regcache->cooked_read (regnum, regval); + target_float_convert (regval, regtype, readbuf, valtype); } return 1; } @@ -1637,23 +1811,26 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, /* 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) + && valtype->code () == TYPE_CODE_DECFLOAT) { int regnum = tdep->ppc_fp0_regnum + 1 + index; - int offset = 8 - TYPE_LENGTH (valtype); + int offset = 0; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - TYPE_LENGTH (valtype); if (writebuf != NULL) - regcache_cooked_write_part (regcache, regnum, - offset, TYPE_LENGTH (valtype), writebuf); + regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype), + writebuf); if (readbuf != NULL) - regcache_cooked_read_part (regcache, regnum, - offset, TYPE_LENGTH (valtype), readbuf); + 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 + && valtype->code () == TYPE_CODE_FLT && (gdbarch_long_double_format (gdbarch) == floatformats_ibm_long_double)) { @@ -1661,13 +1838,13 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, if (writebuf != NULL) { - regcache_cooked_write (regcache, regnum, writebuf); - regcache_cooked_write (regcache, regnum + 1, writebuf + 8); + regcache->cooked_write (regnum, writebuf); + regcache->cooked_write (regnum + 1, writebuf + 8); } if (readbuf != NULL) { - regcache_cooked_read (regcache, regnum, readbuf); - regcache_cooked_read (regcache, regnum + 1, readbuf + 8); + regcache->cooked_read (regnum, readbuf); + regcache->cooked_read (regnum + 1, readbuf + 8); } return 1; } @@ -1675,33 +1852,55 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, /* 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) + && 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 (writebuf != NULL) { - regcache_cooked_write (regcache, regnum, writebuf); - regcache_cooked_write (regcache, regnum + 1, writebuf + 8); + regcache->cooked_write (regnum, writebuf + hipart); + regcache->cooked_write (regnum + 1, writebuf + lopart); } if (readbuf != NULL) { - regcache_cooked_read (regcache, regnum, readbuf); - regcache_cooked_read (regcache, regnum + 1, readbuf + 8); + 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_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype) + if (TYPE_LENGTH (valtype) == 16 + && valtype->code () == TYPE_CODE_ARRAY && valtype->is_vector () && tdep->vector_abi == POWERPC_VEC_ALTIVEC) { int regnum = tdep->ppc_vr0_regnum + 2 + index; if (writebuf != NULL) - regcache_cooked_write (regcache, regnum, writebuf); + regcache->cooked_write (regnum, writebuf); if (readbuf != NULL) - regcache_cooked_read (regcache, regnum, readbuf); + regcache->cooked_read (regnum, readbuf); + return 1; + } + + /* Short vectors are returned in GPRs starting at r3. */ + if (TYPE_LENGTH (valtype) <= 8 + && valtype->code () == TYPE_CODE_ARRAY && valtype->is_vector ()) + { + 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; } @@ -1723,11 +1922,11 @@ 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); + ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (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, i, ok; + int nelt, ok; /* This function exists to support a calling convention that requires floating-point registers. It shouldn't be used on @@ -1735,11 +1934,11 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, gdb_assert (ppc_floating_point_unit_p (gdbarch)); /* Complex types are returned as if two independent scalars. */ - if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX) + if (valtype->code () == TYPE_CODE_COMPLEX) { eltype = check_typedef (TYPE_TARGET_TYPE (valtype)); - for (i = 0; i < 2; i++) + for (int i = 0; i < 2; i++) { ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache, readbuf, writebuf, i); @@ -1756,7 +1955,7 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, /* 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) + if (valtype->code () == TYPE_CODE_ARRAY && valtype->is_vector () && opencl_abi) { if (TYPE_LENGTH (valtype) < 16) @@ -1765,7 +1964,7 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, eltype = register_type (gdbarch, tdep->ppc_vr0_regnum); nelt = TYPE_LENGTH (valtype) / TYPE_LENGTH (eltype); - for (i = 0; i < nelt; i++) + for (int i = 0; i < nelt; i++) { ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache, readbuf, writebuf, i); @@ -1780,33 +1979,104 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, } /* 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)) { int regnum = tdep->ppc_gp0_regnum + 3; if (writebuf != NULL) - regcache_cooked_write (regcache, regnum, writebuf); + regcache->cooked_write (regnum, writebuf); if (readbuf != NULL) - regcache_cooked_read (regcache, regnum, readbuf); + regcache->cooked_read (regnum, readbuf); return RETURN_VALUE_REGISTER_CONVENTION; } /* Small character arrays are returned, right justified, in r3. */ - if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY + if (valtype->code () == TYPE_CODE_ARRAY + && !valtype->is_vector () && TYPE_LENGTH (valtype) <= 8 - && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT + && TYPE_TARGET_TYPE (valtype)->code () == TYPE_CODE_INT && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1) { int regnum = tdep->ppc_gp0_regnum + 3; int offset = (register_size (gdbarch, regnum) - TYPE_LENGTH (valtype)); if (writebuf != NULL) - regcache_cooked_write_part (regcache, regnum, - offset, TYPE_LENGTH (valtype), writebuf); + regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype), + writebuf); if (readbuf != NULL) - regcache_cooked_read_part (regcache, regnum, - offset, TYPE_LENGTH (valtype), readbuf); + regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype), + readbuf); + return RETURN_VALUE_REGISTER_CONVENTION; + } + + /* 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 + && eltype->is_vector () + && tdep->vector_abi == POWERPC_VEC_ALTIVEC + && TYPE_LENGTH (eltype) == 16))) + { + for (int i = 0; i < nelt; i++) + { + 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; + } + + /* 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 + && !valtype->is_vector ()))) + { + int n_regs = ((TYPE_LENGTH (valtype) + tdep->wordsize - 1) + / tdep->wordsize); + + for (int i = 0; i < n_regs; 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) + { + 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); + } + if (readbuf != NULL) + { + 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; }