+ if (argpos->regcache)
+ write_memory (argpos->gparam + offset, val, len);
+ argpos->gparam = align_up (argpos->gparam + len, tdep->wordsize);
+
+ while (len >= tdep->wordsize)
+ {
+ if (argpos->regcache && argpos->greg <= 10)
+ regcache_cooked_write (argpos->regcache,
+ 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->greg++;
+ }
+}
+
+/* The same as ppc64_sysv_abi_push_val, but using a single-word integer
+ value VAL as argument. */
+
+static void
+ppc64_sysv_abi_push_integer (struct gdbarch *gdbarch, ULONGEST val,
+ struct ppc64_sysv_argpos *argpos)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ gdb_byte buf[MAX_REGISTER_SIZE];
+
+ if (argpos->regcache)
+ store_unsigned_integer (buf, tdep->wordsize, byte_order, val);
+ ppc64_sysv_abi_push_val (gdbarch, buf, tdep->wordsize, 0, argpos);
+}
+
+/* VAL is a value of TYPE, a (binary or decimal) floating-point type.
+ Load it into a floating-point register if required by the ABI,
+ and update ARGPOS. */
+
+static void
+ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch,
+ struct type *type, const bfd_byte *val,
+ struct ppc64_sysv_argpos *argpos)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ if (tdep->soft_float)
+ return;
+
+ if (TYPE_LENGTH (type) <= 8
+ && TYPE_CODE (type) == TYPE_CODE_FLT)
+ {
+ /* Floats and doubles go in f1 .. f13. 32-bit floats are converted
+ to double first. */
+ if (argpos->regcache && argpos->freg <= 13)
+ {
+ int regnum = tdep->ppc_fp0_regnum + argpos->freg;
+ struct type *regtype = register_type (gdbarch, regnum);
+ gdb_byte regval[MAX_REGISTER_SIZE];
+
+ convert_typed_floating (val, type, regval, regtype);
+ regcache_cooked_write (argpos->regcache, regnum, regval);
+ }
+
+ argpos->freg++;
+ }
+ else if (TYPE_LENGTH (type) <= 8
+ && TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ {
+ /* Floats and doubles go in f1 .. f13. 32-bit decimal floats are
+ placed in the least significant word. */
+ if (argpos->regcache && argpos->freg <= 13)
+ {
+ int regnum = tdep->ppc_fp0_regnum + argpos->freg;
+ int offset = 0;
+
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ offset = 8 - TYPE_LENGTH (type);
+
+ regcache_cooked_write_part (argpos->regcache, regnum,
+ offset, TYPE_LENGTH (type), val);
+ }
+
+ argpos->freg++;
+ }
+ else if (TYPE_LENGTH (type) == 16
+ && TYPE_CODE (type) == TYPE_CODE_FLT
+ && (gdbarch_long_double_format (gdbarch)
+ == floatformats_ibm_long_double))
+ {
+ /* IBM long double stored in two consecutive FPRs. */
+ if (argpos->regcache && argpos->freg <= 13)
+ {
+ int regnum = tdep->ppc_fp0_regnum + argpos->freg;
+
+ regcache_cooked_write (argpos->regcache, regnum, val);
+ if (argpos->freg <= 12)
+ regcache_cooked_write (argpos->regcache, regnum + 1, val + 8);
+ }
+
+ argpos->freg += 2;
+ }
+ else if (TYPE_LENGTH (type) == 16
+ && TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ {
+ /* 128-bit decimal floating-point values are stored in and even/odd
+ pair of FPRs, with the even FPR holding the most significant half. */
+ argpos->freg += argpos->freg & 1;
+
+ if (argpos->regcache && argpos->freg <= 12)
+ {
+ int regnum = tdep->ppc_fp0_regnum + argpos->freg;
+ int lopart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 : 0;
+ int hipart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
+
+ regcache_cooked_write (argpos->regcache, regnum, val + hipart);
+ regcache_cooked_write (argpos->regcache, regnum + 1, val + lopart);
+ }
+
+ argpos->freg += 2;
+ }
+}
+
+/* VAL is a value of AltiVec vector type. Load it into a vector register
+ if required by the ABI, and update ARGPOS. */
+
+static void
+ppc64_sysv_abi_push_vreg (struct gdbarch *gdbarch, const bfd_byte *val,
+ struct ppc64_sysv_argpos *argpos)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (argpos->regcache && argpos->vreg <= 13)
+ regcache_cooked_write (argpos->regcache,
+ tdep->ppc_vr0_regnum + argpos->vreg, val);
+
+ argpos->vreg++;
+}
+
+/* VAL is a value of TYPE. Load it into memory and/or registers
+ as required by the ABI, and update ARGPOS. */
+
+static void
+ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
+ struct type *type, const bfd_byte *val,
+ struct ppc64_sysv_argpos *argpos)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ {
+ /* Floating-point scalars are passed in floating-point registers. */
+ ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 0, argpos);
+ ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos);
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
+ && tdep->vector_abi == POWERPC_VEC_ALTIVEC
+ && TYPE_LENGTH (type) == 16)
+ {
+ /* AltiVec vectors are passed aligned, and in vector registers. */
+ ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 16, argpos);
+ ppc64_sysv_abi_push_vreg (gdbarch, val, argpos);
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
+ && TYPE_LENGTH (type) >= 16)
+ {
+ /* Non-Altivec vectors are passed by reference. */
+
+ /* Copy value onto the stack ... */
+ CORE_ADDR addr = align_up (argpos->refparam, 16);
+ if (argpos->regcache)
+ write_memory (addr, val, TYPE_LENGTH (type));
+ argpos->refparam = align_up (addr + TYPE_LENGTH (type), tdep->wordsize);
+
+ /* ... and pass a pointer to the copy as parameter. */
+ ppc64_sysv_abi_push_integer (gdbarch, addr, argpos);
+ }
+ else if ((TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_ENUM
+ || TYPE_CODE (type) == TYPE_CODE_BOOL
+ || TYPE_CODE (type) == TYPE_CODE_CHAR
+ || TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF)
+ && TYPE_LENGTH (type) <= tdep->wordsize)
+ {
+ ULONGEST word = 0;
+
+ if (argpos->regcache)
+ {
+ /* Sign extend the value, then store it unsigned. */
+ word = unpack_long (type, val);
+
+ /* Convert any function code addresses into descriptors. */
+ if (tdep->elf_abi == POWERPC_ELF_V1
+ && (TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF))