Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 235529) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -418,12 +418,12 @@ extern const char *host_detect_local_cpu Similarly IFmode is the IBM long double format even if the default is IEEE 128-bit. */ #define FLOAT128_IEEE_P(MODE) \ - (((MODE) == TFmode && TARGET_IEEEQUAD) \ - || ((MODE) == KFmode)) + ((TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \ + || ((MODE) == KFmode) || ((MODE) == KCmode)) #define FLOAT128_IBM_P(MODE) \ - (((MODE) == TFmode && !TARGET_IEEEQUAD) \ - || ((MODE) == IFmode)) + ((!TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \ + || ((MODE) == IFmode) || ((MODE) == ICmode)) /* Helper macros to say whether a 128-bit floating point type can go in a single vector register, or whether it needs paired scalar values. */ @@ -1768,13 +1768,17 @@ extern enum reg_class rs6000_constraints /* Maximum number of registers per ELFv2 homogeneous aggregate argument. */ #define AGGR_ARG_NUM_REG 8 +/* _Complex __float128 needs two registers. */ +#define ALTIVEC_COMPLEX ((TARGET_FLOAT128) ? 1 : 0) + /* Return registers */ #define GP_ARG_RETURN GP_ARG_MIN_REG #define FP_ARG_RETURN FP_ARG_MIN_REG #define ALTIVEC_ARG_RETURN (FIRST_ALTIVEC_REGNO + 2) #define FP_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2 ? FP_ARG_RETURN \ : (FP_ARG_RETURN + AGGR_ARG_NUM_REG - 1)) -#define ALTIVEC_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2 ? ALTIVEC_ARG_RETURN \ +#define ALTIVEC_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2 \ + ? (ALTIVEC_ARG_RETURN + ALTIVEC_COMPLEX) \ : (ALTIVEC_ARG_RETURN + AGGR_ARG_NUM_REG - 1)) /* Flags for the call/call_value rtl operations set up by function_arg */ @@ -2603,7 +2607,7 @@ extern char rs6000_reg_names[][8]; /* re /* Define which CODE values are valid. */ -#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '&') +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '&' || (CODE) == '@') /* Print a memory address as an operand to reference that memory location. */ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 235529) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1866,7 +1866,7 @@ rs6000_hard_regno_nregs_internal (int re 128-bit floating point that can go in vector registers, which has VSX memory addressing. */ if (FP_REGNO_P (regno)) - reg_size = (VECTOR_MEM_VSX_P (mode) + reg_size = (VECTOR_MEM_VSX_P (mode) || FLOAT128_VECTOR_P (mode) ? UNITS_PER_VSX_WORD : UNITS_PER_FP_WORD); @@ -1898,6 +1898,9 @@ rs6000_hard_regno_mode_ok (int regno, ma { int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1; + if (COMPLEX_MODE_P (mode)) + mode = GET_MODE_INNER (mode); + /* PTImode can only go in GPRs. Quad word memory operations require even/odd register combinations, and use PTImode where we need to deal with quad word memory operations. Don't allow quad words in the argument or frame @@ -2700,7 +2703,16 @@ rs6000_setup_reg_addr_masks (void) for (m = 0; m < NUM_MACHINE_MODES; ++m) { machine_mode m2 = (machine_mode)m; - unsigned short msize = GET_MODE_SIZE (m2); + bool complex_p = false; + size_t msize; + + if (COMPLEX_MODE_P (m2)) + { + complex_p = true; + m2 = GET_MODE_INNER (m2); + } + + msize = GET_MODE_SIZE (m2); /* SDmode is special in that we want to access it only via REG+REG addressing on power7 and above, since we want to use the LFIWZX and @@ -2722,7 +2734,7 @@ rs6000_setup_reg_addr_masks (void) /* Indicate if the mode takes more than 1 physical register. If it takes a single register, indicate it can do REG+REG addressing. */ - if (nregs > 1 || m == BLKmode) + if (nregs > 1 || m == BLKmode || complex_p) addr_mask |= RELOAD_REG_MULTIPLE; else addr_mask |= RELOAD_REG_INDEXED; @@ -2738,7 +2750,7 @@ rs6000_setup_reg_addr_masks (void) && msize <= 8 && !VECTOR_MODE_P (m2) && !FLOAT128_VECTOR_P (m2) - && !COMPLEX_MODE_P (m2) + && !complex_p && (m2 != DFmode || !TARGET_UPPER_REGS_DF) && (m2 != SFmode || !TARGET_UPPER_REGS_SF) && !(TARGET_E500_DOUBLE && msize == 8)) @@ -33869,8 +33881,14 @@ rs6000_complex_function_value (machine_m machine_mode inner = GET_MODE_INNER (mode); unsigned int inner_bytes = GET_MODE_UNIT_SIZE (mode); - if (FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS) + if (TARGET_FLOAT128 + && ((mode == KCmode) + || (mode == TCmode && TARGET_IEEEQUAD))) + regno = ALTIVEC_ARG_RETURN; + + else if (FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS) regno = FP_ARG_RETURN; + else { regno = GP_ARG_RETURN; Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 235529) +++ gcc/doc/extend.texi (working copy) @@ -962,8 +962,13 @@ complex @code{__float128} type. When th would use the following syntax to declare @code{_Complex128} to be a complex @code{__float128} type: +On the PowerPC Linux VSX targets, you can declare complex types using +the corresponding internal complex type, @code{KCmode} for +@code{__float128} type and @code{ICmode} for @code{__ibm128} type: + @smallexample -typedef _Complex float __attribute__((mode(KC))) _Complex128; +typedef _Complex float __attribute__((mode(KC))) _Complex_float128; +typedef _Complex float __attribute__((mode(IC))) _Complex_ibm128; @end smallexample Not all targets support additional floating-point types.