[PATCH v3] C-SKY: Support -mfloat-abi=hard.
Xianmiao Qu
xianmiao_qu@c-sky.com
Wed Sep 16 03:05:27 GMT 2020
It looks good to me, pushed it to trunck.
Thanks,
Cooper
On 9/15/20 4:08 PM, Jojo R wrote:
> gcc/ChangeLog:
>
> * config/csky/csky.md (CSKY_NPARM_FREGS): New.
> (call_value_internal_vs/d): New.
> (untyped_call): New.
> * config/csky/csky.h (TARGET_SINGLE_FPU): New.
> (TARGET_DOUBLE_FPU): New.
> (FUNCTION_VARG_REGNO_P): New.
> (CSKY_VREG_MODE_P): New.
> (FUNCTION_VARG_MODE_P): New.
> (CUMULATIVE_ARGS): Add extra regs info.
> (INIT_CUMULATIVE_ARGS): Use csky_init_cumulative_args.
> (FUNCTION_ARG_REGNO_P): Use FUNCTION_VARG_REGNO_P.
> * config/csky/csky-protos.h (csky_init_cumulative_args): Extern.
> * config/csky/csky.c (csky_cpu_cpp_builtins): Support TARGET_HARD_FLOAT_ABI.
> (csky_function_arg): Likewise.
> (csky_num_arg_regs): Likewise.
> (csky_function_arg_advance): Likewise.
> (csky_function_value): Likewise.
> (csky_libcall_value): Likewise.
> (csky_function_value_regno_p): Likewise.
> (csky_arg_partial_bytes): Likewise.
> (csky_setup_incoming_varargs): Likewise.
> (csky_init_cumulative_args): New.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/builtin-apply2.c : Skip if CSKY.
> * gcc.dg/torture/stackalign/builtin-apply-2.c : Likewise.
>
> ---
> gcc/config/csky/csky-protos.h | 2 +
> gcc/config/csky/csky.c | 96 +++++++++++++++++++---
> gcc/config/csky/csky.h | 34 ++++++--
> gcc/config/csky/csky.md | 84 +++++++++++++++++++
> gcc/testsuite/gcc.dg/builtin-apply2.c | 2 +-
> .../gcc.dg/torture/stackalign/builtin-apply-2.c | 2 +-
> 6 files changed, 200 insertions(+), 20 deletions(-)
>
> diff --git a/gcc/config/csky/csky-protos.h b/gcc/config/csky/csky-protos.h
> index cc1a033..2c02399 100644
> --- a/gcc/config/csky/csky-protos.h
> +++ b/gcc/config/csky/csky-protos.h
> @@ -68,4 +68,6 @@ extern int csky_compute_pushpop_length (rtx *);
>
> extern int csky_default_branch_cost (bool, bool);
> extern bool csky_default_logical_op_non_short_circuit (void);
> +
> +extern void csky_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
> #endif /* GCC_CSKY_PROTOS_H */
> diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c
> index 7ba3ed3..8463d8f 100644
> --- a/gcc/config/csky/csky.c
> +++ b/gcc/config/csky/csky.c
> @@ -328,6 +328,16 @@ csky_cpu_cpp_builtins (cpp_reader *pfile)
> {
> builtin_define ("__csky_hard_float__");
> builtin_define ("__CSKY_HARD_FLOAT__");
> + if (TARGET_HARD_FLOAT_ABI)
> + {
> + builtin_define ("__csky_hard_float_abi__");
> + builtin_define ("__CSKY_HARD_FLOAT_ABI__");
> + }
> + if (TARGET_SINGLE_FPU)
> + {
> + builtin_define ("__csky_hard_float_fpu_sf__");
> + builtin_define ("__CSKY_HARD_FLOAT_FPU_SF__");
> + }
> }
> else
> {
> @@ -1790,9 +1800,22 @@ static rtx
> csky_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
> {
> CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
> + int reg = pcum->reg;
> + machine_mode mode = arg.mode;
>
> - if (*pcum < CSKY_NPARM_REGS)
> - return gen_rtx_REG (arg.mode, CSKY_FIRST_PARM_REGNUM + *pcum);
> + if (FUNCTION_VARG_MODE_P(mode)
> + && !pcum->is_stdarg)
> + {
> + reg = pcum->freg;
> +
> + if (reg < CSKY_NPARM_FREGS)
> + return gen_rtx_REG (mode, CSKY_FIRST_VFP_REGNUM + reg);
> + else
> + return NULL_RTX;
> + }
> +
> + if (reg < CSKY_NPARM_REGS)
> + return gen_rtx_REG (mode, CSKY_FIRST_PARM_REGNUM + reg);
>
> return NULL_RTX;
> }
> @@ -1802,7 +1825,7 @@ csky_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
> MODE and TYPE. */
>
> static int
> -csky_num_arg_regs (machine_mode mode, const_tree type)
> +csky_num_arg_regs (machine_mode mode, const_tree type, bool is_stdarg)
> {
> int size;
>
> @@ -1811,6 +1834,14 @@ csky_num_arg_regs (machine_mode mode, const_tree type)
> else
> size = GET_MODE_SIZE (mode);
>
> + if (TARGET_HARD_FLOAT_ABI
> + && !is_stdarg)
> + {
> + if (CSKY_VREG_MODE_P(mode)
> + && !TARGET_SINGLE_FPU)
> + return ((CSKY_NUM_WORDS (size) + 1) / 2);
> + }
> +
> return CSKY_NUM_WORDS (size);
> }
>
> @@ -1822,12 +1853,23 @@ csky_function_arg_advance (cumulative_args_t pcum_v,
> const function_arg_info &arg)
> {
> CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
> - int param_size = csky_num_arg_regs (arg.mode, arg.type);
> + int *reg = &pcum->reg;
> + machine_mode mode = arg.mode;
>
> - if (*pcum + param_size > CSKY_NPARM_REGS)
> - *pcum = CSKY_NPARM_REGS;
> + int param_size = csky_num_arg_regs (mode, arg.type, pcum->is_stdarg);
> + int param_regs_nums = CSKY_NPARM_REGS;
> +
> + if (FUNCTION_VARG_MODE_P(mode)
> + && !pcum->is_stdarg)
> + {
> + reg = &pcum->freg;
> + param_regs_nums = CSKY_NPARM_FREGS;
> + }
> +
> + if (*reg + param_size > param_regs_nums)
> + *reg = param_regs_nums;
> else
> - *pcum += param_size;
> + *reg += param_size;
> }
>
>
> @@ -1843,6 +1885,12 @@ csky_function_value (const_tree type, const_tree func,
> mode = TYPE_MODE (type);
> size = int_size_in_bytes (type);
>
> + if (FUNCTION_VARG_MODE_P(mode))
> + {
> + mode = promote_function_mode (type, mode, &unsignedp, func, 1);
> + return gen_rtx_REG (mode, CSKY_FIRST_VFP_REGNUM);
> + }
> +
> /* Since we promote return types, we must promote the mode here too. */
> if (INTEGRAL_TYPE_P (type))
> {
> @@ -1877,6 +1925,10 @@ static rtx
> csky_libcall_value (machine_mode mode,
> const_rtx libcall ATTRIBUTE_UNUSED)
> {
> + if (FUNCTION_VARG_MODE_P(mode))
> + {
> + return gen_rtx_REG (mode, CSKY_FIRST_VFP_REGNUM);
> + }
> return gen_rtx_REG (mode, CSKY_FIRST_RET_REGNUM);
> }
>
> @@ -1887,7 +1939,11 @@ csky_libcall_value (machine_mode mode,
> static bool
> csky_function_value_regno_p (const unsigned int regno)
> {
> - return (regno == CSKY_FIRST_RET_REGNUM);
> + if (regno == CSKY_FIRST_RET_REGNUM
> + || (TARGET_HARD_FLOAT_ABI
> + && regno == CSKY_FIRST_VFP_REGNUM))
> + return true;
> + return false;
> }
>
>
> @@ -1912,11 +1968,16 @@ static int
> csky_arg_partial_bytes (cumulative_args_t pcum_v, const function_arg_info &arg)
> {
> CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v);
> - int param_size = csky_num_arg_regs (arg.mode, arg.type);
> + int param_size = csky_num_arg_regs (arg.mode, arg.type, pcum->is_stdarg);
> + int reg = pcum->reg;
> +
> + if (FUNCTION_VARG_MODE_P(arg.mode)
> + && !pcum->is_stdarg)
> + return 0;
>
> - if (*pcum < CSKY_NPARM_REGS
> - && *pcum + param_size > CSKY_NPARM_REGS)
> - return (CSKY_NPARM_REGS - *pcum) * UNITS_PER_WORD;
> + if (reg < CSKY_NPARM_REGS
> + && reg + param_size > CSKY_NPARM_REGS)
> + return (CSKY_NPARM_REGS - reg) * UNITS_PER_WORD;
>
> return 0;
> }
> @@ -1941,7 +2002,7 @@ csky_setup_incoming_varargs (cumulative_args_t pcum_v,
> cfun->machine->uses_anonymous_args = 1;
> local_cum = *pcum;
> csky_function_arg_advance (local_cum_v, arg);
> - regs_to_push = CSKY_NPARM_REGS - local_cum;
> + regs_to_push = CSKY_NPARM_REGS - local_cum.reg;
> if (regs_to_push)
> *pretend_size = regs_to_push * UNITS_PER_WORD;
> }
> @@ -6775,6 +6836,15 @@ csky_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
> return true;
> }
>
> +void
> +csky_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
> + rtx libname ATTRIBUTE_UNUSED,
> + tree fndecl ATTRIBUTE_UNUSED)
> +{
> + memset(pcum, 0, sizeof(*pcum));
> + if (stdarg_p (fntype))
> + pcum->is_stdarg = true;
> +}
>
> struct gcc_target targetm = TARGET_INITIALIZER;
>
> diff --git a/gcc/config/csky/csky.h b/gcc/config/csky/csky.h
> index 8f4090b..190a668 100644
> --- a/gcc/config/csky/csky.h
> +++ b/gcc/config/csky/csky.h
> @@ -133,6 +133,22 @@
> /* Use hardware floating point calling convention. */
> #define TARGET_HARD_FLOAT_ABI (csky_float_abi == CSKY_FLOAT_ABI_HARD)
>
> +#define TARGET_SINGLE_FPU (csky_fpu_index == TARGET_FPU_fpv2_sf)
> +#define TARGET_DOUBLE_FPU (TARGET_HARD_FLOAT && !TARGET_SINGLE_FPU)
> +
> +#define FUNCTION_VARG_REGNO_P(REGNO) \
> + (TARGET_HARD_FLOAT_ABI \
> + && IN_RANGE ((REGNO), CSKY_FIRST_VFP_REGNUM, \
> + CSKY_FIRST_VFP_REGNUM + CSKY_NPARM_FREGS - 1))
> +
> +#define CSKY_VREG_MODE_P(mode) \
> + ((mode) == SFmode || (mode) == DFmode)
> +
> +#define FUNCTION_VARG_MODE_P(mode) \
> + (TARGET_HARD_FLOAT_ABI \
> + && CSKY_VREG_MODE_P(mode) \
> + && !(mode == DFmode && TARGET_SINGLE_FPU))
> +
> /* Number of loads/stores handled by ldm/stm. */
> #define CSKY_MIN_MULTIPLE_STLD 3
> #define CSKY_MAX_MULTIPLE_STLD 12
> @@ -360,7 +376,14 @@ extern int csky_arch_isa_features[];
>
> /* A C type for declaring a variable that is used as the first argument of
> TARGET_ FUNCTION_ARG and other related values. */
> -#define CUMULATIVE_ARGS int
> +#if !defined (USED_FOR_TARGET)
> +typedef struct
> +{
> + int reg;
> + int freg;
> + bool is_stdarg;
> +} CUMULATIVE_ARGS;
> +#endif
>
> /* Initialize a variable CUM of type CUMULATIVE_ARGS
> for a call to a function whose data type is FNTYPE.
> @@ -369,15 +392,16 @@ extern int csky_arch_isa_features[];
> On CSKY, the offset always starts at 0: the first parm reg is always
> the same reg. */
> #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
> - ((CUM) = 0)
> + csky_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (INDIRECT))
>
> /* True if N is a possible register number for function argument passing.
> On the CSKY, r0-r3 are used to pass args.
> The int cast is to prevent a complaint about unsigned comparison to
> zero, since CSKY_FIRST_PARM_REGNUM is zero. */
> -#define FUNCTION_ARG_REGNO_P(REGNO) \
> - (((int)(REGNO) >= CSKY_FIRST_PARM_REGNUM) && \
> - ((REGNO) < (CSKY_NPARM_REGS + CSKY_FIRST_PARM_REGNUM)))
> +#define FUNCTION_ARG_REGNO_P(REGNO) \
> + (((REGNO) >= CSKY_FIRST_PARM_REGNUM \
> + && (REGNO) < (CSKY_NPARM_REGS + CSKY_FIRST_PARM_REGNUM)) \
> + || FUNCTION_VARG_REGNO_P(REGNO))
>
> /* How Large Values Are Returned */
>
> diff --git a/gcc/config/csky/csky.md b/gcc/config/csky/csky.md
> index 15f68f9..7f01fbc 100644
> --- a/gcc/config/csky/csky.md
> +++ b/gcc/config/csky/csky.md
> @@ -50,6 +50,7 @@
> (CSKY_LAST_EH_RETDATA_REGNUM 1)
> (CSKY_EH_STACKADJ_REGNUM 2)
> (CSKY_STACKADJUST_REGNUM 4)
> + (CSKY_NPARM_FREGS 4)
> ])
>
> ;; Supported TLS relocations.
> @@ -100,6 +101,7 @@
>
> ; Support for the eh_return pattern.
> VUNSPEC_EH_RETURN
> + VUNSPEC_BLOCKAGE
> ])
>
>
> @@ -3310,6 +3312,88 @@
> force_reg (Pmode, XEXP (operands[1], 0)));
> }")
>
> +;; Call subroutine returning any type.
> +
> +(define_expand "untyped_call"
> + [(parallel [(call (match_operand 0 "" "")
> + (const_int 0))
> + (match_operand 1 "" "")
> + (match_operand 2 "" "")])]
> + ""
> +{
> + int i;
> +
> + emit_call_insn (gen_call (operands[0], const0_rtx));
> +
> + for (i = 0; i < XVECLEN (operands[2], 0); i++)
> + {
> + rtx set = XVECEXP (operands[2], 0, i);
> + emit_move_insn (SET_DEST (set), SET_SRC (set));
> + }
> +
> + /* The optimizer does not know that the call sets the function value
> + registers we stored in the result block. We avoid problems by
> + claiming that all hard registers are used and clobbered at this
> + point. */
> + emit_insn (gen_blockage ());
> +
> + DONE;
> +})
> +
> +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
> +;; all of memory. This blocks insns from being moved across this point.
> +
> +(define_insn "blockage"
> + [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
> + ""
> + ""
> + [(set_attr "length" "0")])
> +
> +(define_insn "*call_value_internal_vs"
> + [(set (match_operand:SF 0 "register_operand" "=v,v,v")
> + (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S"))
> + (match_operand 2 "" "")))
> + (clobber (reg:SI CSKY_LR_REGNUM))]
> + "TARGET_HARD_FLOAT_ABI"
> + "@
> + jsr\t%1
> + jsr\t%1
> + jbsr\t%1"
> + [(set_attr "length" "2,4,4")
> + (set_attr "type" "call_jsr,call_jsr,call")]
> +)
> +
> +(define_insn "*call_value_internal_vd"
> + [(set (match_operand:DF 0 "register_operand" "=v,v,v")
> + (call (mem:SI (match_operand:SI 1 "csky_call_address_operand" "b, r,S"))
> + (match_operand 2 "" "")))
> + (clobber (reg:SI CSKY_LR_REGNUM))]
> + "TARGET_HARD_FLOAT_ABI && TARGET_DOUBLE_FPU"
> + "@
> + jsr\t%1
> + jsr\t%1
> + jbsr\t%1"
> + [(set_attr "length" "2,4,4")
> + (set_attr "type" "call_jsr,call_jsr,call")]
> +)
> +
> +(define_insn "*call_value_internal_pic_vs"
> + [(set (match_operand:SF 0 "register_operand" "=v")
> + (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X"))
> + (match_operand 2 "" "")))
> + (clobber (reg:SI CSKY_LR_REGNUM))]
> + "flag_pic && TARGET_HARD_FLOAT_ABI"
> + "* return csky_output_call (operands, 1);"
> +)
> +
> +(define_insn "*call_value_internal_pic_vd"
> + [(set (match_operand:DF 0 "register_operand" "=v")
> + (call (mem:SI (match_operand:SI 1 "csky_unspec_operand" "X"))
> + (match_operand 2 "" "")))
> + (clobber (reg:SI CSKY_LR_REGNUM))]
> + "flag_pic && TARGET_HARD_FLOAT_ABI && TARGET_DOUBLE_FPU"
> + "* return csky_output_call (operands, 1);"
> +)
>
> (define_insn "*call_value_internal"
> [(set (match_operand 0 "register_operand" "=r,r,r")
> diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c
> index 06ef24e..9049af5 100644
> --- a/gcc/testsuite/gcc.dg/builtin-apply2.c
> +++ b/gcc/testsuite/gcc.dg/builtin-apply2.c
> @@ -1,7 +1,7 @@
> /* { dg-do run } */
> /* { dg-require-effective-target untyped_assembly } */
> /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "avr-*-* nds32*-*-* amdgcn-*-*" } } */
> -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "riscv*-*-* or1k*-*-* msp430-*-* pru-*-*" } } */
> +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "csky*-*-* riscv*-*-* or1k*-*-* msp430-*-* pru-*-*" } } */
> /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } } */
>
> /* PR target/12503 */
> diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
> index 31585a0..5ec0558 100644
> --- a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
> +++ b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
> @@ -9,7 +9,7 @@
> /* arm_hf_eabi: Variadic funcs use Base AAPCS. Normal funcs use VFP variant.
> avr: Variadic funcs don't pass arguments in registers, while normal funcs
> do. */
> -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* pru-*-* } } } */
> +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { csky*-*-* avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* pru-*-* } } } */
> /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* } { v850*-*-* } } */
> /* { dg-require-effective-target untyped_assembly } */
>
More information about the Gcc-patches
mailing list