/* Subroutines for assembler code output on the TMS320C[34]x
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003,
+ 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Some output-actions in c4x.md need these. */
#include "config.h"
#include "optabs.h"
#include "libfuncs.h"
#include "flags.h"
-#include "loop.h"
#include "recog.h"
#include "ggc.h"
#include "cpplib.h"
#include "tm_p.h"
#include "target.h"
#include "target-def.h"
+#include "langhooks.h"
rtx smulhi3_libfunc;
rtx umulhi3_libfunc;
rtx c4x_compare_op0;
rtx c4x_compare_op1;
-const char *c4x_rpts_cycles_string;
-int c4x_rpts_cycles = 0; /* Max. cycles for RPTS. */
-const char *c4x_cpu_version_string;
int c4x_cpu_version = 40; /* CPU version C30/31/32/33/40/44. */
/* Pragma definitions. */
tree naked_tree = NULL_TREE;
/* Forward declarations */
+static bool c4x_handle_option (size_t, const char *, int);
static int c4x_isr_reg_used_p (unsigned int);
static int c4x_leaf_function_p (void);
static int c4x_naked_function_p (void);
-static int c4x_immed_float_p (rtx);
-static int c4x_a_register (rtx);
-static int c4x_x_register (rtx);
static int c4x_immed_int_constant (rtx);
static int c4x_immed_float_constant (rtx);
-static int c4x_K_constant (rtx);
-static int c4x_N_constant (rtx);
-static int c4x_O_constant (rtx);
static int c4x_R_indirect (rtx);
-static int c4x_S_indirect (rtx);
static void c4x_S_address_parse (rtx , int *, int *, int *, int *);
static int c4x_valid_operands (enum rtx_code, rtx *, enum machine_mode, int);
static int c4x_arn_reg_operand (rtx, enum machine_mode, unsigned int);
static tree c4x_handle_fntype_attribute (tree *, tree, tree, int, bool *);
const struct attribute_spec c4x_attribute_table[];
static void c4x_insert_attributes (tree, tree *);
-static void c4x_asm_named_section (const char *, unsigned int);
+static void c4x_asm_named_section (const char *, unsigned int, tree);
static int c4x_adjust_cost (rtx, rtx, rtx, int);
static void c4x_globalize_label (FILE *, const char *);
static bool c4x_rtx_costs (rtx, int, int, int *);
static void c4x_init_libfuncs (void);
static void c4x_external_libcall (rtx);
static rtx c4x_struct_value_rtx (tree, int);
+static tree c4x_gimplify_va_arg_expr (tree, tree, tree *, tree *);
\f
/* Initialize the GCC target structure. */
#undef TARGET_ASM_BYTE_OP
#undef TARGET_ASM_EXTERNAL_LIBCALL
#define TARGET_ASM_EXTERNAL_LIBCALL c4x_external_libcall
+/* Play safe, not the fastest code. */
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (MASK_ALIASES | MASK_PARALLEL \
+ | MASK_PARALLEL_MPY | MASK_RPTB)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION c4x_handle_option
+
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
#undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX c4x_struct_value_rtx
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR c4x_gimplify_va_arg_expr
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
-/* Override command line options.
- Called once after all options have been parsed.
- Mostly we process the processor
- type and sometimes adjust other TARGET_ options. */
+/* Implement TARGET_HANDLE_OPTION. */
-void
-c4x_override_options (void)
+static bool
+c4x_handle_option (size_t code, const char *arg, int value)
{
- if (c4x_rpts_cycles_string)
- c4x_rpts_cycles = atoi (c4x_rpts_cycles_string);
- else
- c4x_rpts_cycles = 0;
-
- if (TARGET_C30)
- c4x_cpu_version = 30;
- else if (TARGET_C31)
- c4x_cpu_version = 31;
- else if (TARGET_C32)
- c4x_cpu_version = 32;
- else if (TARGET_C33)
- c4x_cpu_version = 33;
- else if (TARGET_C40)
- c4x_cpu_version = 40;
- else if (TARGET_C44)
- c4x_cpu_version = 44;
- else
- c4x_cpu_version = 40;
-
- /* -mcpu=xx overrides -m40 etc. */
- if (c4x_cpu_version_string)
+ switch (code)
{
- const char *p = c4x_cpu_version_string;
-
- /* Also allow -mcpu=c30 etc. */
- if (*p == 'c' || *p == 'C')
- p++;
- c4x_cpu_version = atoi (p);
- }
-
- target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C33_FLAG |
- C40_FLAG | C44_FLAG);
+ case OPT_m30: c4x_cpu_version = 30; return true;
+ case OPT_m31: c4x_cpu_version = 31; return true;
+ case OPT_m32: c4x_cpu_version = 32; return true;
+ case OPT_m33: c4x_cpu_version = 33; return true;
+ case OPT_m40: c4x_cpu_version = 40; return true;
+ case OPT_m44: c4x_cpu_version = 44; return true;
+
+ case OPT_mcpu_:
+ if (arg[0] == 'c' || arg[0] == 'C')
+ arg++;
+ value = atoi (arg);
+ switch (value)
+ {
+ case 30: case 31: case 32: case 33: case 40: case 44:
+ c4x_cpu_version = value;
+ return true;
+ }
+ return false;
- switch (c4x_cpu_version)
- {
- case 30: target_flags |= C30_FLAG; break;
- case 31: target_flags |= C31_FLAG; break;
- case 32: target_flags |= C32_FLAG; break;
- case 33: target_flags |= C33_FLAG; break;
- case 40: target_flags |= C40_FLAG; break;
- case 44: target_flags |= C44_FLAG; break;
default:
- warning ("unknown CPU version %d, using 40.\n", c4x_cpu_version);
- c4x_cpu_version = 40;
- target_flags |= C40_FLAG;
+ return true;
}
+}
- if (TARGET_C30 || TARGET_C31 || TARGET_C32 || TARGET_C33)
- target_flags |= C3X_FLAG;
- else
- target_flags &= ~C3X_FLAG;
+/* Override command line options.
+ Called once after all options have been parsed.
+ Mostly we process the processor
+ type and sometimes adjust other TARGET_ options. */
+void
+c4x_override_options (void)
+{
/* Convert foo / 8.0 into foo * 0.125, etc. */
set_fast_math_flags (1);
This provides compatibility with the old -mno-aliases option. */
if (! TARGET_ALIASES && ! flag_argument_noalias)
flag_argument_noalias = 1;
+
+ if (!TARGET_C3X)
+ target_flags |= MASK_MPYI | MASK_DB;
+
+ if (optimize < 2)
+ target_flags &= ~(MASK_RPTB | MASK_PARALLEL);
+
+ if (!TARGET_PARALLEL)
+ target_flags &= ~MASK_PARALLEL_MPY;
}
int
c4x_hard_regno_rename_ok (unsigned int regno1, unsigned int regno2)
{
- /* We can not copy call saved registers from mode QI into QF or from
+ /* We cannot copy call saved registers from mode QI into QF or from
mode QF into QI. */
if (IS_FLOAT_CALL_SAVED_REGNO (regno1) && IS_INT_CALL_SAVED_REGNO (regno2))
return 0;
if ((mode = TYPE_MODE (type)))
{
- if (! MUST_PASS_IN_STACK (mode, type))
+ if (! targetm.calls.must_pass_in_stack (mode, type))
{
/* Look for float, double, or long double argument. */
if (mode == QFmode || mode == HFmode)
if (! TARGET_MEMPARM
&& named
&& type
- && ! MUST_PASS_IN_STACK (mode, type))
+ && ! targetm.calls.must_pass_in_stack (mode, type))
{
/* Look for float, double, or long double argument. */
if (mode == QFmode || mode == HFmode)
if (! TARGET_MEMPARM
&& named
&& type
- && ! MUST_PASS_IN_STACK (mode, type))
+ && ! targetm.calls.must_pass_in_stack (mode, type))
{
/* Look for float, double, or long double argument. */
if (mode == QFmode || mode == HFmode)
/* C[34]x arguments grow in weird ways (downwards) that the standard
varargs stuff can't handle.. */
-rtx
-c4x_va_arg (tree valist, tree type)
+
+static tree
+c4x_gimplify_va_arg_expr (tree valist, tree type,
+ tree *pre_p ATTRIBUTE_UNUSED,
+ tree *post_p ATTRIBUTE_UNUSED)
{
tree t;
+ bool indirect;
+
+ indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+ if (indirect)
+ type = build_pointer_type (type);
- t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
- build_int_2 (int_size_in_bytes (type), 0));
- TREE_SIDE_EFFECTS (t) = 1;
+ t = build2 (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
+ build_int_cst (NULL_TREE, int_size_in_bytes (type)));
+ t = fold_convert (build_pointer_type (type), t);
+ t = build_va_arg_indirect_ref (t);
- return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
+ if (indirect)
+ t = build_va_arg_indirect_ref (t);
+
+ return t;
}
/* Only save/restore regs in leaf function that are used. */
if (c4x_leaf_function)
- return regs_ever_live[regno] && fixed_regs[regno] == 0;
+ return df_regs_ever_live_p (regno) && fixed_regs[regno] == 0;
/* Only save/restore regs that are used by the ISR and regs
that are likely to be used by functions the ISR calls
if they are not fixed. */
return IS_EXT_REGNO (regno)
- || ((regs_ever_live[regno] || call_used_regs[regno])
+ || ((df_regs_ever_live_p (regno) || call_used_regs[regno])
&& fixed_regs[regno] == 0);
}
to save/restore the registers we actually use.
For the global variable leaf_function to be set, we need
to define LEAF_REGISTERS and all that it entails.
- Let's check ourselves... */
+ Let's check ourselves.... */
if (lookup_attribute ("leaf_pretend",
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
/* We need to clear the repeat mode flag if the ISR is
going to use a RPTB instruction or uses the RC, RS, or RE
registers. */
- if (regs_ever_live[RC_REGNO]
- || regs_ever_live[RS_REGNO]
- || regs_ever_live[RE_REGNO])
+ if (df_regs_ever_live_p (RC_REGNO)
+ || df_regs_ever_live_p (RS_REGNO)
+ || df_regs_ever_live_p (RE_REGNO))
{
insn = emit_insn (gen_andn_st (GEN_INT(~0x100)));
RTX_FRAME_RELATED_P (insn) = 1;
}
else
{
- /* If we use ar3, we need to push it. */
+ /* If we use ar3, we need to push it. */
dont_push_ar3 = 0;
if ((size != 0) || (current_function_args_size != 0))
{
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
- if (regs_ever_live[regno] && ! call_used_regs[regno])
+ if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
{
if (IS_FLOAT_CALL_SAVED_REGNO (regno))
{
where required. */
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
{
- if (regs_ever_live[regno] && ! call_used_regs[regno])
+ if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
{
if (regno == AR3_REGNO && dont_pop_ar3)
continue;
&& ! get_frame_size ())
{
for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
- if (regs_ever_live[regno] && ! call_used_regs[regno]
+ if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]
&& (regno != AR3_REGNO))
return 1;
return 0;
&& dp_reg_operand (XEXP (op1, 0), mode))
{
/* expand_increment will sometimes create a LO_SUM immediate
- address. Undo this sillyness. */
+ address. Undo this silliness. */
op1 = XEXP (op1, 1);
}
/* Return nonzero if the floating point operand will fit
in the immediate field. */
-static int
+int
c4x_immed_float_p (rtx op)
{
long convval[2];
Before we can create a repeat block looping instruction we have to
verify that there are no jumps outside the loop and no jumps outside
the loop go into this loop. This can happen in the basic blocks reorder
- pass. The C4x cpu can not handle this. */
+ pass. The C4x cpu cannot handle this. */
static int
c4x_label_ref_used_p (rtx x, rtx code_label)
if (insn == start_label)
break;
- /* Note found then we can not use a rptb or rpts. The label was
+ /* Note found then we cannot use a rptb or rpts. The label was
probably moved by the basic block reorder pass. */
if (! insn)
return 0;
rtx count_reg;
/* If the count register has not been allocated to RC, say if
- there is a movstr pattern in the loop, then do not insert a
+ there is a movmem pattern in the loop, then do not insert a
RPTB instruction. Instead we emit a decrement and branch
at the end of the loop. */
count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0);
if (! c4x_rptb_valid_p (insn, start_label))
{
- /* We can not use the rptb insn. Replace it so reorg can use
+ /* We cannot use the rptb insn. Replace it so reorg can use
the delay slots of the jump insn. */
emit_insn_before (gen_addqi3 (count_reg, count_reg, constm1_rtx), insn);
emit_insn_before (gen_cmpqi (count_reg, const0_rtx), insn);
with only the 'deleted' bit set. Transform it into a note
to avoid confusion of subsequent processing. */
if (INSN_DELETED_P (old))
- {
- PUT_CODE (old, NOTE);
- NOTE_LINE_NUMBER (old) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (old) = 0;
- }
+ SET_INSN_DELETED (old);
}
}
}
-static int
+int
c4x_a_register (rtx op)
{
return REG_P (op) && IS_ADDR_OR_PSEUDO_REG (op);
}
-static int
+int
c4x_x_register (rtx op)
{
return REG_P (op) && IS_INDEX_OR_PSEUDO_REG (op);
}
-static int
+int
c4x_K_constant (rtx op)
{
if (TARGET_C3X || ! c4x_immed_int_constant (op))
}
-static int
+int
c4x_N_constant (rtx op)
{
return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
}
-static int
+int
c4x_O_constant (rtx op)
{
return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
}
-static int
+int
c4x_S_indirect (rtx op)
{
enum machine_mode mode = GET_MODE (op);
}
-/* Match any operand. */
-
-int
-any_operand (register rtx op ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return 1;
-}
-
-
-/* Nonzero if OP is a floating point value with value 0.0. */
-
-int
-fp_zero_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- REAL_VALUE_TYPE r;
-
- if (GET_CODE (op) != CONST_DOUBLE)
- return 0;
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- return REAL_VALUES_EQUAL (r, dconst0);
-}
-
-
-int
-const_operand (register rtx op, register enum machine_mode mode)
-{
- switch (mode)
- {
- case QFmode:
- case HFmode:
- if (GET_CODE (op) != CONST_DOUBLE
- || GET_MODE (op) != mode
- || GET_MODE_CLASS (mode) != MODE_FLOAT)
- return 0;
-
- return c4x_immed_float_p (op);
-
-#if Pmode != QImode
- case Pmode:
-#endif
- case QImode:
- if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
-
- if (GET_CODE (op) != CONST_INT
- || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
- || GET_MODE_CLASS (mode) != MODE_INT)
- return 0;
-
- return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
-
- case HImode:
- return 0;
-
- default:
- return 0;
- }
-}
-
-
-int
-stik_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return c4x_K_constant (op);
-}
-
-
-int
-not_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return c4x_N_constant (op);
-}
-
-
-int
-reg_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG
- && GET_MODE (op) == QFmode)
- return 0;
- return register_operand (op, mode);
-}
-
-
int
mixed_subreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
}
-/* Extended precision register R0-R1. */
-
-int
-r0r1_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
-}
-
-
-/* Extended precision register R2-R3. */
-
-int
-r2r3_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
-}
-
-
-/* Low extended precision register R0-R7. */
-
-int
-ext_low_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
-}
-
-
-/* Extended precision register. */
-
-int
-ext_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (! REG_P (op))
- return 0;
- return IS_EXT_OR_PSEUDO_REG (op);
-}
-
-
-/* Standard precision register. */
-
-int
-std_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
-}
-
-/* Standard precision or normal register. */
-
-int
-std_or_reg_operand (rtx op, enum machine_mode mode)
-{
- if (reload_in_progress)
- return std_reg_operand (op, mode);
- return reg_operand (op, mode);
-}
-
-/* Address register. */
-
-int
-addr_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- return c4x_a_register (op);
-}
-
-
-/* Index register. */
-
-int
-index_reg_operand (rtx op, enum machine_mode mode)
-{
- if (! reg_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return c4x_x_register (op);
-}
-
-
-/* DP register. */
-
-int
-dp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
-}
-
-
-/* SP register. */
-
-int
-sp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
-}
-
-
-/* ST register. */
-
-int
-st_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
-}
-
-
-/* RC register. */
-
-int
-rc_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
-}
-
-
-int
-call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (REG_P (op) || symbolic_address_operand (op, mode));
-}
-
-
-/* Symbolic address operand. */
-
-int
-symbolic_address_operand (register rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
- default:
- return 0;
- }
-}
-
-
-/* Check dst operand of a move instruction. */
-
-int
-dst_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG
- && mixed_subreg_operand (op, mode))
- return 0;
-
- if (REG_P (op))
- return reg_operand (op, mode);
-
- return nonimmediate_operand (op, mode);
-}
-
-
-/* Check src operand of two operand arithmetic instructions. */
-
-int
-src_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG
- && mixed_subreg_operand (op, mode))
- return 0;
-
- if (REG_P (op))
- return reg_operand (op, mode);
-
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (GET_CODE (op) == CONST_INT)
- return (mode == QImode || mode == Pmode || mode == HImode)
- && c4x_I_constant (op);
-
- /* We don't like CONST_DOUBLE integers. */
- if (GET_CODE (op) == CONST_DOUBLE)
- return c4x_H_constant (op);
-
- /* Disallow symbolic addresses. Only the predicate
- symbolic_address_operand will match these. */
- if (GET_CODE (op) == SYMBOL_REF
- || GET_CODE (op) == LABEL_REF
- || GET_CODE (op) == CONST)
- return 0;
-
- /* If TARGET_LOAD_DIRECT_MEMS is nonzero, disallow direct memory
- access to symbolic addresses. These operands will get forced
- into a register and the movqi expander will generate a
- HIGH/LO_SUM pair if TARGET_EXPOSE_LDP is nonzero. */
- if (GET_CODE (op) == MEM
- && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- || GET_CODE (XEXP (op, 0)) == LABEL_REF
- || GET_CODE (XEXP (op, 0)) == CONST)))
- return !TARGET_EXPOSE_LDP &&
- ! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
-
- return general_operand (op, mode);
-}
-
-
-int
-src_hi_operand (rtx op, enum machine_mode mode)
-{
- if (c4x_O_constant (op))
- return 1;
- return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand logical instructions. */
-
-int
-lsrc_operand (rtx op, enum machine_mode mode)
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode != QImode && mode != Pmode)
- fatal_insn ("mode not QImode", op);
-
- if (GET_CODE (op) == CONST_INT)
- return c4x_L_constant (op) || c4x_J_constant (op);
-
- return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand tricky instructions. */
-
-int
-tsrc_operand (rtx op, enum machine_mode mode)
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode != QImode && mode != Pmode)
- fatal_insn ("mode not QImode", op);
-
- if (GET_CODE (op) == CONST_INT)
- return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
-
- return src_operand (op, mode);
-}
-
-
-/* Check src operand of two operand non immedidate instructions. */
-
-int
-nonimmediate_src_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
- return 0;
-
- return src_operand (op, mode);
-}
-
-
-/* Check logical src operand of two operand non immedidate instructions. */
-
-int
-nonimmediate_lsrc_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
- return 0;
-
- return lsrc_operand (op, mode);
-}
-
-
-int
-reg_or_const_operand (rtx op, enum machine_mode mode)
-{
- return reg_operand (op, mode) || const_operand (op, mode);
-}
-
-
-/* Check for indirect operands allowable in parallel instruction. */
-
-int
-par_ind_operand (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- return c4x_S_indirect (op);
-}
-
-
-/* Check for operands allowable in parallel instruction. */
-
-int
-parallel_operand (rtx op, enum machine_mode mode)
-{
- return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
-}
-
-
static void
c4x_S_address_parse (rtx op, int *base, int *incdec, int *index, int *disp)
{
if (! TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1))
return 1;
- /* We can not optimize the case where op1 and op2 refer to the same
+ /* We cannot optimize the case where op1 and op2 refer to the same
address. */
if (base0 == base1 && disp0 == disp1 && index0 == index1)
return 1;
case MEM:
break;
- /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
- into a stack slot memory address comprising a PLUS and a
- constant. */
- case ADDRESSOF:
- break;
-
default:
fatal_insn ("c4x_valid_operands: Internal error", op2);
break;
case MEM:
break;
- /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
- into a stack slot memory address comprising a PLUS and a
- constant. */
- case ADDRESSOF:
- break;
-
default:
abort ();
break;
&& TARGET_HOIST
&& optimize > 0
&& GET_CODE (operands[1]) == CONST_INT
- && preserve_subexpressions_p ()
&& rtx_cost (operands[1], code) > 1)
operands[1] = force_reg (mode, operands[1]);
&& TARGET_HOIST
&& optimize > 1
&& GET_CODE (operands[2]) == CONST_INT
- && preserve_subexpressions_p ()
&& rtx_cost (operands[2], code) > 1)
operands[2] = force_reg (mode, operands[2]);
static void
c4x_file_start (void)
{
- int dspversion = 0;
- if (TARGET_C30) dspversion = 30;
- if (TARGET_C31) dspversion = 31;
- if (TARGET_C32) dspversion = 32;
- if (TARGET_C33) dspversion = 33;
- if (TARGET_C40) dspversion = 40;
- if (TARGET_C44) dspversion = 44;
-
default_file_start ();
- fprintf (asm_out_file, "\t.version\t%d\n", dspversion);
+ fprintf (asm_out_file, "\t.version\t%d\n", c4x_cpu_version);
fputs ("\n\t.data\ndata_sec:\n", asm_out_file);
}
{
if (TREE_CODE (*node) != FUNCTION_TYPE)
{
- warning ("`%s' attribute only applies to functions",
+ warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
where they are and print a warning. We should
probably move these insns before the repeat block insn. */
if (TARGET_DEBUG)
- fatal_insn("c4x_rptb_rpts_p: Repeat block top label moved\n",
- insn);
+ fatal_insn ("c4x_rptb_rpts_p: Repeat block top label moved",
+ insn);
return 0;
}
{
tree endlink = void_list_node;
- builtin_function ("fast_ftoi",
- build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, double_type_node, endlink)),
- C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL_TREE);
- builtin_function ("ansi_ftoi",
- build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, double_type_node, endlink)),
- C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("fast_ftoi",
+ build_function_type
+ (integer_type_node,
+ tree_cons (NULL_TREE, double_type_node,
+ endlink)),
+ C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("ansi_ftoi",
+ build_function_type
+ (integer_type_node,
+ tree_cons (NULL_TREE, double_type_node,
+ endlink)),
+ C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL,
+ NULL_TREE);
if (TARGET_C3X)
- builtin_function ("fast_imult",
- build_function_type
- (integer_type_node,
- tree_cons (NULL_TREE, integer_type_node,
- tree_cons (NULL_TREE,
- integer_type_node, endlink))),
- C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("fast_imult",
+ build_function_type
+ (integer_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ integer_type_node,
+ endlink))),
+ C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL,
+ NULL_TREE);
else
{
- builtin_function ("toieee",
- build_function_type
- (double_type_node,
- tree_cons (NULL_TREE, double_type_node, endlink)),
- C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL, NULL_TREE);
- builtin_function ("frieee",
- build_function_type
- (double_type_node,
- tree_cons (NULL_TREE, double_type_node, endlink)),
- C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL, NULL_TREE);
- builtin_function ("fast_invf",
- build_function_type
- (double_type_node,
- tree_cons (NULL_TREE, double_type_node, endlink)),
- C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL, NULL_TREE);
+ add_builtin_function ("toieee",
+ build_function_type
+ (double_type_node,
+ tree_cons (NULL_TREE, double_type_node,
+ endlink)),
+ C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL,
+ NULL_TREE);
+ add_builtin_function ("frieee",
+ build_function_type
+ (double_type_node,
+ tree_cons (NULL_TREE, double_type_node,
+ endlink)),
+ C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL,
+ NULL_TREE);
+ add_builtin_function ("fast_invf",
+ build_function_type
+ (double_type_node,
+ tree_cons (NULL_TREE, double_type_node,
+ endlink)),
+ C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL,
+ NULL_TREE);
}
}
enum machine_mode mode ATTRIBUTE_UNUSED,
int ignore ATTRIBUTE_UNUSED)
{
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- tree arglist = TREE_OPERAND (exp, 1);
tree arg0, arg1;
rtx r0, r1;
switch (fcode)
{
case C4X_BUILTIN_FIX:
- arg0 = TREE_VALUE (arglist);
+ arg0 = CALL_EXPR_ARG (exp, 0);
r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
- r0 = protect_from_queue (r0, 0);
if (! target || ! register_operand (target, QImode))
target = gen_reg_rtx (QImode);
emit_insn (gen_fixqfqi_clobber (target, r0));
return target;
case C4X_BUILTIN_FIX_ANSI:
- arg0 = TREE_VALUE (arglist);
+ arg0 = CALL_EXPR_ARG (exp, 0);
r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
- r0 = protect_from_queue (r0, 0);
if (! target || ! register_operand (target, QImode))
target = gen_reg_rtx (QImode);
emit_insn (gen_fix_truncqfqi2 (target, r0));
case C4X_BUILTIN_MPYI:
if (! TARGET_C3X)
break;
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
r0 = expand_expr (arg0, NULL_RTX, QImode, 0);
r1 = expand_expr (arg1, NULL_RTX, QImode, 0);
- r0 = protect_from_queue (r0, 0);
- r1 = protect_from_queue (r1, 0);
if (! target || ! register_operand (target, QImode))
target = gen_reg_rtx (QImode);
emit_insn (gen_mulqi3_24_clobber (target, r0, r1));
case C4X_BUILTIN_TOIEEE:
if (TARGET_C3X)
break;
- arg0 = TREE_VALUE (arglist);
+ arg0 = CALL_EXPR_ARG (exp, 0);
r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
- r0 = protect_from_queue (r0, 0);
if (! target || ! register_operand (target, QFmode))
target = gen_reg_rtx (QFmode);
emit_insn (gen_toieee (target, r0));
case C4X_BUILTIN_FRIEEE:
if (TARGET_C3X)
break;
- arg0 = TREE_VALUE (arglist);
- if (TREE_CODE (arg0) == VAR_DECL || TREE_CODE (arg0) == PARM_DECL)
- put_var_into_stack (arg0, /*rescan=*/true);
+ arg0 = CALL_EXPR_ARG (exp, 0);
r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
- r0 = protect_from_queue (r0, 0);
if (register_operand (r0, QFmode))
{
r1 = assign_stack_local (QFmode, GET_MODE_SIZE (QFmode), 0);
case C4X_BUILTIN_RCPF:
if (TARGET_C3X)
break;
- arg0 = TREE_VALUE (arglist);
+ arg0 = CALL_EXPR_ARG (exp, 0);
r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
- r0 = protect_from_queue (r0, 0);
if (! target || ! register_operand (target, QFmode))
target = gen_reg_rtx (QFmode);
emit_insn (gen_rcpfqf_clobber (target, r0));
}
static void
-c4x_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
+c4x_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED,
+ tree decl ATTRIBUTE_UNUSED)
{
fprintf (asm_out_file, "\t.sect\t\"%s\"\n", name);
}