diff options
author | J"orn Rennecke <joern.rennecke@st.com> | 2005-08-23 13:07:16 +0000 |
---|---|---|
committer | Joern Rennecke <amylaar@gcc.gnu.org> | 2005-08-23 14:07:16 +0100 |
commit | a11c004bd747e274becda2edaa8d1ea5bb8f18b8 (patch) | |
tree | f281b1b984d8047564b6344db9e21524ce532824 /gcc/config/sh | |
parent | aec5ba601b0ebaaca5362d32cebc9612aa6d2005 (diff) | |
download | gcc-a11c004bd747e274becda2edaa8d1ea5bb8f18b8.zip gcc-a11c004bd747e274becda2edaa8d1ea5bb8f18b8.tar.gz gcc-a11c004bd747e274becda2edaa8d1ea5bb8f18b8.tar.bz2 |
sh.c (sh_builtin_saveregs): If the number of to-be-saved fp registers is even...
* sh.c (sh_builtin_saveregs): If the number of to-be-saved fp
registers is even, and we have a hardware double precision fp,
align the buffer.
(sh_gimplify_va_arg_expr): For floating point arguments, consider
size of current argument when checking if argument was passed in
registers.
* sh.c (sh_attr_renesas_p): Handle error_mark_node.
From-SVN: r103398
Diffstat (limited to 'gcc/config/sh')
-rw-r--r-- | gcc/config/sh/sh.c | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 9d39ac6..1fbdcee 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -6441,8 +6441,18 @@ sh_builtin_saveregs (void) emit_insn (gen_iorsi3 (addr, addr, GEN_INT (UNITS_PER_WORD))); regbuf = change_address (regbuf, BLKmode, addr); } + else if (STACK_BOUNDARY < 64 && TARGET_FPU_DOUBLE && n_floatregs) + { + rtx addr, mask; + + regbuf = assign_stack_local (BLKmode, bufsize + UNITS_PER_WORD, 0); + addr = copy_to_mode_reg (Pmode, plus_constant (XEXP (regbuf, 0), 4)); + mask = copy_to_mode_reg (Pmode, GEN_INT (-8)); + emit_insn (gen_andsi3 (addr, addr, mask)); + regbuf = change_address (regbuf, BLKmode, addr); + } else - regbuf = assign_stack_local (BLKmode, bufsize, 0); + regbuf = assign_stack_local (BLKmode, bufsize, TARGET_FPU_DOUBLE ? 64 : 0); alias_set = get_varargs_alias_set (); set_mem_alias_set (regbuf, alias_set); @@ -6740,30 +6750,37 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, if (pass_as_float) { - int first_floatreg - = current_function_args_info.arg_count[(int) SH_ARG_FLOAT]; - int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg); + tree next_fp_tmp = create_tmp_var (TREE_TYPE (f_next_fp), NULL); + tree cmp; + bool is_double = size == 8 && TREE_CODE (type) == REAL_TYPE; - tmp = build (GE_EXPR, boolean_type_node, next_fp, next_fp_limit); - tmp = build (COND_EXPR, void_type_node, tmp, + tmp = build1 (ADDR_EXPR, pptr_type_node, next_fp); + tmp = build2 (MODIFY_EXPR, void_type_node, addr, tmp); + gimplify_and_add (tmp, pre_p); + + tmp = build2 (MODIFY_EXPR, ptr_type_node, next_fp_tmp, valist); + gimplify_and_add (tmp, pre_p); + tmp = next_fp_limit; + if (size > 4 && !is_double) + tmp = build2 (PLUS_EXPR, TREE_TYPE (tmp), tmp, + fold_convert (TREE_TYPE (tmp), size_int (4 - size))); + tmp = build (GE_EXPR, boolean_type_node, next_fp_tmp, tmp); + cmp = build (COND_EXPR, void_type_node, tmp, build (GOTO_EXPR, void_type_node, lab_false), NULL); - gimplify_and_add (tmp, pre_p); + if (!is_double) + gimplify_and_add (cmp, pre_p); - if (TYPE_ALIGN (type) > BITS_PER_WORD - || (((TREE_CODE (type) == REAL_TYPE && size == 8) || size == 16) - && (n_floatregs & 1))) + if (TYPE_ALIGN (type) > BITS_PER_WORD || (is_double || size == 16)) { tmp = fold_convert (ptr_type_node, size_int (UNITS_PER_WORD)); - tmp = build (BIT_AND_EXPR, ptr_type_node, next_fp, tmp); - tmp = build (PLUS_EXPR, ptr_type_node, next_fp, tmp); - tmp = build (MODIFY_EXPR, ptr_type_node, next_fp, tmp); + tmp = build (BIT_AND_EXPR, ptr_type_node, next_fp_tmp, tmp); + tmp = build (PLUS_EXPR, ptr_type_node, next_fp_tmp, tmp); + tmp = build (MODIFY_EXPR, ptr_type_node, next_fp_tmp, tmp); gimplify_and_add (tmp, pre_p); } - - tmp = build1 (ADDR_EXPR, pptr_type_node, next_fp); - tmp = build (MODIFY_EXPR, void_type_node, addr, tmp); - gimplify_and_add (tmp, pre_p); + if (is_double) + gimplify_and_add (cmp, pre_p); #ifdef FUNCTION_ARG_SCmode_WART if (TYPE_MODE (type) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN) @@ -6771,10 +6788,12 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree subtype = TREE_TYPE (type); tree real, imag; - imag = std_gimplify_va_arg_expr (valist, subtype, pre_p, NULL); + imag + = std_gimplify_va_arg_expr (next_fp_tmp, subtype, pre_p, NULL); imag = get_initialized_tmp_var (imag, pre_p, NULL); - real = std_gimplify_va_arg_expr (valist, subtype, pre_p, NULL); + real + = std_gimplify_va_arg_expr (next_fp_tmp, subtype, pre_p, NULL); real = get_initialized_tmp_var (real, pre_p, NULL); result = build (COMPLEX_EXPR, type, real, imag); @@ -6791,6 +6810,12 @@ sh_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack); tmp = build (MODIFY_EXPR, void_type_node, addr, tmp); gimplify_and_add (tmp, pre_p); + tmp = build2 (MODIFY_EXPR, ptr_type_node, next_fp_tmp, valist); + gimplify_and_add (tmp, pre_p); + + tmp = build2 (MODIFY_EXPR, ptr_type_node, valist, next_fp_tmp); + gimplify_and_add (tmp, post_p); + valist = next_fp_tmp; } else { @@ -7541,6 +7566,8 @@ sh_attr_renesas_p (tree td) return 0; if (DECL_P (td)) td = TREE_TYPE (td); + if (td == error_mark_node) + return 0; return (lookup_attribute ("renesas", TYPE_ATTRIBUTES (td)) != NULL_TREE); } |