mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 04:10:26 +08:00
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:
parent
48d3ee1d0a
commit
9595a419c6
@ -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.
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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...
|
||||
|
@ -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.
|
||||
|
@ -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 =
|
||||
|
||||
|
@ -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
|
||||
|
@ -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}}
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 *, ...);
|
||||
|
Loading…
x
Reference in New Issue
Block a user