aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/csky
diff options
context:
space:
mode:
authorJojo R <jiejie_rong@c-sky.com>2020-09-15 16:08:01 +0800
committerXianmiao Qu <xianmiao_qu@c-sky.com>2020-09-16 10:13:49 +0800
commit01d56aeaffa11959278dd6f6f2c1085cac25a345 (patch)
tree985e7fdf9c0ce505c28a3903d688376f082bcd1c /gcc/config/csky
parent3f3f28de3f62ce6d3b1454d54c4da7569a60e2c6 (diff)
downloadgcc-01d56aeaffa11959278dd6f6f2c1085cac25a345.zip
gcc-01d56aeaffa11959278dd6f6f2c1085cac25a345.tar.gz
gcc-01d56aeaffa11959278dd6f6f2c1085cac25a345.tar.bz2
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.
Diffstat (limited to 'gcc/config/csky')
-rw-r--r--gcc/config/csky/csky-protos.h2
-rw-r--r--gcc/config/csky/csky.c96
-rw-r--r--gcc/config/csky/csky.h34
-rw-r--r--gcc/config/csky/csky.md84
4 files changed, 198 insertions, 18 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 aa05365..5aa2336 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 2644acd..78c9b80 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")