#define TARGET_ADJUST_UNROLL_MAX sh_adjust_unroll_max
#endif
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD sh_secondary_reload
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* Implement TARGET_HANDLE_OPTION. */
if (mode == Pmode || mode == ptr_mode)
{
- rtx op0, op1;
+ rtx op0, op1, opc;
enum tls_model tls_kind;
op0 = operands[0];
op1 = operands[1];
+ if (GET_CODE (op1) == CONST
+ && GET_CODE (XEXP (op1, 0)) == PLUS
+ && tls_symbolic_operand (XEXP (XEXP (op1, 0), 0), Pmode))
+ {
+ opc = XEXP (XEXP (op1, 0), 1);
+ op1 = XEXP (XEXP (op1, 0), 0);
+ }
+ else
+ opc = NULL_RTX;
+
if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
{
rtx tga_op1, tga_ret, tmp, tmp2;
default:
gcc_unreachable ();
}
+ if (opc)
+ emit_insn (gen_addsi3 (op1, op1, force_reg (SImode, opc)));
operands[1] = op1;
}
}
gcc_assert (worker
&& GET_CODE (worker) != CODE_LABEL
&& GET_CODE (worker) != JUMP_INSN);
- } while (recog_memoized (worker) != CODE_FOR_casesi_worker_1);
+ } while (GET_CODE (worker) == NOTE
+ || recog_memoized (worker) != CODE_FOR_casesi_worker_1);
wpat = PATTERN (worker);
wpat0 = XVECEXP (wpat, 0, 0);
wpat1 = XVECEXP (wpat, 0, 1);
f_next_fp_limit = TREE_CHAIN (f_next_fp);
f_next_stack = TREE_CHAIN (f_next_fp_limit);
- next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
- NULL_TREE);
- next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
- valist, f_next_o_limit, NULL_TREE);
- next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp,
+ next_o = build3 (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
NULL_TREE);
- next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
- valist, f_next_fp_limit, NULL_TREE);
- next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
- valist, f_next_stack, NULL_TREE);
+ next_o_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
+ valist, f_next_o_limit, NULL_TREE);
+ next_fp = build3 (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp,
+ NULL_TREE);
+ next_fp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
+ valist, f_next_fp_limit, NULL_TREE);
+ next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
+ valist, f_next_stack, NULL_TREE);
/* Call __builtin_saveregs. */
u = make_tree (ptr_type_node, expand_builtin_saveregs ());
- t = build (MODIFY_EXPR, ptr_type_node, next_fp, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_fp, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
nfp = 8 - nfp;
else
nfp = 0;
- u = fold (build (PLUS_EXPR, ptr_type_node, u,
- build_int_cst (NULL_TREE, UNITS_PER_WORD * nfp)));
- t = build (MODIFY_EXPR, ptr_type_node, next_fp_limit, u);
+ u = fold_build2 (PLUS_EXPR, ptr_type_node, u,
+ build_int_cst (NULL_TREE, UNITS_PER_WORD * nfp));
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_fp_limit, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- t = build (MODIFY_EXPR, ptr_type_node, next_o, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_o, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
nint = 4 - nint;
else
nint = 0;
- u = fold (build (PLUS_EXPR, ptr_type_node, u,
- build_int_cst (NULL_TREE, UNITS_PER_WORD * nint)));
- t = build (MODIFY_EXPR, ptr_type_node, next_o_limit, u);
+ u = fold_build2 (PLUS_EXPR, ptr_type_node, u,
+ build_int_cst (NULL_TREE, UNITS_PER_WORD * nint));
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_o_limit, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
u = make_tree (ptr_type_node, nextarg);
- t = build (MODIFY_EXPR, ptr_type_node, next_stack, u);
+ t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
f_next_fp_limit = TREE_CHAIN (f_next_fp);
f_next_stack = TREE_CHAIN (f_next_fp_limit);
- next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
- NULL_TREE);
- next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
- valist, f_next_o_limit, NULL_TREE);
- next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp),
- valist, f_next_fp, NULL_TREE);
- next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
- valist, f_next_fp_limit, NULL_TREE);
- next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
- valist, f_next_stack, NULL_TREE);
+ next_o = build3 (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o,
+ NULL_TREE);
+ next_o_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
+ valist, f_next_o_limit, NULL_TREE);
+ next_fp = build3 (COMPONENT_REF, TREE_TYPE (f_next_fp),
+ valist, f_next_fp, NULL_TREE);
+ next_fp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
+ valist, f_next_fp_limit, NULL_TREE);
+ next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack),
+ valist, f_next_stack, NULL_TREE);
/* Structures with a single member with a distinct mode are passed
like their member. This is relevant if the latter has a REAL_TYPE
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);
+ tmp = build2 (GE_EXPR, boolean_type_node, next_fp_tmp, tmp);
+ cmp = build3 (COND_EXPR, void_type_node, tmp,
+ build1 (GOTO_EXPR, void_type_node, lab_false),
+ NULL_TREE);
if (!is_double)
gimplify_and_add (cmp, pre_p);
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);
- tmp = build (PLUS_EXPR, ptr_type_node, next_fp_tmp, tmp);
- tmp = build (MODIFY_EXPR, ptr_type_node, next_fp_tmp, tmp);
+ tmp = build2 (BIT_AND_EXPR, ptr_type_node, next_fp_tmp, tmp);
+ tmp = build2 (PLUS_EXPR, ptr_type_node, next_fp_tmp, tmp);
+ tmp = build2 (MODIFY_EXPR, ptr_type_node, next_fp_tmp, tmp);
gimplify_and_add (tmp, pre_p);
}
if (is_double)
= 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);
+ result = build2 (COMPLEX_EXPR, type, real, imag);
result = get_initialized_tmp_var (result, pre_p, NULL);
}
#endif /* FUNCTION_ARG_SCmode_WART */
- tmp = build (GOTO_EXPR, void_type_node, lab_over);
+ tmp = build1 (GOTO_EXPR, void_type_node, lab_over);
gimplify_and_add (tmp, pre_p);
- tmp = build (LABEL_EXPR, void_type_node, lab_false);
+ tmp = build1 (LABEL_EXPR, void_type_node, lab_false);
gimplify_and_add (tmp, pre_p);
tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
- tmp = build (MODIFY_EXPR, void_type_node, addr, tmp);
+ 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);
else
{
tmp = fold_convert (ptr_type_node, size_int (rsize));
- tmp = build (PLUS_EXPR, ptr_type_node, next_o, tmp);
- tmp = build (GT_EXPR, boolean_type_node, tmp, next_o_limit);
- tmp = build (COND_EXPR, void_type_node, tmp,
- build (GOTO_EXPR, void_type_node, lab_false),
- NULL);
+ tmp = build2 (PLUS_EXPR, ptr_type_node, next_o, tmp);
+ tmp = build2 (GT_EXPR, boolean_type_node, tmp, next_o_limit);
+ tmp = build3 (COND_EXPR, void_type_node, tmp,
+ build1 (GOTO_EXPR, void_type_node, lab_false),
+ NULL_TREE);
gimplify_and_add (tmp, pre_p);
tmp = build1 (ADDR_EXPR, pptr_type_node, next_o);
- tmp = build (MODIFY_EXPR, void_type_node, addr, tmp);
+ tmp = build2 (MODIFY_EXPR, void_type_node, addr, tmp);
gimplify_and_add (tmp, pre_p);
- tmp = build (GOTO_EXPR, void_type_node, lab_over);
+ tmp = build1 (GOTO_EXPR, void_type_node, lab_over);
gimplify_and_add (tmp, pre_p);
- tmp = build (LABEL_EXPR, void_type_node, lab_false);
+ tmp = build1 (LABEL_EXPR, void_type_node, lab_false);
gimplify_and_add (tmp, pre_p);
if (size > 4 && ! TARGET_SH4)
{
- tmp = build (MODIFY_EXPR, ptr_type_node, next_o, next_o_limit);
+ tmp = build2 (MODIFY_EXPR, ptr_type_node, next_o, next_o_limit);
gimplify_and_add (tmp, pre_p);
}
tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
- tmp = build (MODIFY_EXPR, void_type_node, addr, tmp);
+ tmp = build2 (MODIFY_EXPR, void_type_node, addr, tmp);
gimplify_and_add (tmp, pre_p);
}
if (!result)
{
- tmp = build (LABEL_EXPR, void_type_node, lab_over);
+ tmp = build1 (LABEL_EXPR, void_type_node, lab_over);
gimplify_and_add (tmp, pre_p);
}
}
tmp = std_gimplify_va_arg_expr (valist, type, pre_p, NULL);
if (result)
{
- tmp = build (MODIFY_EXPR, void_type_node, result, tmp);
+ tmp = build2 (MODIFY_EXPR, void_type_node, result, tmp);
gimplify_and_add (tmp, pre_p);
- tmp = build (LABEL_EXPR, void_type_node, lab_over);
+ tmp = build1 (LABEL_EXPR, void_type_node, lab_over);
gimplify_and_add (tmp, pre_p);
}
else
return fpscr_rtx;
}
+static GTY(()) tree fpscr_values;
+
+static void
+emit_fpu_switch (rtx scratch, int index)
+{
+ rtx dst, src;
+
+ if (fpscr_values == NULL)
+ {
+ tree t;
+
+ t = build_index_type (integer_one_node);
+ t = build_array_type (integer_type_node, t);
+ t = build_decl (VAR_DECL, get_identifier ("__fpscr_values"), t);
+ DECL_ARTIFICIAL (t) = 1;
+ DECL_IGNORED_P (t) = 1;
+ DECL_EXTERNAL (t) = 1;
+ TREE_STATIC (t) = 1;
+ TREE_PUBLIC (t) = 1;
+ TREE_USED (t) = 1;
+
+ fpscr_values = t;
+ }
+
+ src = DECL_RTL (fpscr_values);
+ if (no_new_pseudos)
+ {
+ emit_move_insn (scratch, XEXP (src, 0));
+ if (index != 0)
+ emit_insn (gen_addsi3 (scratch, scratch, GEN_INT (index * 4)));
+ src = adjust_automodify_address (src, PSImode, scratch, index * 4);
+ }
+ else
+ src = adjust_address (src, PSImode, index * 4);
+
+ dst = get_fpscr_rtx ();
+ emit_move_insn (dst, src);
+}
+
void
emit_sf_insn (rtx pat)
{
fpscr_set_from_mem (int mode, HARD_REG_SET regs_live)
{
enum attr_fp_mode fp_mode = mode;
+ enum attr_fp_mode norm_mode = ACTUAL_NORMAL_MODE (FP_MODE);
rtx addr_reg = get_free_reg (regs_live);
- if (fp_mode == (enum attr_fp_mode) ACTUAL_NORMAL_MODE (FP_MODE))
- emit_insn (gen_fpu_switch1 (addr_reg));
- else
- emit_insn (gen_fpu_switch0 (addr_reg));
+ emit_fpu_switch (addr_reg, fp_mode == norm_mode);
}
/* Is the given character a logical line separator for the assembler? */
&& REGCLASS_HAS_FP_REG (dstclass))
return 4;
+ if (REGCLASS_HAS_FP_REG (dstclass) && srcclass == T_REGS)
+ return ((TARGET_HARD_SH4 && !optimize_size) ? 10 : 7);
+
if ((REGCLASS_HAS_FP_REG (dstclass) && srcclass == MAC_REGS)
|| (dstclass == MAC_REGS && REGCLASS_HAS_FP_REG (srcclass)))
return 9;
if (TREE_CODE (type) != ARRAY_TYPE
|| ! TYPE_SIZE (type) || ! TYPE_SIZE_UNIT (type))
break;
- size_tree = fold (build (TRUNC_DIV_EXPR,
+ size_tree = fold_build2 (TRUNC_DIV_EXPR,
bitsizetype,
TYPE_SIZE (type),
- TYPE_SIZE_UNIT (type)));
+ TYPE_SIZE_UNIT (type));
if (TREE_CODE (size_tree) == INTEGER_CST
&& ! TREE_INT_CST_HIGH (size_tree)
&& TREE_INT_CST_LOW (size_tree) < max_iterations)
return fnaddr;
}
+enum reg_class
+sh_secondary_reload (bool in_p, rtx x, enum reg_class class,
+ enum machine_mode mode, secondary_reload_info *sri)
+{
+ if (in_p)
+ {
+ if (REGCLASS_HAS_FP_REG (class)
+ && ! TARGET_SHMEDIA
+ && immediate_operand ((x), mode)
+ && ! ((fp_zero_operand (x) || fp_one_operand (x))
+ && mode == SFmode && fldi_ok ()))
+ switch (mode)
+ {
+ case SFmode:
+ sri->icode = CODE_FOR_reload_insf__frn;
+ return NO_REGS;
+ case DFmode:
+ sri->icode = CODE_FOR_reload_indf__frn;
+ return NO_REGS;
+ case SImode:
+ /* ??? If we knew that we are in the appropriate mode -
+ single precision - we could use a reload pattern directly. */
+ return FPUL_REGS;
+ default:
+ abort ();
+ }
+ if (class == FPUL_REGS
+ && ((GET_CODE (x) == REG
+ && (REGNO (x) == MACL_REG || REGNO (x) == MACH_REG
+ || REGNO (x) == T_REG))
+ || GET_CODE (x) == PLUS))
+ return GENERAL_REGS;
+ if (class == FPUL_REGS && immediate_operand (x, mode))
+ {
+ if (GET_CODE (x) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (x)))
+ return GENERAL_REGS;
+ sri->icode = CODE_FOR_reload_insi__i_fpul;
+ return NO_REGS;
+ }
+ if (class == FPSCR_REGS
+ && ((GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
+ || (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS)))
+ return GENERAL_REGS;
+ if (REGCLASS_HAS_FP_REG (class)
+ && TARGET_SHMEDIA
+ && immediate_operand (x, mode)
+ && x != CONST0_RTX (GET_MODE (x))
+ && GET_MODE (x) != V4SFmode)
+ return GENERAL_REGS;
+ if ((mode == QImode || mode == HImode)
+ && TARGET_SHMEDIA && inqhi_operand (x, mode))
+ {
+ sri->icode = ((mode == QImode)
+ ? CODE_FOR_reload_inqi : CODE_FOR_reload_inhi);
+ return NO_REGS;
+ }
+ if (TARGET_SHMEDIA && class == GENERAL_REGS
+ && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
+ return TARGET_REGS;
+ } /* end of input-only processing. */
+
+ if (((REGCLASS_HAS_FP_REG (class)
+ && (GET_CODE (x) == REG
+ && (GENERAL_OR_AP_REGISTER_P (REGNO (x))
+ || (FP_REGISTER_P (REGNO (x)) && mode == SImode
+ && TARGET_FMOVD))))
+ || (REGCLASS_HAS_GENERAL_REG (class)
+ && GET_CODE (x) == REG
+ && FP_REGISTER_P (REGNO (x))))
+ && ! TARGET_SHMEDIA
+ && (mode == SFmode || mode == SImode))
+ return FPUL_REGS;
+ if ((class == FPUL_REGS
+ || (REGCLASS_HAS_FP_REG (class)
+ && ! TARGET_SHMEDIA && mode == SImode))
+ && (GET_CODE (x) == MEM
+ || (GET_CODE (x) == REG
+ && (REGNO (x) >= FIRST_PSEUDO_REGISTER
+ || REGNO (x) == T_REG
+ || system_reg_operand (x, VOIDmode)))))
+ {
+ if (class == FPUL_REGS)
+ return GENERAL_REGS;
+ return FPUL_REGS;
+ }
+ if ((class == TARGET_REGS
+ || (TARGET_SHMEDIA && class == SIBCALL_REGS))
+ && !EXTRA_CONSTRAINT_Csy (x)
+ && (GET_CODE (x) != REG || ! GENERAL_REGISTER_P (REGNO (x))))
+ return GENERAL_REGS;
+ if ((class == MAC_REGS || class == PR_REGS)
+ && GET_CODE (x) == REG && ! GENERAL_REGISTER_P (REGNO (x))
+ && class != REGNO_REG_CLASS (REGNO (x)))
+ return GENERAL_REGS;
+ if (class != GENERAL_REGS && GET_CODE (x) == REG
+ && TARGET_REGISTER_P (REGNO (x)))
+ return GENERAL_REGS;
+ return NO_REGS;
+}
+
enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT;
/* This defines the storage for the variable part of a -mboard= option.