/* 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-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "inferior.h"
#include "regcache.h"
#include "value.h"
-#include <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 <algorithm>
/* Check whether FTPYE is a (pointer to) function type that should use
{
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);
}
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);
(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,
int len = TYPE_LENGTH (type);
const bfd_byte *val = value_contents (arg);
- if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8
+ if (type->code () == TYPE_CODE_FLT && len <= 8
&& !tdep->soft_float)
{
/* Floating point value converted to "double" then
{
/* 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++;
}
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)
{
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;
}
}
}
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"
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
{
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
{
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
else
p = val;
- regcache_cooked_write (regcache,
- tdep->ppc_fp0_regnum + freg, p);
+ regcache->cooked_write (tdep->ppc_fp0_regnum + freg, p);
}
freg++;
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
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
freg += 2;
}
else if (len < 16
- && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& opencl_abi)
{
{
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++;
}
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
}
}
else if (len >= 16
- && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& opencl_abi)
{
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
}
}
else if (len == 16
- && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& tdep->vector_abi == POWERPC_VEC_ALTIVEC)
{
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
}
}
else if (len == 8
- && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& tdep->vector_abi == POWERPC_VEC_SPE)
{
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
{
/* Reduce the parameter down to something that fits in a
"word". */
- gdb_byte word[MAX_REGISTER_SIZE];
- memset (word, 0, MAX_REGISTER_SIZE);
+ gdb_byte word[PPC_MAX_REGISTER_SIZE];
+ memset (word, 0, PPC_MAX_REGISTER_SIZE);
if (len > tdep->wordsize
- || TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION)
+ || type->code () == TYPE_CODE_STRUCT
+ || type->code () == TYPE_CODE_UNION)
{
/* Structs and large values are put in an
aligned stack slot ... */
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+ if (type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& len >= 16)
structoffset = align_up (structoffset, 16);
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));
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
}
/* 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);
- 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. */
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)
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);
}
}
}
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)
{
{
/* Floats and doubles stored in "f1". Convert the value to
the required type. */
- gdb_byte regval[MAX_REGISTER_SIZE];
+ gdb_byte regval[PPC_MAX_REGISTER_SIZE];
struct type *regtype = register_type (gdbarch,
tdep->ppc_fp0_regnum + 1);
- regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
- convert_typed_floating (regval, regtype, readbuf, type);
+ regcache->cooked_read (tdep->ppc_fp0_regnum + 1, regval);
+ target_float_convert (regval, regtype, readbuf, type);
}
if (writebuf)
{
/* Floats and doubles stored in "f1". Convert the value to
the register's "double" type. */
- gdb_byte regval[MAX_REGISTER_SIZE];
+ gdb_byte regval[PPC_MAX_REGISTER_SIZE];
struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
- convert_typed_floating (writebuf, type, regval, regtype);
- regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
+ target_float_convert (writebuf, type, regval, regtype);
+ regcache->cooked_write (tdep->ppc_fp0_regnum + 1, regval);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
- if (TYPE_CODE (type) == TYPE_CODE_FLT
+ if (type->code () == TYPE_CODE_FLT
&& TYPE_LENGTH (type) == 16
&& !tdep->soft_float
&& (gdbarch_long_double_format (gdbarch)
/* 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)
}
/* OpenCL vectors < 16 bytes are returned as distinct
scalars in f1..f2 or r3..r10. */
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+ if (type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& TYPE_LENGTH (type) < 16
&& opencl_abi)
{
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
return RETURN_VALUE_REGISTER_CONVENTION;
}
/* OpenCL vectors >= 16 bytes are returned in v2..v9. */
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+ if (type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& TYPE_LENGTH (type) >= 16
&& opencl_abi)
int regnum = tdep->ppc_vr0_regnum + 2 + i;
if (writebuf != NULL)
- regcache_cooked_write (regcache, regnum, writebuf + offset);
+ regcache->cooked_write (regnum, writebuf + offset);
if (readbuf != NULL)
- regcache_cooked_read (regcache, regnum, readbuf + offset);
+ regcache->cooked_read (regnum, readbuf + offset);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_LENGTH (type) == 16
- && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& tdep->vector_abi == POWERPC_VEC_ALTIVEC)
{
if (readbuf)
{
/* Altivec places the return value in "v2". */
- regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
+ regcache->cooked_read (tdep->ppc_vr0_regnum + 2, readbuf);
}
if (writebuf)
{
/* Altivec places the return value in "v2". */
- regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
+ regcache->cooked_write (tdep->ppc_vr0_regnum + 2, writebuf);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_LENGTH (type) == 16
- && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& tdep->vector_abi == POWERPC_VEC_GENERIC)
{
ABI risks in that case; we don't try to support it. */
if (readbuf)
{
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
- readbuf + 0);
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
- readbuf + 4);
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5,
- readbuf + 8);
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6,
- readbuf + 12);
+ regcache->cooked_read (tdep->ppc_gp0_regnum + 3, readbuf + 0);
+ regcache->cooked_read (tdep->ppc_gp0_regnum + 4, readbuf + 4);
+ regcache->cooked_read (tdep->ppc_gp0_regnum + 5, readbuf + 8);
+ regcache->cooked_read (tdep->ppc_gp0_regnum + 6, readbuf + 12);
}
if (writebuf)
{
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
- writebuf + 0);
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
- writebuf + 4);
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5,
- writebuf + 8);
- regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6,
- writebuf + 12);
+ regcache->cooked_write (tdep->ppc_gp0_regnum + 3, writebuf + 0);
+ regcache->cooked_write (tdep->ppc_gp0_regnum + 4, writebuf + 4);
+ regcache->cooked_write (tdep->ppc_gp0_regnum + 5, writebuf + 8);
+ regcache->cooked_write (tdep->ppc_gp0_regnum + 6, writebuf + 12);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_LENGTH (type) == 8
- && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && type->code () == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
&& tdep->vector_abi == POWERPC_VEC_SPE)
{
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)
/* 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;
/* 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)
/* 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;
}
{
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. */
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_VECTOR (type))
+ {
+ if (!*field_type)
+ *field_type = type;
+ if ((*field_type)->code () == type->code ()
+ && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type))
+ return 1;
+ }
+ else
+ {
+ LONGEST count, low_bound, high_bound;
+
+ count = ppc64_aggregate_candidate
+ (TYPE_TARGET_TYPE (type), field_type);
+ if (count == -1)
+ return -1;
+
+ if (!get_array_bounds (type, &low_bound, &high_bound))
+ return -1;
+ count *= high_bound - low_bound;
+
+ /* There must be no padding. */
+ if (count == 0)
+ return TYPE_LENGTH (type) == 0 ? 0 : -1;
+ else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type))
+ return -1;
+
+ return count;
+ }
+ break;
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ {
+ LONGEST count = 0;
+ int i;
+
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ LONGEST sub_count;
+
+ if (field_is_static (&TYPE_FIELD (type, i)))
+ continue;
+
+ sub_count = ppc64_aggregate_candidate
+ (TYPE_FIELD_TYPE (type, i), field_type);
+ if (sub_count == -1)
+ return -1;
+
+ if (type->code () == TYPE_CODE_STRUCT)
+ count += sub_count;
+ else
+ count = std::max (count, sub_count);
+ }
+
+ /* There must be no padding. */
+ if (count == 0)
+ return TYPE_LENGTH (type) == 0 ? 0 : -1;
+ else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type))
+ return -1;
+
+ return count;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+/* If an argument of type TYPE is a homogeneous float or vector aggregate
+ that shall be passed in FP/vector registers according to the ELFv2 ABI,
+ return the homogeneous element type in *ELT_TYPE and the number of
+ elements in *N_ELTS, and return non-zero. Otherwise, return zero. */
+
+static int
+ppc64_elfv2_abi_homogeneous_aggregate (struct type *type,
+ struct type **elt_type, int *n_elts)
+{
+ /* Complex types at the top level are treated separately. However,
+ complex types can be elements of homogeneous aggregates. */
+ if (type->code () == TYPE_CODE_STRUCT
+ || type->code () == TYPE_CODE_UNION
+ || (type->code () == TYPE_CODE_ARRAY && !TYPE_VECTOR (type)))
+ {
+ struct type *field_type = NULL;
+ LONGEST field_count = ppc64_aggregate_candidate (type, &field_type);
+
+ if (field_count > 0)
+ {
+ int n_regs = ((field_type->code () == TYPE_CODE_FLT
+ || field_type->code () == TYPE_CODE_DECFLOAT)?
+ (TYPE_LENGTH (field_type) + 7) >> 3 : 1);
+
+ /* The ELFv2 ABI allows homogeneous aggregates to occupy
+ up to 8 registers. */
+ if (field_count * n_regs <= 8)
+ {
+ if (elt_type)
+ *elt_type = field_type;
+ if (n_elts)
+ *n_elts = (int) field_count;
+ /* Note that field_count is LONGEST since it may hold the size
+ of an array, while *n_elts is int since its value is bounded
+ by the number of registers used for argument passing. The
+ cast cannot overflow due to the bounds checking above. */
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
/* Structure holding the next argument position. */
struct ppc64_sysv_argpos
{
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;
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++;
}
}
{
struct gdbarch_tdep *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);
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. */
{
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 (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))
{
{
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. */
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 + hipart);
- regcache_cooked_write (argpos->regcache, regnum + 1, val + lopart);
+ argpos->regcache->cooked_write (regnum, val + hipart);
+ argpos->regcache->cooked_write (regnum + 1, val + lopart);
}
argpos->freg += 2;
struct gdbarch_tdep *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++;
}
{
struct gdbarch_tdep *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_VECTOR (type)
&& tdep->vector_abi == POWERPC_VEC_ALTIVEC
&& TYPE_LENGTH (type) == 16)
{
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_VECTOR (type)
&& TYPE_LENGTH (type) >= 16)
{
/* Non-Altivec vectors are passed by reference. */
/* ... 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;
/* 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))
+ && (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;
/* 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
+ if (type->code () == TYPE_CODE_STRUCT
&& TYPE_NFIELDS (type) == 1)
{
- while (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ while (type->code () == TYPE_CODE_STRUCT
&& TYPE_NFIELDS (type) == 1)
type = check_typedef (TYPE_FIELD_TYPE (type, 0));
- 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
+ && TYPE_VECTOR (eltype)
+ && tdep->vector_abi == POWERPC_VEC_ALTIVEC
+ && TYPE_LENGTH (eltype) == 16)
+ ppc64_sysv_abi_push_vreg (gdbarch, elval, argpos);
+ }
+ }
}
}
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);
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
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 (return_method == return_method_struct)
ppc64_sysv_abi_push_integer (gdbarch, struct_addr, &argpos);
for (argno = 0; argno < nargs; argno++)
struct type *type = check_typedef (value_type (arg));
const bfd_byte *val = value_contents (arg);
- 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));
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_VECTOR (type)
&& opencl_abi)
{
/* OpenCL vectors shorter than 16 bytes are passed as if
struct type *ftype = check_typedef (value_type (function));
CORE_ADDR desc_addr = value_as_address (function);
- if (TYPE_CODE (ftype) == TYPE_CODE_PTR
+ 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. */
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)
+ if ((valtype->code () == TYPE_CODE_INT
+ || valtype->code () == TYPE_CODE_ENUM
+ || valtype->code () == TYPE_CODE_CHAR
+ || valtype->code () == TYPE_CODE_BOOL)
&& TYPE_LENGTH (valtype) <= 8)
{
int regnum = tdep->ppc_gp0_regnum + 3 + index;
/* 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;
}
/* 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 = 0;
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))
{
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;
}
/* 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;
if (writebuf != NULL)
{
- regcache_cooked_write (regcache, regnum, writebuf + hipart);
- regcache_cooked_write (regcache, regnum + 1, writebuf + lopart);
+ regcache->cooked_write (regnum, writebuf + hipart);
+ regcache->cooked_write (regnum + 1, writebuf + lopart);
}
if (readbuf != NULL)
{
- regcache_cooked_read (regcache, regnum, readbuf + hipart);
- regcache_cooked_read (regcache, regnum + 1, readbuf + lopart);
+ 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 && TYPE_VECTOR (valtype)
&& 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 (regnum, readbuf);
+ return 1;
+ }
+
+ /* Short vectors are returned in GPRs starting at r3. */
+ if (TYPE_LENGTH (valtype) <= 8
+ && valtype->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype))
+ {
+ int regnum = tdep->ppc_gp0_regnum + 3 + index;
+ int offset = 0;
+
+ 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 (regcache, regnum, readbuf);
+ regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype),
+ readbuf);
return 1;
}
struct type *func_type = function ? value_type (function) : NULL;
int opencl_abi = func_type? ppc_sysv_use_opencl_abi (func_type) : 0;
struct type *eltype;
- int nelt, i, ok;
+ int nelt, ok;
/* This function exists to support a calling convention that
requires floating-point registers. It shouldn't be used on
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);
/* 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 && TYPE_VECTOR (valtype)
&& opencl_abi)
{
if (TYPE_LENGTH (valtype) < 16)
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);
}
/* 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
+ && !TYPE_VECTOR (valtype)
&& 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
+ && TYPE_VECTOR (eltype)
+ && 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
+ && !TYPE_VECTOR (valtype))))
+ {
+ 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;
}