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:
parent
3f3f28de3f
commit
01d56aeaff
6 changed files with 200 additions and 20 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 } */
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue