C-SKY: Support -mfloat-abi=hard.

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.
This commit is contained in:
Jojo R 2020-09-15 16:08:01 +08:00 committed by Xianmiao Qu
parent 3f3f28de3f
commit 01d56aeaff
6 changed files with 200 additions and 20 deletions

View file

@ -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 */

View file

@ -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 (*pcum < CSKY_NPARM_REGS
&& *pcum + param_size > CSKY_NPARM_REGS)
return (CSKY_NPARM_REGS - *pcum) * UNITS_PER_WORD;
if (FUNCTION_VARG_MODE_P(arg.mode)
&& !pcum->is_stdarg)
return 0;
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;

View file

@ -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 */

View file

@ -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")

View file

@ -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 */

View file

@ -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 } */