/* The 64 bit ABI retun value convention. Return non-zero if the return-value is stored in a register, return 0 if the return-value is instead stored on the stack (a.k.a., struct return convention). For a return-value stored in a register: when WRITEBUF is non-NULL, copy the buffer to the corresponding register return-value location location; when READBUF is non-NULL, fill the buffer from the corresponding register return-value location. */ enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* This function exists to support a calling convention that requires floating-point registers. It shouldn't be used on processors that lack them. */ gdb_assert (ppc_floating_point_unit_p (gdbarch)); /* Floats and doubles in F1. */ if (TYPE_CODE (valtype) == TYPE_CODE_FLT && TYPE_LENGTH (valtype) <= 8) { gdb_byte regval[MAX_REGISTER_SIZE]; struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum); if (writebuf != NULL) { convert_typed_floating (writebuf, valtype, regval, regtype); regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval); } if (readbuf != NULL) { regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval); convert_typed_floating (regval, regtype, readbuf, valtype); } return RETURN_VALUE_REGISTER_CONVENTION; } if ((TYPE_CODE (valtype) == TYPE_CODE_INT || TYPE_CODE (valtype) == TYPE_CODE_ENUM) && TYPE_LENGTH (valtype) <= 8) { /* Integers in r3. */ if (writebuf != NULL) { /* Be careful to sign extend the value. */ regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3, unpack_long (valtype, writebuf)); } if (readbuf != NULL) { /* Extract the integer from r3. Since this is truncating the value, there isn't a sign extension problem. */ ULONGEST regval; regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3, ®val); store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval); } return RETURN_VALUE_REGISTER_CONVENTION; } /* All pointers live in r3. */ if (TYPE_CODE (valtype) == TYPE_CODE_PTR) { /* All pointers live in r3. */ if (writebuf != NULL) regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf); if (readbuf != NULL) regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf); return RETURN_VALUE_REGISTER_CONVENTION; } if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_LENGTH (valtype) <= 8 && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1) { /* Small character arrays are returned, right justified, in r3. */ int offset = (register_size (gdbarch, tdep->ppc_gp0_regnum + 3) - TYPE_LENGTH (valtype)); if (writebuf != NULL) regcache_cooked_write_part (regcache, tdep->ppc_gp0_regnum + 3, offset, TYPE_LENGTH (valtype), writebuf); if (readbuf != NULL) regcache_cooked_read_part (regcache, tdep->ppc_gp0_regnum + 3, offset, TYPE_LENGTH (valtype), readbuf); return RETURN_VALUE_REGISTER_CONVENTION; } /* Big floating point values get stored in adjacent floating point registers. */ if (TYPE_CODE (valtype) == TYPE_CODE_FLT && (TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 32)) { if (writebuf || readbuf != NULL) { int i; for (i = 0; i < TYPE_LENGTH (valtype) / 8; i++) { if (writebuf != NULL) regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i, (const bfd_byte *) writebuf + i * 8); if (readbuf != NULL) regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i, (bfd_byte *) readbuf + i * 8); } } return RETURN_VALUE_REGISTER_CONVENTION; } /* Complex values get returned in f1:f2, need to convert. */ if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX && (TYPE_LENGTH (valtype) == 8 || TYPE_LENGTH (valtype) == 16)) { if (regcache != NULL) { int i; for (i = 0; i < 2; i++) { gdb_byte regval[MAX_REGISTER_SIZE]; struct type *regtype = register_type (current_gdbarch, tdep->ppc_fp0_regnum); if (writebuf != NULL) { convert_typed_floating ((const bfd_byte *) writebuf + i * (TYPE_LENGTH (valtype) / 2), valtype, regval, regtype); regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i, regval); } if (readbuf != NULL) { regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i, regval); convert_typed_floating (regval, regtype, (bfd_byte *) readbuf + i * (TYPE_LENGTH (valtype) / 2), valtype); } } } return RETURN_VALUE_REGISTER_CONVENTION; } /* Big complex values get stored in f1:f4. */ if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX && TYPE_LENGTH (valtype) == 32) { if (regcache != NULL) { int i; for (i = 0; i < 4; i++) { if (writebuf != NULL) regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i, (const bfd_byte *) writebuf + i * 8); if (readbuf != NULL) regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i, (bfd_byte *) readbuf + i * 8); } } return RETURN_VALUE_REGISTER_CONVENTION; } return RETURN_VALUE_STRUCT_CONVENTION; }
static enum return_value_convention d10v_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, void *readbuf, const void *writebuf) { if (TYPE_LENGTH (valtype) > 8) /* Anything larger than 8 bytes (4 registers) goes on the stack. */ return RETURN_VALUE_STRUCT_CONVENTION; if (TYPE_LENGTH (valtype) == 5 || TYPE_LENGTH (valtype) == 6) /* Anything 5 or 6 bytes in size goes in memory. Contents don't appear to matter. Note that 7 and 8 byte objects do end up in registers! */ return RETURN_VALUE_STRUCT_CONVENTION; if (TYPE_LENGTH (valtype) == 1) { /* All single byte values go in a register stored right-aligned. Note: 2 byte integer values are handled further down. */ if (readbuf) { /* Since TYPE is smaller than the register, there isn't a sign extension problem. Let the extraction truncate the register value. */ ULONGEST regval; regcache_cooked_read_unsigned (regcache, R0_REGNUM, ®val); store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), regval); } if (writebuf) { ULONGEST regval; if (TYPE_CODE (valtype) == TYPE_CODE_INT) /* Some sort of integer value stored in R0. Use unpack_long since that should handle any required sign extension. */ regval = unpack_long (valtype, writebuf); else /* Some other type. Don't sign-extend the value when storing it in the register. */ regval = extract_unsigned_integer (writebuf, 1); regcache_cooked_write_unsigned (regcache, R0_REGNUM, regval); } return RETURN_VALUE_REGISTER_CONVENTION; } if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT || TYPE_CODE (valtype) == TYPE_CODE_UNION) && TYPE_NFIELDS (valtype) > 1 && TYPE_FIELD_BITPOS (valtype, 1) == 8) /* If a composite is 8 bit aligned (determined by looking at the start address of the second field), put it in memory. */ return RETURN_VALUE_STRUCT_CONVENTION; /* Assume it is in registers. */ if (writebuf || readbuf) { int reg; /* Per above, the value is never more than 8 bytes long. */ gdb_assert (TYPE_LENGTH (valtype) <= 8); /* Xfer 2 bytes at a time. */ for (reg = 0; (reg * 2) + 1 < TYPE_LENGTH (valtype); reg++) { if (readbuf) regcache_cooked_read (regcache, R0_REGNUM + reg, (bfd_byte *) readbuf + reg * 2); if (writebuf) regcache_cooked_write (regcache, R0_REGNUM + reg, (bfd_byte *) writebuf + reg * 2); } /* Any trailing byte ends up _left_ aligned. */ if ((reg * 2) < TYPE_LENGTH (valtype)) { if (readbuf) regcache_cooked_read_part (regcache, R0_REGNUM + reg, 0, 1, (bfd_byte *) readbuf + reg * 2); if (writebuf) regcache_cooked_write_part (regcache, R0_REGNUM + reg, 0, 1, (bfd_byte *) writebuf + reg * 2); } } return RETURN_VALUE_REGISTER_CONVENTION; }