diff options
author | nickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-03 16:25:29 +0000 |
---|---|---|
committer | nickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-03 16:25:29 +0000 |
commit | 67e66e16928468050d4593ada24a16013fe3ca20 (patch) | |
tree | e2ed6b0428b652d000e627bca0a843d199164895 /gcc/config/rx | |
parent | 98f767b793f057165c877f91c46fe0bfd4ee7124 (diff) | |
download | gcc-67e66e16928468050d4593ada24a16013fe3ca20.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@153853 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/rx')
-rw-r--r-- | gcc/config/rx/constraints.md | 2 | ||||
-rw-r--r-- | gcc/config/rx/predicates.md | 18 | ||||
-rw-r--r-- | gcc/config/rx/rx.c | 268 | ||||
-rw-r--r-- | gcc/config/rx/rx.h | 59 | ||||
-rw-r--r-- | gcc/config/rx/rx.md | 82 | ||||
-rw-r--r-- | gcc/config/rx/rx.opt | 34 | ||||
-rw-r--r-- | gcc/config/rx/t-rx | 6 |
7 files changed, 333 insertions, 136 deletions
diff --git a/gcc/config/rx/constraints.md b/gcc/config/rx/constraints.md index f15b586afb5..52bf7df3621 100644 --- a/gcc/config/rx/constraints.md +++ b/gcc/config/rx/constraints.md @@ -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") diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md index 75cf8ebaed8..d7a363ebb88 100644 --- a/gcc/config/rx/predicates.md +++ b/gcc/config/rx/predicates.md @@ -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; diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index cf2b098e83c..885f52581de 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -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 (register_mask) + if (is_interrupt_func (NULL_TREE) && TARGET_SAVE_ACC_REGISTER) { - unsigned int reg; + 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) + { 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); @@ -1733,20 +1842,6 @@ rx_init_builtins (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) { if (reg && ! REG_P (arg)) @@ -1791,6 +1886,21 @@ rx_expand_builtin_mvfc (tree t_arg, rtx 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)) { rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); @@ -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 diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h index a01e194910b..bb7cf7f1e3e 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -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) diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 165da4f41a1..360f6235558 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -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... diff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt index 83e75bfba76..768d565b478 100644 --- a/gcc/config/rx/rx.opt +++ b/gcc/config/rx/rx.opt @@ -19,13 +19,31 @@ ; <http://www.gnu.org/licenses/>. ;--------------------------------------------------- +m32bit-doubles +Target RejectNegative Mask(32BIT_DOUBLES) +Stores doubles in 32 bits. + m64bit-doubles -Target RejectNegative Mask(64BIT_DOUBLES) -Store doubles in 64 bits. +Target RejectNegative InverseMask(32BIT_DOUBLES) +Store doubles in 64 bits. This is the default. -m32bit-doubles -Target RejectNegative InverseMask(64BIT_DOUBLES) -Stores doubles in 32 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. diff --git a/gcc/config/rx/t-rx b/gcc/config/rx/t-rx index 39cda72af57..eb1ca48d3a3 100644 --- a/gcc/config/rx/t-rx +++ b/gcc/config/rx/t-rx @@ -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 = |