predicates.md (rx_store_multiple_vector): Reverse order of expected registers.

* config/rx/predicates.md (rx_store_multiple_vector): Reverse
        order of expected registers.
        (rx_load_multiple_vector): Likewise.
        (rx_rtsd_vector): Likewise.
        * config/rx/rx.c (rx_cpu_type): New variable.
        (rx_print_operand): Fix bug printing 64-bit constant values.
        (rx_emit_stack_pushm): Reverse order of pushed registers.
        (gen_rx_store_vector): Likewise.
        (is_fast_interrupt_func): Only accept "fast_interrupt" as the
        attribute name.
        (is_exception_func): Rename to is_interrupt_func and only accept
        "interrupt" as the attribute name.
        (rx_get_stack_layout): Use new function name.
        (rx_func_attr_inlinable): Likewise.
        (rx_attribute_table): Remove "exception".
        (rx_expand_prologue): If necessary push the accumulator register
        in the prologue of interrupt functions.
        (rx_expand_epilogue): If necessary pop the accumulator.
        (rx_builtins): Add RX_BUILTIN_MVTIPL.
        (rx_expand_builtin_stz): Remove.
        (rx_expand_builtin_mvtipl): New function.
        (rx_init_builtins): Handle RX_BUILTIN_MVTIPL.
        (rx_expand_builtin): Likewise.
        (rx_enable_fpu): New variable.
        (rx_handle_option): Handle -fpu, -nofpu, -mcpu and -patch.
        * config/rx/rx.h (TARGET_CPU_CPP_BUILTINS): Assert machine based
        on rx_cpu_type.  Define __RX_FPU_INSNS__ if FPU insns are allowed.
        (enum rx_cpu_types): Define.
        (ASM_SPEC): Pass -m32bit-doubles on to assembler.
        (INCOMING_FRAME_SP_OFFSET): Define.
        (ARG_POINTER_CFA_OFFSET): Define.
        (FRAME_POINTER_CFA_OFFSET): Define.
        (OVERRIDE_OPTIONS): Enable fast math if RX FPU insns are enabled.
        (ALLOW_RX_FPU_INSNS): Define.
        * config/rx/rx.md: Test ALLOW_RX_FPU_INSNS instead of
        fast_math_flags_set_p.
        (UNSPEC_BUILTIN_MVTIPL): Define.
        (revl): Rename to bswapsi2.
        (bswaphi2): New pattern.
        (mvtachi): Mark as volatile because it uses a register unknown to
        GCC.
        (mvtaclo): Likewise.
        (racw): Likewise.
        (mvtc): Remove clobber of cc0.
        (mvtcp): Delete.
        (opecp): Delete.
        * config/rx/rx.opt (mieee): Remove.
        (fpu): Add.
        (nofpu): Add.
        (mcpu=): Add.
        (patch=): Add.
        (msave-acc-in-interrupts): Add.
        * config/rx/t-rx (MULTILIB_OPTIONS): Change default to 64bit
        doubles.
        (MULTILIB_DIRS): Likewise.
        (MULTILIB_MATCHES): Treat -fpu as an alias for -m32bit-doubles.
        * doc/extend.texi: Remove description of "exception" function
        attribute.
        * doc/invoke.texi: Document -fpu, -nofpu, -mcpu=, -patch= and
        -msave-acc-in-interrupts options.

        * gcc.target/rx/builtins,c: Remove redundant tests.
        Add test of MVTIPL instruction.
        * gcc.target/rx/interrupts.c: Use fast_interrupt and interrupt
        function attributes.  Add -msave-acc-in-interrupts option to the
        command line.

Co-Authored-By: Kevin Buettner <kevinb@redhat.com>

From-SVN: r153853
This commit is contained in:
Nick Clifton 2009-11-03 16:25:29 +00:00 committed by Nick Clifton
parent 48d3ee1d0a
commit 9595a419c6
14 changed files with 460 additions and 154 deletions

View File

@ -1,3 +1,67 @@
2009-11-03 Nick Clifton <nickc@redhat.com>
Kevin Buettner <kevinb@redhat.com>
* config/rx/predicates.md (rx_store_multiple_vector): Reverse
order of expected registers.
(rx_load_multiple_vector): Likewise.
(rx_rtsd_vector): Likewise.
* config/rx/rx.c (rx_cpu_type): New variable.
(rx_print_operand): Fix bug printing 64-bit constant values.
(rx_emit_stack_pushm): Reverse order of pushed registers.
(gen_rx_store_vector): Likewise.
(is_fast_interrupt_func): Only accept "fast_interrupt" as the
attribute name.
(is_exception_func): Rename to is_interrupt_func and only accept
"interrupt" as the attribute name.
(rx_get_stack_layout): Use new function name.
(rx_func_attr_inlinable): Likewise.
(rx_attribute_table): Remove "exception".
(rx_expand_prologue): If necessary push the accumulator register
in the prologue of interrupt functions.
(rx_expand_epilogue): If necessary pop the accumulator.
(rx_builtins): Add RX_BUILTIN_MVTIPL.
(rx_expand_builtin_stz): Remove.
(rx_expand_builtin_mvtipl): New function.
(rx_init_builtins): Handle RX_BUILTIN_MVTIPL.
(rx_expand_builtin): Likewise.
(rx_enable_fpu): New variable.
(rx_handle_option): Handle -fpu, -nofpu, -mcpu and -patch.
* config/rx/rx.h (TARGET_CPU_CPP_BUILTINS): Assert machine based
on rx_cpu_type. Define __RX_FPU_INSNS__ if FPU insns are allowed.
(enum rx_cpu_types): Define.
(ASM_SPEC): Pass -m32bit-doubles on to assembler.
(INCOMING_FRAME_SP_OFFSET): Define.
(ARG_POINTER_CFA_OFFSET): Define.
(FRAME_POINTER_CFA_OFFSET): Define.
(OVERRIDE_OPTIONS): Enable fast math if RX FPU insns are enabled.
(ALLOW_RX_FPU_INSNS): Define.
* config/rx/rx.md: Test ALLOW_RX_FPU_INSNS instead of
fast_math_flags_set_p.
(UNSPEC_BUILTIN_MVTIPL): Define.
(revl): Rename to bswapsi2.
(bswaphi2): New pattern.
(mvtachi): Mark as volatile because it uses a register unknown to
GCC.
(mvtaclo): Likewise.
(racw): Likewise.
(mvtc): Remove clobber of cc0.
(mvtcp): Delete.
(opecp): Delete.
* config/rx/rx.opt (mieee): Remove.
(fpu): Add.
(nofpu): Add.
(mcpu=): Add.
(patch=): Add.
(msave-acc-in-interrupts): Add.
* config/rx/t-rx (MULTILIB_OPTIONS): Change default to 64bit
doubles.
(MULTILIB_DIRS): Likewise.
(MULTILIB_MATCHES): Treat -fpu as an alias for -m32bit-doubles.
* doc/extend.texi: Remove description of "exception" function
attribute.
* doc/invoke.texi: Document -fpu, -nofpu, -mcpu=, -patch= and
-msave-acc-in-interrupts options.
2009-11-03 Richard Guenther <rguenther@suse.de>
* c-common.c (fold_offsetof_1): Use HOST_WIDE_INT_PRINT_DEC.

View File

@ -55,7 +55,7 @@
;; This constraint is used by the SUBSI3 pattern because the
;; RX SUB instruction can only take a 4-bit unsigned integer
;; value.
;; value. Also used by the MVTIPL instruction.
(define_constraint "Uint04"
"@internal An unsigned 4-bit immediate value"
(and (match_code "const_int")

View File

@ -117,16 +117,22 @@
/* Check that the next element is the first push. */
element = XVECEXP (op, 0, 1);
if ( ! SET_P (element)
|| ! REG_P (SET_SRC (element))
|| GET_MODE (SET_SRC (element)) != SImode
|| ! MEM_P (SET_DEST (element))
|| ! REG_P (XEXP (SET_DEST (element), 0))
|| REGNO (XEXP (SET_DEST (element), 0)) != SP_REG
|| ! REG_P (SET_SRC (element)))
|| GET_MODE (SET_DEST (element)) != SImode
|| GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
|| ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
|| REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
|| ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
|| INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
!= GET_MODE_SIZE (SImode))
return false;
src_regno = REGNO (SET_SRC (element));
/* Check that the remaining elements use SP-<disp>
addressing and incremental register numbers. */
addressing and decreasing register numbers. */
for (i = 2; i < count; i++)
{
element = XVECEXP (op, 0, i);
@ -134,7 +140,7 @@
if ( ! SET_P (element)
|| ! REG_P (SET_SRC (element))
|| GET_MODE (SET_SRC (element)) != SImode
|| REGNO (SET_SRC (element)) != src_regno + (i - 1)
|| REGNO (SET_SRC (element)) != src_regno - (i - 1)
|| ! MEM_P (SET_DEST (element))
|| GET_MODE (SET_DEST (element)) != SImode
|| GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
@ -142,7 +148,7 @@
|| REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
|| ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
|| INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
!= (i - 1) * GET_MODE_SIZE (SImode))
!= i * GET_MODE_SIZE (SImode))
return false;
}
return true;

View File

@ -51,6 +51,8 @@
#include "target-def.h"
#include "langhooks.h"
enum rx_cpu_types rx_cpu_type = RX600;
/* Return true if OP is a reference to an object in a small data area. */
static bool
@ -249,7 +251,6 @@ rx_is_mode_dependent_addr (rtx addr)
}
}
/* A C compound statement to output to stdio stream FILE the
assembler syntax for an instruction operand that is a memory
reference whose address is ADDR. */
@ -445,8 +446,13 @@ rx_print_operand (FILE * file, rtx op, int letter)
fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 0 : 1)]);
else if (CONST_INT_P (op))
{
HOST_WIDE_INT v = INTVAL (op);
fprintf (file, "#");
rx_print_integer (file, INTVAL (op) >> 32);
/* Trickery to avoid problems with shifting 32 bits at a time. */
v = v >> 16;
v = v >> 16;
rx_print_integer (file, v);
}
else
{
@ -840,22 +846,20 @@ has_func_attr (const_tree decl, const char * func_attr)
return lookup_attribute (func_attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
}
/* Returns true if the provided function has
the "[fast_]interrupt" attribute. */
/* Returns true if the provided function has the "fast_interrupt" attribute. */
static inline bool
is_fast_interrupt_func (const_tree decl)
{
return has_func_attr (decl, "interrupt")
|| has_func_attr (decl, "fast_interrupt") ;
return has_func_attr (decl, "fast_interrupt");
}
/* Returns true if the provided function has the "exception" attribute. */
/* Returns true if the provided function has the "interrupt" attribute. */
static inline bool
is_exception_func (const_tree decl)
is_interrupt_func (const_tree decl)
{
return has_func_attr (decl, "exception");
return has_func_attr (decl, "interrupt");
}
/* Returns true if the provided function has the "naked" attribute. */
@ -945,8 +949,8 @@ rx_set_current_function (tree fndecl)
{
/* Remember the last target of rx_set_current_function. */
static tree rx_previous_fndecl;
bool prev_was_interrupt;
bool current_is_interrupt;
bool prev_was_fast_interrupt;
bool current_is_fast_interrupt;
/* Only change the context if the function changes. This hook is called
several times in the course of compiling a function, and we don't want
@ -954,18 +958,19 @@ rx_set_current_function (tree fndecl)
if (fndecl == rx_previous_fndecl)
return;
prev_was_interrupt
prev_was_fast_interrupt
= rx_previous_fndecl
? is_fast_interrupt_func (rx_previous_fndecl) : false;
current_is_interrupt
current_is_fast_interrupt
= fndecl ? is_fast_interrupt_func (fndecl) : false;
if (prev_was_interrupt != current_is_interrupt)
if (prev_was_fast_interrupt != current_is_fast_interrupt)
{
use_fixed_regs = current_is_interrupt;
use_fixed_regs = current_is_fast_interrupt;
target_reinit ();
}
rx_previous_fndecl = fndecl;
}
@ -1057,8 +1062,8 @@ rx_get_stack_layout (unsigned int * lowest,
if (df_regs_ever_live_p (reg)
&& (! call_used_regs[reg]
/* Even call clobbered registered must
be pushed inside exception handlers. */
|| is_exception_func (NULL_TREE)))
be pushed inside interrupt handlers. */
|| is_interrupt_func (NULL_TREE)))
{
if (low == 0)
low = reg;
@ -1142,9 +1147,8 @@ rx_emit_stack_pushm (rtx * operands)
gcc_assert (REG_P (first_push));
asm_fprintf (asm_out_file, "\tpushm\t%s-%s\n",
reg_names [REGNO (first_push)],
reg_names [REGNO (first_push) + last_reg]);
reg_names [REGNO (first_push) - last_reg],
reg_names [REGNO (first_push)]);
}
/* Generate a PARALLEL that will pass the rx_store_multiple_vector predicate. */
@ -1167,14 +1171,30 @@ gen_rx_store_vector (unsigned int low, unsigned int high)
XVECEXP (vector, 0, i + 1) =
gen_rtx_SET (SImode,
gen_rtx_MEM (SImode,
i == 0 ? stack_pointer_rtx
: gen_rtx_MINUS (SImode, stack_pointer_rtx,
GEN_INT (i * UNITS_PER_WORD))),
gen_rtx_REG (SImode, low + i));
gen_rtx_MINUS (SImode, stack_pointer_rtx,
GEN_INT ((i + 1) * UNITS_PER_WORD))),
gen_rtx_REG (SImode, high - i));
return vector;
}
/* Mark INSN as being frame related. If it is a PARALLEL
then mark each element as being frame related as well. */
static void
mark_frame_related (rtx insn)
{
RTX_FRAME_RELATED_P (insn) = 1;
insn = PATTERN (insn);
if (GET_CODE (insn) == PARALLEL)
{
unsigned int i;
for (i = 0; i < XVECLEN (insn, 0); i++)
RTX_FRAME_RELATED_P (XVECEXP (insn, 0, i)) = 1;
}
}
void
rx_expand_prologue (void)
{
@ -1183,6 +1203,7 @@ rx_expand_prologue (void)
unsigned int mask;
unsigned int low;
unsigned int high;
unsigned int reg;
rtx insn;
/* Naked functions use their own, programmer provided prologues. */
@ -1196,14 +1217,12 @@ rx_expand_prologue (void)
/* If we use any of the callee-saved registers, save them now. */
if (mask)
{
unsigned int reg;
/* Push registers in reverse order. */
for (reg = FIRST_PSEUDO_REGISTER; reg --;)
if (mask & (1 << reg))
{
insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg)));
RTX_FRAME_RELATED_P (insn) = 1;
mark_frame_related (insn);
}
}
else if (low)
@ -1214,7 +1233,57 @@ rx_expand_prologue (void)
insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1)
* UNITS_PER_WORD),
gen_rx_store_vector (low, high)));
RTX_FRAME_RELATED_P (insn) = 1;
mark_frame_related (insn);
}
if (is_interrupt_func (NULL_TREE) && TARGET_SAVE_ACC_REGISTER)
{
unsigned int acc_high, acc_low;
/* Interrupt handlers have to preserve the accumulator
register if so requested by the user. Use the first
two pushed register as intermediaries. */
if (mask)
{
acc_low = acc_high = 0;
for (reg = 1; reg < FIRST_PSEUDO_REGISTER; reg ++)
if (mask & (1 << reg))
{
if (acc_low == 0)
acc_low = reg;
else
{
acc_high = reg;
break;
}
}
/* We have assumed that there are at least two registers pushed... */
gcc_assert (acc_high != 0);
/* Note - the bottom 16 bits of the accumulator are inaccessible.
We just assume that they are zero. */
emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low)));
emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high)));
}
else
{
acc_low = low;
acc_high = low + 1;
/* We have assumed that there are at least two registers pushed... */
gcc_assert (acc_high <= high);
emit_insn (gen_mvfacmi (gen_rtx_REG (SImode, acc_low)));
emit_insn (gen_mvfachi (gen_rtx_REG (SImode, acc_high)));
emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD),
gen_rx_store_vector (acc_low, acc_high)));
}
frame_size += 2 * UNITS_PER_WORD;
}
/* If needed, set up the frame pointer. */
@ -1270,8 +1339,8 @@ rx_output_function_prologue (FILE * file,
if (is_fast_interrupt_func (NULL_TREE))
asm_fprintf (file, "\t; Note: Fast Interrupt Handler\n");
if (is_exception_func (NULL_TREE))
asm_fprintf (file, "\t; Note: Exception Handler\n");
if (is_interrupt_func (NULL_TREE))
asm_fprintf (file, "\t; Note: Interrupt Handler\n");
if (is_naked_func (NULL_TREE))
asm_fprintf (file, "\t; Note: Naked Function\n");
@ -1382,6 +1451,7 @@ rx_expand_epilogue (bool is_sibcall)
unsigned int stack_size;
unsigned int register_mask;
unsigned int regs_size;
unsigned int reg;
unsigned HOST_WIDE_INT total_size;
if (is_naked_func (NULL_TREE))
@ -1407,14 +1477,14 @@ rx_expand_epilogue (bool is_sibcall)
their caller. Instead they branch to their sibling and allow their
return instruction to return to this function's parent.
- Fast interrupt and exception handling functions have to use special
- Fast and normal interrupt handling functions have to use special
return instructions.
- Functions where we have pushed a fragmented set of registers into the
call-save area must have the same set of registers popped. */
if (is_sibcall
|| is_fast_interrupt_func (NULL_TREE)
|| is_exception_func (NULL_TREE)
|| is_interrupt_func (NULL_TREE)
|| register_mask)
{
/* Cannot use the special instructions - deconstruct by hand. */
@ -1422,10 +1492,47 @@ rx_expand_epilogue (bool is_sibcall)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (total_size)));
if (is_interrupt_func (NULL_TREE) && TARGET_SAVE_ACC_REGISTER)
{
unsigned int acc_low, acc_high;
/* Reverse the saving of the accumulator register onto the stack.
Note we must adjust the saved "low" accumulator value as it
is really the middle 32-bits of the accumulator. */
if (register_mask)
{
acc_low = acc_high = 0;
for (reg = 1; reg < FIRST_PSEUDO_REGISTER; reg ++)
if (register_mask & (1 << reg))
{
if (acc_low == 0)
acc_low = reg;
else
{
acc_high = reg;
break;
}
}
emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high)));
emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low)));
}
else
{
acc_low = low;
acc_high = low + 1;
emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD),
gen_rx_popm_vector (acc_low, acc_high)));
}
emit_insn (gen_ashlsi3 (gen_rtx_REG (SImode, acc_low),
gen_rtx_REG (SImode, acc_low),
GEN_INT (16)));
emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low)));
emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high)));
}
if (register_mask)
{
unsigned int reg;
for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg ++)
if (register_mask & (1 << reg))
emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg)));
@ -1441,7 +1548,7 @@ rx_expand_epilogue (bool is_sibcall)
if (is_fast_interrupt_func (NULL_TREE))
emit_jump_insn (gen_fast_interrupt_return ());
else if (is_exception_func (NULL_TREE))
else if (is_interrupt_func (NULL_TREE))
emit_jump_insn (gen_exception_return ());
else if (! is_sibcall)
emit_jump_insn (gen_simple_return ());
@ -1670,6 +1777,7 @@ enum rx_builtin
RX_BUILTIN_MVTACHI,
RX_BUILTIN_MVTACLO,
RX_BUILTIN_MVTC,
RX_BUILTIN_MVTIPL,
RX_BUILTIN_RACW,
RX_BUILTIN_REVW,
RX_BUILTIN_RMPA,
@ -1725,6 +1833,7 @@ rx_init_builtins (void)
ADD_RX_BUILTIN1 (RMPA, "rmpa", void, void);
ADD_RX_BUILTIN1 (MVFC, "mvfc", intSI, integer);
ADD_RX_BUILTIN2 (MVTC, "mvtc", void, integer, integer);
ADD_RX_BUILTIN1 (MVTIPL, "mvtipl", void, integer);
ADD_RX_BUILTIN1 (RACW, "racw", void, integer);
ADD_RX_BUILTIN1 (ROUND, "round", intSI, float);
ADD_RX_BUILTIN1 (REVW, "revw", intSI, intSI);
@ -1732,20 +1841,6 @@ rx_init_builtins (void)
ADD_RX_BUILTIN1 (WAIT, "wait", void, void);
}
static rtx
rx_expand_builtin_stz (rtx arg, rtx target, rtx (* gen_func)(rtx, rtx))
{
if (! CONST_INT_P (arg))
return NULL_RTX;
if (target == NULL_RTX || ! REG_P (target))
target = gen_reg_rtx (SImode);
emit_insn (gen_func (target, arg));
return target;
}
static rtx
rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg)
{
@ -1790,6 +1885,21 @@ rx_expand_builtin_mvfc (tree t_arg, rtx target)
return target;
}
static rtx
rx_expand_builtin_mvtipl (rtx arg)
{
/* The RX610 does not support the MVTIPL instruction. */
if (rx_cpu_type == RX610)
return NULL_RTX;
if (! CONST_INT_P (arg) || ! IN_RANGE (arg, 0, (1 << 4) - 1))
return NULL_RTX;
emit_insn (gen_mvtipl (arg));
return NULL_RTX;
}
static rtx
rx_expand_builtin_mac (tree exp, rtx (* gen_func)(rtx, rtx))
{
@ -1887,6 +1997,7 @@ rx_expand_builtin (tree exp,
case RX_BUILTIN_RMPA: emit_insn (gen_rmpa ()); return NULL_RTX;
case RX_BUILTIN_MVFC: return rx_expand_builtin_mvfc (arg, target);
case RX_BUILTIN_MVTC: return rx_expand_builtin_mvtc (exp);
case RX_BUILTIN_MVTIPL: return rx_expand_builtin_mvtipl (op);
case RX_BUILTIN_RACW: return rx_expand_void_builtin_1_arg
(op, gen_racw, false);
case RX_BUILTIN_ROUND: return rx_expand_builtin_round (op, target);
@ -1945,7 +2056,7 @@ rx_elf_asm_destructor (rtx symbol, int priority)
rx_elf_asm_cdtor (symbol, priority, /* is_ctor= */false);
}
/* Check "interrupt", "exception" and "naked" attributes. */
/* Check "fast_interrupt", "interrupt" and "naked" attributes. */
static tree
rx_handle_func_attribute (tree * node,
@ -1975,9 +2086,8 @@ rx_handle_func_attribute (tree * node,
const struct attribute_spec rx_attribute_table[] =
{
/* Name, min_len, max_len, decl_req, type_req, fn_type_req, handler. */
{ "interrupt", 0, 0, true, false, false, rx_handle_func_attribute },
{ "fast_interrupt", 0, 0, true, false, false, rx_handle_func_attribute },
{ "exception", 0, 0, true, false, false, rx_handle_func_attribute },
{ "interrupt", 0, 0, true, false, false, rx_handle_func_attribute },
{ "naked", 0, 0, true, false, false, rx_handle_func_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@ -1993,7 +2103,7 @@ static bool
rx_func_attr_inlinable (const_tree decl)
{
return ! is_fast_interrupt_func (decl)
&& ! is_exception_func (decl)
&& ! is_interrupt_func (decl)
&& ! is_naked_func (decl);
}
@ -2115,6 +2225,20 @@ rx_is_legitimate_constant (rtx x)
( 1 << (rx_max_constant_size * 8)));
}
/* This is a tri-state variable. The default value of 0 means that the user
has specified neither -mfpu nor -mnofpu on the command line. In this case
the selection of RX FPU instructions is entirely based upon the size of
the floating point object and whether unsafe math optimizations were
enabled. If 32-bit doubles have been enabled then both floats and doubles
can make use of FPU instructions, otherwise only floats may do so.
If the value is 1 then the user has specified -mfpu and the FPU
instructions should be used. Unsafe math optimizations will automatically
be enabled and doubles set to 32-bits. If the value is -1 then -mnofpu
has been specified and FPU instructions will not be used, even if unsafe
math optimizations have been enabled. */
int rx_enable_fpu = 0;
/* Extra processing for target specific command line options. */
static bool
@ -2122,6 +2246,27 @@ rx_handle_option (size_t code, const char * arg ATTRIBUTE_UNUSED, int value)
{
switch (code)
{
/* -mfpu enables the use of RX FPU instructions. This implies the use
of 32-bit doubles and also the enabling of fast math optimizations.
(Since the RX FPU instructions are not IEEE compliant). The -mnofpu
option disables the use of RX FPU instructions, but does not make
place any constraints on the size of doubles or the use of fast math
optimizations.
The selection of 32-bit vs 64-bit doubles is handled by the setting
of the 32BIT_DOUBLES mask in the rx.opt file. Enabling fast math
optimizations is performed in OVERRIDE_OPTIONS since if it was done
here it could be overridden by a -fno-fast-math option specified
*earlier* on the command line. (Target specific options are
processed before generic ones). */
case OPT_fpu:
rx_enable_fpu = 1;
break;
case OPT_nofpu:
rx_enable_fpu = -1;
break;
case OPT_mint_register_:
switch (value)
{
@ -2145,12 +2290,21 @@ rx_handle_option (size_t code, const char * arg ATTRIBUTE_UNUSED, int value)
break;
case OPT_mmax_constant_size_:
/* Make sure that the the -mmax-constant_size option is in range. */
/* Make sure that the -mmax-constant_size option is in range. */
return IN_RANGE (value, 0, 4);
case OPT_mcpu_:
case OPT_patch_:
if (strcasecmp (arg, "RX610") == 0)
rx_cpu_type = RX610;
/* FIXME: Should we check for non-RX cpu names here ? */
break;
default:
return true;
break;
}
return true;
}
static int

View File

@ -24,18 +24,24 @@
{ \
builtin_define ("__RX__"); \
builtin_assert ("cpu=RX"); \
builtin_assert ("machine=RX"); \
if (rx_cpu_type == RX610) \
builtin_assert ("machine=RX610"); \
else \
builtin_assert ("machine=RX600"); \
\
if (TARGET_BIG_ENDIAN_DATA) \
builtin_define ("__RX_BIG_ENDIAN__"); \
else \
builtin_define ("__RX_LITTLE_ENDIAN__");\
\
if (TARGET_64BIT_DOUBLES) \
builtin_define ("__RX_64BIT_DOUBLES__");\
else \
if (TARGET_32BIT_DOUBLES) \
builtin_define ("__RX_32BIT_DOUBLES__");\
else \
builtin_define ("__RX_64BIT_DOUBLES__");\
\
if (ALLOW_RX_FPU_INSNS) \
builtin_define ("__RX_FPU_INSNS__"); \
\
if (TARGET_AS100_SYNTAX) \
builtin_define ("__RX_AS100_SYNTAX__"); \
else \
@ -43,6 +49,17 @@
} \
while (0)
enum rx_cpu_types
{
RX600,
RX610
};
extern enum rx_cpu_types rx_cpu_type;
#undef CC1_SPEC
#define CC1_SPEC "%{mas100-syntax:%{gdwarf*:%e-mas100-syntax is incompatible with -gdwarf}}"
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:crt0.o%s} crtbegin.o%s"
@ -52,7 +69,8 @@
#undef ASM_SPEC
#define ASM_SPEC "\
%{mbig-endian-data:-mbig-endian-data} \
%{m64bit-doubles:-m64bit-doubles} \
%{m32bit-doubles:-m32bit-doubles} \
%{!m32bit-doubles:-m64bit-doubles} \
%{msmall-data-limit*:-msmall-data-limit} \
%{mrelax:-relax} \
"
@ -88,16 +106,17 @@
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE (TARGET_64BIT_DOUBLES ? 64 : 32)
#define DOUBLE_TYPE_SIZE (TARGET_32BIT_DOUBLES ? 32 : 64)
#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
#ifdef __RX_64BIT_DOUBLES__
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
#define LIBGCC2_DOUBLE_TYPE_SIZE 64
#define LIBGCC2_HAS_DF_MODE 1
#else
#ifdef __RX_32BIT_DOUBLES__
#define LIBGCC2_HAS_DF_MODE 0
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 32
#define LIBGCC2_DOUBLE_TYPE_SIZE 32
#else
#define LIBGCC2_HAS_DF_MODE 1
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
#define LIBGCC2_DOUBLE_TYPE_SIZE 64
#endif
#define DEFAULT_SIGNED_CHAR 0
@ -591,7 +610,6 @@ typedef unsigned int CUMULATIVE_ARGS;
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
rx_print_operand_address (FILE, ADDR)
#define CC_NO_CARRY 0400
#define NOTICE_UPDATE_CC(EXP, INSN) rx_notice_update_cc (EXP, INSN)
@ -614,19 +632,28 @@ extern int rx_float_compare_mode;
#define PREFERRED_DEBUGGING_TYPE (TARGET_AS100_SYNTAX \
? DBX_DEBUG : DWARF2_DEBUG)
#undef CC1_SPEC
#define CC1_SPEC "%{mas100-syntax:%{gdwarf*:%e-mas100-syntax is incompatible with -gdwarf}}"
#define INCOMING_FRAME_SP_OFFSET 4
#define ARG_POINTER_CFA_OFFSET(FNDECL) 4
#define FRAME_POINTER_CFA_OFFSET(FNDECL) 4
extern int rx_enable_fpu;
/* For some unknown reason LTO compression is not working, at
least on my local system. So set the default compression
level to none, for now. */
level to none, for now.
For an explanation of rx_flag_no_fpu see rx_handle_option(). */
#define OVERRIDE_OPTIONS \
do \
{ \
if (flag_lto_compression_level == -1) \
flag_lto_compression_level = 0; \
\
if (rx_enable_fpu == 1) \
set_fast_math_flags (true); \
} \
while (0)
/* This macro is used to decide when RX FPU instructions can be used. */
#define ALLOW_RX_FPU_INSNS flag_unsafe_math_optimizations
#define ALLOW_RX_FPU_INSNS ((rx_enable_fpu != -1) \
&& flag_unsafe_math_optimizations)

View File

@ -27,8 +27,8 @@
;; This code iterator is used for sign- and zero- extensions.
(define_mode_iterator small_int_modes [(HI "") (QI "")])
;; We do not handle DFmode here because by default it is
;; the same as SFmode, and if -m64bit-doubles is active
;; We do not handle DFmode here because it is either
;; the same as SFmode, or if -m64bit-doubles is active
;; then all operations on doubles have to be handled by
;; library functions.
(define_mode_iterator register_modes
@ -75,15 +75,14 @@
(UNSPEC_BUILTIN_MVTACHI 41)
(UNSPEC_BUILTIN_MVTACLO 42)
(UNSPEC_BUILTIN_MVTC 43)
(UNSPEC_BUILTIN_MVTCP 44)
(UNSPEC_BUILTIN_OPEPC 45)
(UNSPEC_BUILTIN_RACW 46)
(UNSPEC_BUILTIN_REVW 47)
(UNSPEC_BUILTIN_RMPA 48)
(UNSPEC_BUILTIN_ROUND 49)
(UNSPEC_BUILTIN_SAT 50)
(UNSPEC_BUILTIN_SETPSW 51)
(UNSPEC_BUILTIN_WAIT 52)
(UNSPEC_BUILTIN_MVTIPL 44)
(UNSPEC_BUILTIN_RACW 45)
(UNSPEC_BUILTIN_REVW 46)
(UNSPEC_BUILTIN_RMPA 47)
(UNSPEC_BUILTIN_ROUND 48)
(UNSPEC_BUILTIN_SAT 49)
(UNSPEC_BUILTIN_SETPSW 50)
(UNSPEC_BUILTIN_WAIT 51)
]
)
@ -1002,10 +1001,8 @@
(set_attr "timings" "11,11,11,11,11,33")
(set_attr "length" "3,4,5,6,7,6")]
)
;; Floating Point Instructions
;; These patterns are only enabled with -ffast-math because the RX FPU
;; cannot handle sub-normal values.
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=r,r,r")
@ -1298,7 +1295,6 @@
[(set_attr "length" "3,6")
(set_attr "timings" "22")]
)
;; Block move functions.
@ -1580,8 +1576,8 @@
;; Move to Accumulator (high)
(define_insn "mvtachi"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")]
UNSPEC_BUILTIN_MVTACHI)]
[(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
UNSPEC_BUILTIN_MVTACHI)]
""
"mvtachi\t%0"
[(set_attr "length" "3")]
@ -1589,8 +1585,8 @@
;; Move to Accumulator (low)
(define_insn "mvtaclo"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")]
UNSPEC_BUILTIN_MVTACLO)]
[(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
UNSPEC_BUILTIN_MVTACLO)]
""
"mvtaclo\t%0"
[(set_attr "length" "3")]
@ -1598,8 +1594,8 @@
;; Round Accumulator
(define_insn "racw"
[(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")]
UNSPEC_BUILTIN_RACW)]
[(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
UNSPEC_BUILTIN_RACW)]
""
"racw\t%0"
[(set_attr "length" "3")]
@ -1679,7 +1675,7 @@
;; Move from control register
(define_insn "mvfc"
[(set (match_operand:SI 0 "register_operand" "=r")
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")]
UNSPEC_BUILTIN_MVFC))]
""
@ -1691,13 +1687,24 @@
(define_insn "mvtc"
[(unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i")
(match_operand:SI 1 "nonmemory_operand" "r,i")]
UNSPEC_BUILTIN_MVTC)
(clobber (cc0))]
UNSPEC_BUILTIN_MVTC)]
""
"mvtc\t%1, %C0"
[(set_attr "length" "3,7")
(set_attr "cc" "clobber")] ;; Just in case the control
;; register selected is the psw.
[(set_attr "length" "3,7")]
;; Ignore possible clobbering of the comparison flags in the
;; PSW register. This is a cc0 target so any cc0 setting
;; instruction will always be paired with a cc0 user, without
;; the possibility of this instruction being placed in between
;; them.
)
;; Move to interrupt priority level
(define_insn "mvtipl"
[(unspec:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
UNSPEC_BUILTIN_MVTIPL)]
""
"mvtipl\t%0"
[(set_attr "length" "3")]
)
;;---------- Interrupts ------------------------
@ -1748,27 +1755,6 @@
[(set_attr "length" "5")]
)
;; Move to co-processor register
(define_insn "mvtcp"
[(unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i")
(match_operand:SI 1 "nonmemory_operand" "i,r")
(match_operand:SI 2 "immediate_operand" "i,i")]
UNSPEC_BUILTIN_MVTCP)]
""
"; mvtcp\t%0, %1, %2"
[(set_attr "length" "7,5")]
)
;; Co-processor operation
(define_insn "opecp"
[(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")
(match_operand:SI 1 "immediate_operand" "i")]
UNSPEC_BUILTIN_OPEPC)]
""
"; opecp\t%0, %1"
[(set_attr "length" "5")]
)
;;---------- Misc ------------------------
;; Required by cfglayout.c...

View File

@ -19,13 +19,31 @@
; <http://www.gnu.org/licenses/>.
;---------------------------------------------------
m64bit-doubles
Target RejectNegative Mask(64BIT_DOUBLES)
Store doubles in 64 bits.
m32bit-doubles
Target RejectNegative InverseMask(64BIT_DOUBLES)
Stores doubles in 32 bits. This is the default.
Target RejectNegative Mask(32BIT_DOUBLES)
Stores doubles in 32 bits.
m64bit-doubles
Target RejectNegative InverseMask(32BIT_DOUBLES)
Store doubles in 64 bits. This is the default.
fpu
Target RejectNegative Mask(32BIT_DOUBLES) MaskExists
Enable the use of RX FPU instructions.
nofpu
Target RejectNegative InverseMask(32BIT_DOUBLES) MaskExists
Disable the use of RX FPU instructions.
;---------------------------------------------------
mcpu=
Target RejectNegative Joined Var(rx_cpu_name)
Specify the target RX cpu type.
patch=
Target RejectNegative Joined Var(rx_cpu_name)
Alias for -mcpu.
;---------------------------------------------------
@ -72,3 +90,9 @@ Maximum size in bytes of constant values allowed as operands.
mint-register=
Target RejectNegative Joined UInteger Var(rx_interrupt_registers) Init(0)
Specifies the number of registers to reserve for interrupt handlers.
;---------------------------------------------------
msave-acc-in-interrupts
Target Mask(SAVE_ACC_REGISTER)
Specifies whether interrupt functions should save and restore the accumulator register.

View File

@ -20,9 +20,9 @@
# Enable multilibs:
MULTILIB_OPTIONS = m64bit-doubles mbig-endian-data
MULTILIB_DIRNAMES = 64fp big-endian-data
MULTILIB_MATCHES = m64bit-doubles=mieee
MULTILIB_OPTIONS = m32bit-doubles mbig-endian-data
MULTILIB_DIRNAMES = 32fp big-endian-data
MULTILIB_MATCHES = m32bit-doubles=fpu
MULTILIB_EXCEPTIONS =
MULTILIB_EXTRA_OPTS =

View File

@ -2270,13 +2270,6 @@ on data in the eight bit data area. Note the eight bit data area is limited to
You must use GAS and GLD from GNU binutils version 2.7 or later for
this attribute to work correctly.
@item exception
@cindex exception handler functions on the RX processor
Use this attribute on the RX to indicate that the specified function
is an exception handler. The compiler will generate function entry and
exit sequences suitable for use in an exception handler when this
attribute is present.
@item exception_handler
@cindex exception handler functions on the Blackfin processor
Use this attribute on the Blackfin to indicate that the specified function

View File

@ -784,14 +784,16 @@ See RS/6000 and PowerPC Options.
-msdata=@var{opt} -mvxworks -G @var{num} -pthread}
@emph{RX Options}
@gccoptlist{-m64bit-doubles -m32bit-doubles -mieee -mno-ieee@gol
@gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol
-mcpu= -patch=@gol
-mbig-endian-data -mlittle-endian-data @gol
-msmall-data @gol
-msim -mno-sim@gol
-mas100-syntax -mno-as100-syntax@gol
-mrelax@gol
-mmax-constant-size=@gol
-mint-register=}
-mint-register=@gol
-msave-acc-in-interrupts}
@emph{S/390 and zSeries Options}
@gccoptlist{-mtune=@var{cpu-type} -march=@var{cpu-type} @gol
@ -15408,16 +15410,37 @@ These @option{-m} options are defined for RX implementations:
@table @gcctabopt
@item -m64bit-doubles
@itemx -m32bit-doubles
@itemx -fpu
@itemx -nofpu
@opindex m64bit-doubles
@opindex m32bit-doubles
@opindex fpu
@opindex nofpu
Make the @code{double} data type be 64-bits (@option{-m64bit-doubles})
or 32-bits (@option{-m32bit-doubles}) in size. The default is
@option{-m32bit-doubles}. @emph{Note} the RX's hardware floating
@option{-m64bit-doubles}. @emph{Note} the RX's hardware floating
point instructions are only used for 32-bit floating point values, and
then only if @option{-ffast-math} has been specified on the command
line. This is because the RX FPU instructions do not properly support
denormal (or sub-normal) values.
The options @option{-fpu} and @option{-nofpu} have been provided at
the request of Rensas for compatibility with their toolchain. The
@option{-mfpu} option enables the use of RX FPU instructions by
selecting 32-bit doubles and enabling unsafe math optimizations. The
@option{-mnofpu} option disables the use of RX FPU instructions, even
if @option{-m32bit-doubles} is active and unsafe math optimizations
have been enabled.
@item -mcpu=@var{name}
@itemx -patch=@var{name}
@opindex -mcpu
@opindex -patch
Selects the type of RX CPU to be targeted. Currently on two types are
supported, the generic @var{RX600} and the specific @var{RX610}. The
only difference between them is that the @var{RX610} does not support
the @code{MVTIPL} instruction.
@item -mbig-endian-data
@itemx -mlittle-endian-data
@opindex mbig-endian-data
@ -15493,6 +15516,15 @@ of fast interrupt handlers. A value of 2 reserves @code{r13} and
@code{r12}. A value of 3 reserves @code{r13}, @code{r12} and
@code{r11}, and a value of 4 reserves @code{r13} through @code{r10}.
A value of 0, the default, does not reserve any registers.
@item -msave-acc-in-interrupts
@opindex msave-acc-in-interrupts
Specifies that interrupt handler functions should preserve the
accumulator register. This is only necessary if normal code might use
the accumulator register, for example because it performs 64-bit
multiplications. The default is to ignore the accumulator as this
makes the interrupt handlers faster.
@end table
@emph{Note:} The generic GCC command line @option{-ffixed-@var{reg}}

View File

@ -1,3 +1,11 @@
2009-11-03 Nick Clifton <nickc@redhat.com>
* gcc.target/rx/builtins,c: Remove redundant tests.
Add test of MVTIPL instruction.
* gcc.target/rx/interrupts.c: Use fast_interrupt and interrupt
function attributes. Add -msave-acc-in-interrupts option to the
command line.
2009-11-03 Andrew Stubbs <ams@codesourcery.com>
Maxim Kuvyrkov <maxim@codesourcery.com>

View File

@ -17,7 +17,6 @@
to correctly set the psw flags. */
int saturate_add (int, int) __attribute__((__noinline__));
int subtract_with_borrow (int, int, int) __attribute__((__noinline__));
int exchange (int, int) __attribute__((__noinline__));
int
@ -33,6 +32,13 @@ saturate_add (int arg1, int arg2)
return __builtin_rx_sat (arg1);
}
int
exchange (int arg1, int arg2)
{
arg1 = __builtin_rx_xchg (arg2);
return arg1;
}
long
multiply_and_accumulate (long arg1, long arg2, long arg3)
{
@ -157,3 +163,9 @@ rmpa (int * multiplicand, int * multiplier, int num)
{
__builtin_rx_rmpa ();
}
void
set_interrupts (void)
{
__builtin_mvtipl (3);
}

View File

@ -1,10 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-mint-register=3" } */
/* { dg-options "-mint-register=3 -msave-acc-in-interrupts" } */
/* Verify that the RX specific function attributes work. */
void fast_interrupt (void) __attribute__((__fast_interrupt__));
void interrupt (void) __attribute__((__interrupt__));
void exception (void) __attribute__((__exception__));
int naked (int) __attribute__((__naked__));
int flag = 0;
@ -13,16 +13,16 @@ int flag = 0;
by the -fixed-xxx gcc command line option. Returns via RTFI. */
void
interrupt (void)
fast_interrupt (void)
{
flag = 1;
}
/* Exception handler. Must preserve any register it uses, even
/* Interrupt handler. Must preserve any register it uses, even
call clobbered ones. Returns via RTE. */
void
exception (void)
interrupt (void)
{
switch (flag)
{

View File

@ -1,6 +1,6 @@
/* { dg-do run } */
/* { dg-options "-msim" } */
/* Note: The -msim abiove is actually there to override the default
/* Note: The -msim above is actually there to override the default
options which include -ansi -pendantic and -Wlong-long... */
extern int printf (const char *, ...);