From cc11b5226a939e73bcdc4d5b5f0583c110d1edd7 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Mon, 27 Oct 2025 12:30:03 +0000 Subject: [PATCH] rx: Update rx gcc from Renesas release This commit pickup the changes from GCC for RX release by Renesas to support newer RX devices and functionality Changes are pickup from https://llvm-gcc-renesas.com/rx/rx-latest-source-code/ Signed-off-by: Duy Nguyen --- gcc/common/config/rx/rx-common.cc | 4 +- gcc/config.gcc | 4 +- gcc/config/rx/constraints.md | 79 + gcc/config/rx/elf.opt | 2 +- gcc/config/rx/predicates.md | 49 +- gcc/config/rx/rx-opts.h | 30 +- gcc/config/rx/rx-pragma.c | 56 + gcc/config/rx/rx-protos.h | 9 + gcc/config/rx/rx.cc | 3005 ++++++++++++++++++++++---- gcc/config/rx/rx.h | 220 +- gcc/config/rx/rx.md | 3293 +++++++++++++++++++++++++---- gcc/config/rx/rx.opt | 124 +- gcc/config/rx/rx.opt.urls | 35 +- gcc/config/rx/t-rx | 115 +- gcc/config/rx/t-zephyr | 117 +- gcc/config/sh/sh.md | 48 +- libgcc/config/rx/rx-lib.h | 7 +- 17 files changed, 6276 insertions(+), 921 deletions(-) create mode 100644 gcc/config/rx/rx-pragma.c diff --git a/gcc/common/config/rx/rx-common.cc b/gcc/common/config/rx/rx-common.cc index ce4bd75028ce8..e26a252a2abc2 100644 --- a/gcc/common/config/rx/rx-common.cc +++ b/gcc/common/config/rx/rx-common.cc @@ -51,11 +51,11 @@ rx_handle_option (struct gcc_options *opts, return value >= 0 && value <= 4; case OPT_mcpu_: - if ((enum rx_cpu_types) value == RX200 || + if ((enum rx_cpu_types) value == RX200 || (enum rx_cpu_types) value == RX100) opts->x_target_flags |= MASK_NO_USE_FPU; break; - + case OPT_fpu: if (opts->x_rx_cpu_type == RX200) error_at (loc, "the RX200 cpu does not have FPU hardware"); diff --git a/gcc/config.gcc b/gcc/config.gcc index 6a1b27cd2e018..76f0e36be0d47 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -187,7 +187,7 @@ # the --with-sysroot configure option or the # --sysroot command line option is used this # will be relative to the sysroot. -# target_type_format_char +# target_type_format_char # The default character to be used for formatting # the attribute in a # .type symbol_name, ${t_t_f_c} @@ -3254,6 +3254,8 @@ rx-*-elf*) tmake_file="${tmake_file} rx/t-rx" ;; esac + c_target_objs="rx-pragma.o" + cxx_target_objs="rx-pragma.o" extra_options="${extra_options} rx/elf.opt" ;; rx-*-linux*) diff --git a/gcc/config/rx/constraints.md b/gcc/config/rx/constraints.md index c5188a3bc781f..d6fb0c63982b6 100644 --- a/gcc/config/rx/constraints.md +++ b/gcc/config/rx/constraints.md @@ -32,6 +32,13 @@ ) ) +(define_constraint "Ibset" + "@internal An unsigned 8-bit immediate value with a single bit set" + (and (match_code "const_int") + (match_test "exact_log2 (ival) != -1") + ) +) + (define_constraint "Sint08" "@internal A signed 8-bit immediate value" (and (match_code "const_int") @@ -63,6 +70,20 @@ ) ) +(define_constraint "Uint05" + "@internal An unsigned 5-bit immediate value" + (and (match_code "const_int") + (match_test "IN_RANGE (ival, 0, 31)") + ) +) + +(define_constraint "Uintz5" + "@internal An unsigned ,non-zero, 5-bit immediate value" + (and (match_code "const_int") + (match_test "IN_RANGE (ival, 1, 31)") + ) +) + (define_constraint "NEGint4" "@internal An signed 4-bit negative immediate value" (and (match_code "const_int") @@ -87,6 +108,14 @@ ) ) +(define_register_constraint "DFPUreg" "DOUBLE_REGS" + "The DFPU registers") + +(define_constraint "DoubleC" + "Const double." + (match_code "const_double") +) + (define_constraint "Rpid" "A MEM to a PID variable" (and (match_code "mem") @@ -107,6 +136,56 @@ ) ) +(define_memory_constraint "Rreg" + "A MEM which only uses REG addressing." + (and (match_code "mem") + (match_code "reg" "0") + ) +) + +(define_memory_constraint "Rd05" + "A MEM which only uses REG+INT addressing with 5-bit displacement." + (and (match_code "mem") + (and (match_code "plus" "0") + (and (match_code "reg,subreg" "00") + (and (match_code "const_int" "01") + (match_test "IN_RANGE (INTVAL (XEXP (XEXP (op, 0), 1)), + 0, 31 * GET_MODE_SIZE (GET_MODE (op)))") + ) + ) + ) + ) +) + +(define_memory_constraint "Rd08" + "A MEM which only uses REG+INT addressing with 8-bit displacement." + (and (match_code "mem") + (and (match_code "plus" "0") + (and (match_code "reg,subreg" "00") + (and (match_code "const_int" "01") + (match_test "IN_RANGE (INTVAL (XEXP (XEXP (op, 0), 1)), + 0, 255 * GET_MODE_SIZE (GET_MODE (op)))") + ) + ) + ) + ) +) + +(define_constraint "RXV2" +"Reg constraint for RXV2 instructions" +(and (match_code "reg") + (match_test "TARGET_RXV2") + ) +) + +(define_constraint "RXV3" +"Reg constraint for RXV3 instructions" +(and (match_code "reg") + (match_test "TARGET_RXV3") + ) +) + + (define_constraint "CALL_OP_SYMBOL_REF" "constraint for call instructions using symbol ref" (and (match_test "!TARGET_JSR") diff --git a/gcc/config/rx/elf.opt b/gcc/config/rx/elf.opt index a8d1d6bfaa771..b685a4e75408f 100644 --- a/gcc/config/rx/elf.opt +++ b/gcc/config/rx/elf.opt @@ -34,7 +34,7 @@ Generate assembler output that is compatible with the Renesas AS100 assembler. ;--------------------------------------------------- mint-register= -Target RejectNegative Joined UInteger Var(rx_interrupt_registers) Init(0) +Target RejectNegative Joined UInteger Var(rx_deferred_options) Defer Specifies the number of registers to reserve for interrupt handlers. ;--------------------------------------------------- diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md index 31cc7b55e4070..e4eea96cef56b 100644 --- a/gcc/config/rx/predicates.md +++ b/gcc/config/rx/predicates.md @@ -49,6 +49,16 @@ (match_test "IN_RANGE (INTVAL (op), 0, 31)")) ) +(define_predicate "rx_bitclr_operand" + (and (match_code "const_int") + (match_test "exact_log2 (~INTVAL (op)) != -1")) +) + +(define_predicate "rx_bitset_operand" + (and (match_code "const_int") + (match_test "exact_log2 (INTVAL (op)) != -1")) +) + (define_predicate "rx_restricted_mem_operand" (and (match_code "mem") (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)")) @@ -64,6 +74,13 @@ (match_operand 0 "rx_restricted_mem_operand")) ) +(define_predicate "rx_speed_source_operand" + (ior (match_operand 0 "register_operand") + (match_operand 0 "immediate_operand") + (and (match_test "optimize_size") + (match_operand 0 "rx_restricted_mem_operand"))) +) + ;; Check that the operand is suitable as the source operand ;; for a comparison instruction. This is the same as ;; rx_source_operand except that SUBREGs are allowed but @@ -84,6 +101,18 @@ (match_operand 0 "rx_restricted_mem_operand")) ) +(define_predicate "rx_speed_minmaxex_operand" + (ior (match_operand 0 "immediate_operand") + (and (match_test "optimize_size") + (match_operand 0 "rx_restricted_mem_operand"))) +) + +(define_predicate "rx_speed_compare_operand" + (ior (match_operand 0 "register_operand") + (and (match_test "optimize_size") + (match_operand 0 "rx_restricted_mem_operand"))) +) + ;; Return true if OP is a store multiple operation. This looks like: ;; ;; [(set (SP) (MINUS (SP) (INT))) @@ -114,33 +143,15 @@ || ! CONST_INT_P (XEXP (SET_SRC (element), 1))) return false; - /* 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)) - || 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- addressing and decreasing register numbers. */ - for (i = 2; i < count; i++) + for (i = 1; i < count - 1; i++) { element = XVECEXP (op, 0, i); if ( ! SET_P (element) || ! REG_P (SET_SRC (element)) || GET_MODE (SET_SRC (element)) != SImode - || 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 diff --git a/gcc/config/rx/rx-opts.h b/gcc/config/rx/rx-opts.h index 86cdfb4f4be64..1e9329d74837a 100644 --- a/gcc/config/rx/rx-opts.h +++ b/gcc/config/rx/rx-opts.h @@ -22,10 +22,38 @@ enum rx_cpu_types { + RX13T, + RX230, + RX71M, + RX72T, + RX64M, RX600, RX610, + RX66T, RX200, - RX100 + RX100, + RX140, + RX_CPUUNINIT +}; +enum rx_tfu_versions +{ + RX_TFUV1, + RX_TFUV2, + RX_TFUVUNINIT +}; +enum rx_isa_versions +{ + RX_ISAV1, + RX_ISAV2, + RX_ISAV3, + RX_ISAUNINIT +}; + +enum rx_tfu_types +{ + RX_INTRINSIC, + RX_MATHLIB, + RX_TFUUNINIT }; #endif diff --git a/gcc/config/rx/rx-pragma.c b/gcc/config/rx/rx-pragma.c new file mode 100644 index 0000000000000..ad20298bc759f --- /dev/null +++ b/gcc/config/rx/rx-pragma.c @@ -0,0 +1,56 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "c-family/c-pragma.h" +#include "c-family/c-common.h" +#include "diagnostic-core.h" +#include "cpplib.h" +#include "hard-reg-set.h" +#include "output.h" +#include "rx-protos.h" +#include "function.h" +#define MAX_RECOG_OPERANDS 10 +#include "reload.h" +#include "target.h" + +/* Implements the "pragma ADDRESS" pragma. This pragma takes a + * variable name and an address, and arranges for that variable to be + * "at" that address. The variable is also made volatile. */ +static void +rx_pragma_address (cpp_reader * reader ATTRIBUTE_UNUSED) +{ + /* on off */ + tree var, addr; + enum cpp_ttype type; + + type = pragma_lex (&var); + if (type == CPP_NAME) + { + type = pragma_lex (&addr); + if (type == CPP_NUMBER) + { + if (var != error_mark_node) + { + unsigned uaddr = tree_to_uhwi (addr); + rx_note_pragma_address (IDENTIFIER_POINTER (var), uaddr); + } + + type = pragma_lex (&var); + if (type != CPP_EOF) + { + error ("junk at end of #pragma ADDRESS"); + } + return; + } + } + error ("malformed #pragma ADDRESS variable address"); +} + +void +rx_register_pragmas (void) +{ + c_register_pragma (NULL, "ADDRESS", rx_pragma_address); + c_register_pragma (NULL, "address", rx_pragma_address); +} diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h index 7b4614657c085..4020d87189e78 100644 --- a/gcc/config/rx/rx-protos.h +++ b/gcc/config/rx/rx-protos.h @@ -25,6 +25,14 @@ extern bool rx_can_use_simple_return (void); extern void rx_expand_epilogue (bool); extern void rx_expand_prologue (void); extern int rx_initial_elimination_offset (int, int); +extern void rx_register_pragmas (void); +extern void rx_note_pragma_address (const char *varname, unsigned address); +extern void rx_output_aligned_common (FILE *stream, tree decl ATTRIBUTE_UNUSED, const char *name,int size, int align); +extern void rx_adjust_reg_alloc_order (void); +extern enum reg_class rx_regno_class (int); +extern bool rx_hard_regno_mode_ok (unsigned regno, machine_mode mode); +extern unsigned int rx_regmode_natural_size (enum machine_mode mode); +extern unsigned int rx_dbx_register_number (unsigned int); bool is_interrupt_func (const_tree decl); bool is_fast_interrupt_func (const_tree decl); @@ -53,6 +61,7 @@ extern int rx_adjust_insn_length (rtx_insn *, int); extern align_flags rx_align_for_label (rtx_insn *, int); extern void rx_emit_stack_popm (rtx *, bool); extern void rx_emit_stack_pushm (rtx *); +extern void rx_emit_stack_dpushm (rtx *); extern char * rx_gen_move_template (rtx *, bool); extern bool rx_is_legitimate_constant (machine_mode, rtx); extern bool rx_is_restricted_memory_address (rtx, diff --git a/gcc/config/rx/rx.cc b/gcc/config/rx/rx.cc index 9bf9d87fed173..1ef82d0d11f16 100644 --- a/gcc/config/rx/rx.cc +++ b/gcc/config/rx/rx.cc @@ -47,10 +47,20 @@ #include "flags.h" #include "explow.h" #include "expr.h" +#include "optabs.h" +#include "libfuncs.h" +#include "recog.h" #include "toplev.h" +#include "reload.h" +#include "ggc.h" +#include "debug.h" #include "langhooks.h" #include "opts.h" #include "builtins.h" +#include "tree-pass.h" +#include "ifcvt.h" + +#include "insn-attr.h" /* This file should be included last. */ #include "target-def.h" @@ -58,7 +68,7 @@ static unsigned int rx_gp_base_regnum_val = INVALID_REGNUM; static unsigned int rx_pid_base_regnum_val = INVALID_REGNUM; static unsigned int rx_num_interrupt_regs; - + static unsigned int rx_gp_base_regnum (void) { @@ -129,7 +139,9 @@ rx_pid_data_operand (rtx op) if (op_decl) { - if (TREE_READONLY (op_decl)) + if (TREE_READONLY (op_decl) + || TREE_CODE (op_decl) == FUNCTION_DECL + || TREE_CODE (op_decl) == LABEL_DECL) return PID_UNENCODED; } else @@ -156,7 +168,7 @@ rx_legitimize_address (rtx x, if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS - && REG_P (XEXP (XEXP (x, 0), 0)) + && REG_P (XEXP (XEXP (x, 0), 0)) && REG_P (XEXP (x, 1))) return force_reg (SImode, x); @@ -171,6 +183,9 @@ rx_small_data_operand (rtx op) if (rx_small_data_limit == 0) return false; + if (TARGET_64BIT_DOUBLES) + return false; + if (GET_CODE (op) == SYMBOL_REF) return SYMBOL_REF_SMALL_P (op); @@ -232,7 +247,7 @@ rx_is_legitimate_address (machine_mode mode, rtx x, switch (GET_MODE_SIZE (mode)) { - default: + default: case 4: factor = 4; break; case 2: factor = 2; break; case 1: factor = 1; break; @@ -250,6 +265,10 @@ rx_is_legitimate_address (machine_mode mode, rtx x, case MULT: { + if(GET_MODE_SIZE (mode) > 4) + { + return false; + } /* Scaled Indexed Register Indirect: REG + (REG * FACTOR) Factor has to equal the mode size, REG has to be valid. */ rtx factor; @@ -272,7 +291,35 @@ rx_is_legitimate_address (machine_mode mode, rtx x, return rx_small_data_operand (x); } -/* Returns TRUE for simple memory addresses, ie ones +enum reg_class +rx_regno_class (int regno) +{ + if(regno >= FIRST_PSEUDO_REGISTER) + return NO_REGS; + else if (regno >= 16) + return DOUBLE_REGS; + else + return GR_REGS; +} + +unsigned int +rx_dbx_register_number (unsigned int regno) +{ + if (REGNO_REG_CLASS (regno) == GR_REGS) + return regno; + else if (regno == CC_REG) + return 16; + else if (regno == PC_REGNUM) + return 17; + else if (REGNO_REG_CLASS (regno) == DOUBLE_REGS) + return ((regno - 16) / 2) + 32; + + /* Return values >= DWARF_FRAME_REGISTERS indicate that there is no + equivalent DWARF register. */ + return DWARF_FRAME_REGISTERS; +} + +/* Returns TRUE for simple memory addreses, ie ones that do not involve register indirect addressing or pre/post increment/decrement. */ @@ -299,7 +346,7 @@ rx_is_restricted_memory_address (rtx mem, machine_mode mode) case PLUS: { rtx base, index; - + /* Only allow REG+INT addressing. */ base = XEXP (mem, 0); index = XEXP (mem, 1); @@ -503,11 +550,12 @@ rx_assemble_integer (rtx x, unsigned int size, int is_aligned) } -/* Handles the insertion of a single operand into the assembler output. +/* Handles the insertion of a single operand into the assembler output.op The % directives supported are: %A Print an operand without a leading # character. %B Print an integer comparison name. + %b Print a bit number based on a single set or cleared bit. %C Print a control register name. %F Print a condition code flag name. %G Register used for small-data-area addressing @@ -517,7 +565,10 @@ rx_assemble_integer (rtx x, unsigned int size, int is_aligned) %P Register used for PID addressing %Q If the operand is a MEM, then correctly generate register indirect or register relative addressing. - %R Like %Q but for zero-extending loads. */ + %R Like %Q but for zero-extending loads. + %S %Q with unsigned mode. + %U print QI unsigned constant + %V print HI unsigned constant */ static void rx_print_operand (FILE * file, rtx op, int letter) @@ -542,98 +593,109 @@ rx_print_operand (FILE * file, rtx op, int letter) op = XEXP (op, 0); switch (GET_CODE (op)) - { - case LABEL_REF: - case SYMBOL_REF: - output_addr_const (file, op); - break; - case CONST_INT: - fprintf (file, "%ld", (long) INTVAL (op)); - break; - default: - rx_print_operand (file, op, 0); - break; - } + { + case LABEL_REF: + case SYMBOL_REF: + output_addr_const (file, op); + break; + case CONST_INT: + fprintf (file, "%ld", (long) INTVAL (op)); + break; + default: + rx_print_operand (file, op, 0); + break; + } break; case 'B': - { - enum rtx_code code = GET_CODE (op); - machine_mode mode = GET_MODE (XEXP (op, 0)); - const char *ret; + { + enum rtx_code code = GET_CODE (op); + enum machine_mode mode = GET_MODE (XEXP (op, 0)); + const char *ret; - if (mode == CC_Fmode) - { + if (mode == CC_Fmode) + { /* C flag is undefined, and O flag carries unordered. None of the branch combinations that include O use it helpfully. */ - switch (code) - { - case ORDERED: - ret = "no"; - break; - case UNORDERED: - ret = "o"; - break; - case LT: - ret = "n"; - break; - case GE: - ret = "pz"; - break; - case EQ: - ret = "eq"; - break; - case NE: - ret = "ne"; - break; - default: - gcc_unreachable (); - } - } - else + switch (code) + { + case ORDERED: + ret = "no"; + break; + case UNORDERED: + ret = "o"; + break; + case LT: + ret = "n"; + break; + case GE: + ret = "pz"; + break; + case EQ: + ret = "eq"; + break; + case NE: + ret = "ne"; + break; + default: + gcc_unreachable (); + } + } + else + { + unsigned int flags = flags_from_mode (mode); + + switch (code) + { + case LT: + ret = (flags & CC_FLAG_O ? "lt" : "n"); + break; + case GE: + ret = (flags & CC_FLAG_O ? "ge" : "pz"); + break; + case GT: + ret = "gt"; + break; + case LE: + ret = "le"; + break; + case GEU: + ret = "geu"; + break; + case LTU: + ret = "ltu"; + break; + case GTU: + ret = "gtu"; + break; + case LEU: + ret = "leu"; + break; + case EQ: + ret = "eq"; + break; + case NE: + ret = "ne"; + break; + default: + gcc_unreachable (); + } + gcc_checking_assert ((flags_from_code (code) & ~flags) == 0); + } + fputs (ret, file); + break; + } + case 'b': { - unsigned int flags = flags_from_mode (mode); + int b; - switch (code) - { - case LT: - ret = (flags & CC_FLAG_O ? "lt" : "n"); - break; - case GE: - ret = (flags & CC_FLAG_O ? "ge" : "pz"); - break; - case GT: - ret = "gt"; - break; - case LE: - ret = "le"; - break; - case GEU: - ret = "geu"; - break; - case LTU: - ret = "ltu"; - break; - case GTU: - ret = "gtu"; - break; - case LEU: - ret = "leu"; - break; - case EQ: - ret = "eq"; - break; - case NE: - ret = "ne"; - break; - default: - gcc_unreachable (); - } - gcc_checking_assert ((flags_from_code (code) & ~flags) == 0); + gcc_assert (CONST_INT_P (op)); + b = exact_log2 (INTVAL (op)); + if (b == -1) + b = exact_log2 (~ INTVAL (op)); + fprintf (file, "#%d", b); } - fputs (ret, file); - break; - } + break; case 'C': gcc_assert (CONST_INT_P (op)); @@ -648,6 +710,7 @@ rx_print_operand (FILE * file, rtx op, int letter) case CTRLREG_ISP: fprintf (file, "isp"); break; case CTRLREG_FINTV: fprintf (file, "fintv"); break; case CTRLREG_INTB: fprintf (file, "intb"); break; + case CTRLREG_EXTB: fprintf (file, "extb"); break; default: warning (0, "unrecognized control register number: %d" " - using %", (int) INTVAL (op)); @@ -655,20 +718,35 @@ rx_print_operand (FILE * file, rtx op, int letter) break; } break; - + case 'D': + gcc_assert (CONST_INT_P (op)); + switch (INTVAL (op)) + { + case 0: fprintf (file, "dpsw"); break; + case 1: fprintf (file, "dcmr"); break; + case 2: fprintf (file, "decnt"); break; + case 3: fprintf (file, "depc"); break; + default: + warning (0, "unrecognized control register number: %d - using 'dpsw'", + (int) INTVAL (op)); + fprintf (file, "dpsw"); + break; + } + break; case 'F': gcc_assert (CONST_INT_P (op)); switch (INTVAL (op)) - { - case 0: case 'c': case 'C': fprintf (file, "C"); break; - case 1: case 'z': case 'Z': fprintf (file, "Z"); break; - case 2: case 's': case 'S': fprintf (file, "S"); break; - case 3: case 'o': case 'O': fprintf (file, "O"); break; - case 8: case 'i': case 'I': fprintf (file, "I"); break; - case 9: case 'u': case 'U': fprintf (file, "U"); break; - default: - gcc_unreachable (); - } + { + case 0: case 'c': case 'C': fprintf (file, "C"); break; + case 1: case 'z': case 'Z': fprintf (file, "Z"); break; + case 2: case 's': case 'S': fprintf (file, "S"); break; + case 3: case 'o': case 'O': fprintf (file, "O"); break; + case 8: case 'i': case 'I': fprintf (file, "I"); break; + case 9: case 'u': case 'U': fprintf (file, "U"); break; + default: + error ("__builtin_rx_setpsw takes 'C', 'Z', 'S', 'O', 'I', or 'U'"); + return; + } break; case 'G': @@ -677,57 +755,79 @@ rx_print_operand (FILE * file, rtx op, int letter) case 'H': switch (GET_CODE (op)) - { - case REG: - fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 0 : 1)]); - break; - case CONST_INT: - { - HOST_WIDE_INT v = INTVAL (op); - - fprintf (file, "#"); - /* Trickery to avoid problems with shifting 32 bits at a time. */ - v = v >> 16; - v = v >> 16; - rx_print_integer (file, v); - break; - } - case CONST_DOUBLE: - fprintf (file, "#"); - rx_print_integer (file, CONST_DOUBLE_HIGH (op)); - break; - case MEM: - if (! WORDS_BIG_ENDIAN) - op = adjust_address (op, SImode, 4); - output_address (GET_MODE (op), XEXP (op, 0)); - break; - default: - gcc_unreachable (); - } + { + case REG: + if(REGNO (op) >= FIRST_DOUBLE_REG) + { + fprintf (file, "drh%u", (REGNO (op) - FIRST_DOUBLE_REG)/2); + } + else + { + fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 0 : 1)]); + } + break; + case CONST_INT: + { + HOST_WIDE_INT v = INTVAL (op); + + fprintf (file, "#"); + /* Trickery to avoid problems with shifting 32 bits at a time. */ + v = v >> 16; + v = v >> 16; + rx_print_integer (file, v); + break; + } + case CONST_DOUBLE: + fprintf (file, "#"); + { + long t[2]; + REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), t); + rx_print_integer (file, WORDS_BIG_ENDIAN? t[0] : t[1]); + } + break; + case MEM: + if (! WORDS_BIG_ENDIAN) + op = adjust_address (op, SImode, 4); + output_address (GET_MODE (op), XEXP (op, 0)); + break; + default: + gcc_unreachable (); + } break; case 'L': switch (GET_CODE (op)) - { - case REG: - fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 1 : 0)]); - break; - case CONST_INT: - fprintf (file, "#"); - rx_print_integer (file, INTVAL (op) & 0xffffffff); - break; - case CONST_DOUBLE: - fprintf (file, "#"); - rx_print_integer (file, CONST_DOUBLE_LOW (op)); - break; - case MEM: - if (WORDS_BIG_ENDIAN) - op = adjust_address (op, SImode, 4); - output_address (GET_MODE (op), XEXP (op, 0)); - break; - default: - gcc_unreachable (); - } + { + case REG: + if(REGNO (op) >= FIRST_DOUBLE_REG) + { + fprintf (file, "drl%u", (REGNO (op) - FIRST_DOUBLE_REG)/2); + } + else + { + fprintf (file, "%s", reg_names [REGNO (op) + (WORDS_BIG_ENDIAN ? 1 : 0)]); + } + break; + case CONST_INT: + fprintf (file, "#"); + rx_print_integer (file, INTVAL (op) & 0xffffffff); + break; + case CONST_DOUBLE: + fprintf (file, "#"); + { + long t[2]; + REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), t); + rx_print_integer (file, WORDS_BIG_ENDIAN? t[1] : t[0]); + } + break; + case MEM: + if (WORDS_BIG_ENDIAN) + op = adjust_address (op, SImode, 4); + output_address (GET_MODE (op), XEXP (op, 0)); + break; + default: + gcc_unreachable (); + } break; case 'N': @@ -740,8 +840,20 @@ rx_print_operand (FILE * file, rtx op, int letter) fprintf (file, "%s", reg_names [rx_pid_base_regnum ()]); break; + case 'U': + if (print_hash) + fprintf (file, "#"); + fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, UINTVAL(op) & 0xFF); + break; + + case 'V': + if (print_hash) + fprintf (file, "#"); + fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, UINTVAL(op) & 0xFFFF); + break; + case 'R': - gcc_assert (GET_MODE_SIZE (GET_MODE (op)) <= 4); + gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4); unsigned_load = true; /* Fall through. */ case 'Q': @@ -783,27 +895,30 @@ rx_print_operand (FILE * file, rtx op, int letter) rx_print_operand (file, op, 0); fprintf (file, "]."); - switch (GET_MODE_SIZE (GET_MODE (mem))) - { - case 1: - gcc_assert (offset <= 65535 * 1); - fprintf (file, unsigned_load ? "UB" : "B"); - break; - case 2: - gcc_assert (offset % 2 == 0); - gcc_assert (offset <= 65535 * 2); - fprintf (file, unsigned_load ? "UW" : "W"); - break; - case 4: - gcc_assert (offset % 4 == 0); - gcc_assert (offset <= 65535 * 4); - fprintf (file, "L"); - break; - default: - gcc_unreachable (); - } - break; - } + switch (GET_MODE_SIZE (GET_MODE (mem))) + { + case 1: + gcc_assert (offset <= 65535 * 1); + if (letter == 'R') + fprintf (file, "UB"); + else + fprintf (file, "B"); + break; + case 2: + gcc_assert (offset % 2 == 0); + gcc_assert (offset <= 65535 * 2); + if (letter == 'R') + fprintf (file, "UW"); + else + fprintf (file, "W"); + break; + default: + gcc_assert (offset % 4 == 0); + gcc_assert (offset <= 65535 * 4); + fprintf (file, "L"); + } + break; + } /* Fall through. */ @@ -1002,14 +1117,14 @@ rx_gen_move_template (rtx * operands, bool is_movu) { gcc_assert (GET_MODE (src) != DImode); gcc_assert (GET_MODE (src) != DFmode); - + src_template = "(%A1 - __pid_base)[%P1]"; } else if (MEM_P (src) && rx_small_data_operand (XEXP (src, 0))) { gcc_assert (GET_MODE (src) != DImode); gcc_assert (GET_MODE (src) != DFmode); - + src_template = "%%gp(%A1)[%G1]"; } else @@ -1019,7 +1134,7 @@ rx_gen_move_template (rtx * operands, bool is_movu) { gcc_assert (GET_MODE (dest) != DImode); gcc_assert (GET_MODE (dest) != DFmode); - + dst_template = "%%gp(%A0)[%G0]"; } else @@ -1119,8 +1234,6 @@ rx_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED, /* Older versions of the RX backend aligned all on-stack arguments to 32-bits. The RX C ABI however says that they should be aligned to their natural alignment. (See section 5.2.2 of the ABI). */ - if (TARGET_GCC_ABI) - return STACK_BOUNDARY; if (type) { @@ -1151,7 +1264,7 @@ rx_function_value (const_tree ret_type, && ! VECTOR_MODE_P (mode) ) return gen_rtx_REG (SImode, FUNC_RETURN_REGNUM); - + return gen_rtx_REG (mode, FUNC_RETURN_REGNUM); } @@ -1241,9 +1354,29 @@ is_naked_func (const_tree decl) { return has_func_attr (decl, "naked"); } + +/* Returns true if the provided function has the "save" attribute. */ + +static inline bool +is_interrupt_bank_func (const_tree decl) +{ + return has_func_attr (decl, "interrupt_bank"); +} static bool use_fixed_regs = false; +char rx_leaf_registers [FIRST_PSEUDO_REGISTER]; + +static void +rx_set_leaf_registers (int enable) +{ + int i; + + if (rx_leaf_registers[0] != enable) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + rx_leaf_registers[i] = enable; +} + static void rx_conditional_register_usage (void) { @@ -1278,16 +1411,18 @@ rx_conditional_register_usage (void) memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs); /* This is for fast interrupt handlers. Any register in - the range r10 to r13 (inclusive) that is currently - marked as fixed is now a viable, call-used register. */ - for (r = 10; r <= 13; r++) - if (fixed_regs[r]) - { - fixed_regs[r] = 0; - call_used_regs[r] = 1; - } - - /* Mark r7 as fixed. This is just a hack to avoid + the range r11 to r13 (inclusive) that is currently + marked as fixed is now a viable, call-used register. */ + for (r = 11; r <= 13; r++) + if (fixed_regs[r] + && r != rx_pid_base_regnum_val + && r != rx_gp_base_regnum_val) + { + fixed_regs[r] = 0; + call_used_regs[r] = 1; + } + + /* Mark r7 as fixed. This is just a hack to avoid altering the reg_alloc_order array so that the newly freed r10-r13 registers are the preferred registers. */ fixed_regs[7] = call_used_regs[7] = 1; @@ -1363,7 +1498,7 @@ rx_set_current_function (tree fndecl) current_is_fast_interrupt = fndecl ? is_fast_interrupt_func (fndecl) : false; - + if (prev_was_fast_interrupt != current_is_fast_interrupt) { use_fixed_regs = current_is_fast_interrupt; @@ -1438,7 +1573,8 @@ bit_count (unsigned int x) #define MUST_SAVE_ACC_REGISTER \ (TARGET_SAVE_ACC_REGISTER \ && (is_interrupt_func (NULL_TREE) \ - || is_fast_interrupt_func (NULL_TREE))) + || is_fast_interrupt_func (NULL_TREE) \ + || is_interrupt_bank_func (NULL_TREE))) #else #define MUST_SAVE_ACC_REGISTER 0 #endif @@ -1454,6 +1590,8 @@ bit_count (unsigned int x) static void rx_get_stack_layout (unsigned int * lowest, unsigned int * highest, + unsigned int * dr_lowest, + unsigned int * dr_highest, unsigned int * register_mask, unsigned int * frame_size, unsigned int * stack_size) @@ -1475,22 +1613,31 @@ rx_get_stack_layout (unsigned int * lowest, * register_mask = 0; * frame_size = 0; * stack_size = 0; + * dr_lowest = 0; + * dr_highest = 0; return; } - for (save_mask = high = low = 0, reg = 1; reg < CC_REGNUM; reg++) + for (save_mask = high = low = 0, reg = 1; reg < FIRST_DOUBLE_REG; reg++) { + + if( rx_num_interrupt_regs <= 4 && ( + reg == 13 && rx_num_interrupt_regs > 0 || + reg == 12 && rx_num_interrupt_regs > 1 || + reg == 11 && rx_num_interrupt_regs > 2 || + reg == 10 && rx_num_interrupt_regs > 3)) continue; + if ((df_regs_ever_live_p (reg) /* Always save all call clobbered registers inside non-leaf interrupt handlers, even if they are not live - they may be used in (non-interrupt aware) routines called from this one. */ || (call_used_or_fixed_reg_p (reg) - && is_interrupt_func (NULL_TREE) + && (is_interrupt_func (NULL_TREE) || is_interrupt_bank_func (NULL_TREE)) && ! crtl->is_leaf)) && (! call_used_or_fixed_reg_p (reg) /* Even call clobbered registered must be pushed inside interrupt handlers. */ - || is_interrupt_func (NULL_TREE) + || (is_interrupt_func (NULL_TREE) || is_interrupt_bank_func (NULL_TREE)) /* Likewise for fast interrupt handlers, except registers r10 - r13. These are normally call-saved, but may have been set to call-used by rx_conditional_register_usage. If so then @@ -1568,6 +1715,37 @@ rx_get_stack_layout (unsigned int * lowest, * register_mask = 0; } + *dr_lowest = 0; + *dr_highest = 0; + if(flag_dfpu) + { + unsigned int d_low = CC_REGNUM - 1; + unsigned int d_high = FIRST_DOUBLE_REG; + for (reg = FIRST_DOUBLE_REG; reg < CC_REGNUM; reg++) + if(df_regs_ever_live_p(reg)) + { + d_low = (d_low > reg)? reg : d_low; + d_high = (d_high < reg)? reg : d_high; + } + if(d_low <= d_high) + { + *dr_lowest = d_low; + *dr_highest = d_high; + } + } + + if (FRAME_GROWS_DOWNWARD != 0) + { + *frame_size = 0; + if (crtl->args.size > 0) + * frame_size = rx_round_up(crtl->args.size, STACK_BOUNDARY / BITS_PER_UNIT); + + * stack_size = rx_round_up(get_frame_size(), STACK_BOUNDARY / BITS_PER_UNIT); + * stack_size += rx_round_up(crtl->outgoing_args_size, STACK_BOUNDARY / BITS_PER_UNIT); + } + else + { + * frame_size = rx_round_up (get_frame_size (), STACK_BOUNDARY / BITS_PER_UNIT); @@ -1578,6 +1756,7 @@ rx_get_stack_layout (unsigned int * lowest, * stack_size = rx_round_up (crtl->outgoing_args_size, STACK_BOUNDARY / BITS_PER_UNIT); } +} /* Generate a PUSHM instruction that matches the given operands. */ @@ -1596,9 +1775,20 @@ rx_emit_stack_pushm (rtx * operands) first_push = SET_SRC (first_push); gcc_assert (REG_P (first_push)); - asm_fprintf (asm_out_file, "\tpushm\t%s-%s\n", + if(REGNO(first_push) >= FIRST_DOUBLE_REG) + { + gcc_assert(flag_dfpu); + + asm_fprintf (asm_out_file, "\tdpushm.d\t%s-%s\n", + reg_names [(REGNO (first_push) - last_reg) & (~1)], + reg_names [REGNO (first_push) & (~1)]); + } + else + { + asm_fprintf (asm_out_file, "\tpushm\t%s-%s\n", reg_names [REGNO (first_push) - last_reg], reg_names [REGNO (first_push)]); + } } /* Generate a PARALLEL that will pass the rx_store_multiple_vector predicate. */ @@ -1616,15 +1806,19 @@ gen_rx_store_vector (unsigned int low, unsigned int high) gen_rtx_SET (stack_pointer_rtx, gen_rtx_MINUS (SImode, stack_pointer_rtx, GEN_INT ((count - 1) * UNITS_PER_WORD))); + /* Registers are pushed from high numbered to low. */ + for (i = 0; i < count - 1; i++) + { + int ofs = i + 1; - for (i = 0; i < count - 1; i++) - XVECEXP (vector, 0, i + 1) = - gen_rtx_SET (gen_rtx_MEM (SImode, - gen_rtx_MINUS (SImode, stack_pointer_rtx, - GEN_INT ((i + 1) * UNITS_PER_WORD))), - gen_rtx_REG (SImode, high - i)); - return vector; -} + XVECEXP (vector, 0, i + 1) = + gen_rtx_SET (gen_rtx_MEM (SImode, + gen_rtx_MINUS (SImode, stack_pointer_rtx, + GEN_INT (ofs * 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. */ @@ -1652,7 +1846,6 @@ add_pop_cfi_notes (rtx_insn *insn, unsigned int high, unsigned int low) (high - low + 1) * UNITS_PER_WORD); t = gen_rtx_SET (stack_pointer_rtx, t); add_reg_note (insn, REG_CFA_ADJUST_CFA, t); - RTX_FRAME_RELATED_P (insn) = 1; for (unsigned int i = low; i <= high; i++) add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (word_mode, i)); } @@ -1709,16 +1902,29 @@ gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related) RTX_FRAME_RELATED_P (insn) = 1; } +static void +increase_stack_usage_info(unsigned int size) +{ + if (flag_stack_usage_info || flag_stack_usage) + current_function_static_stack_size += size; +} + static void push_regs (unsigned int high, unsigned int low) { rtx insn; if (low == high) + { insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low))); + increase_stack_usage_info(UNITS_PER_WORD); + } else + { insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1) * UNITS_PER_WORD), gen_rx_store_vector (low, high))); + increase_stack_usage_info(((high - low) + 1) * UNITS_PER_WORD); + } mark_frame_related (insn); } @@ -1730,22 +1936,51 @@ rx_expand_prologue (void) unsigned int mask; unsigned int low; unsigned int high; + unsigned int dr_low; + unsigned int dr_high; unsigned int reg; - + tree inter_bank_attr = lookup_attribute ("interrupt_bank", DECL_ATTRIBUTES (current_function_decl)); /* Naked functions use their own, programmer provided prologues. */ if (is_naked_func (NULL_TREE)) return; - rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size); - - if (flag_stack_usage_info) - current_function_static_stack_size = frame_size + stack_size; - + rx_get_stack_layout (& low, & high, & dr_low, & dr_high, & mask, & frame_size, & stack_size); + + if (inter_bank_attr && TARGET_RXV3) + { + int num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (inter_bank_attr))); + emit_insn (gen_save (GEN_INT (num))); + //we don't push any register using interrupt_bank + low = 0; + high = 0; + dr_low = 0; + dr_high = 0; + mask = 0; + } +if (is_interrupt_func (NULL_TREE) && (rx_tfu_version == RX_TFUV2) && !TARGET_NO_SAVE_TFU) +{ + if(low == 0) + low = 1; + for(unsigned int reg = low; reg<=high; ++reg) + mask |= 1 << reg; + mask |= 0xe; +} +/* Calculate initial stack size based on frame, stack size + and add 4 bytes for the PC. */ + if (flag_stack_usage_info || flag_stack_usage) + { + current_function_static_stack_size = frame_size + stack_size + 4; + if(is_interrupt_func (NULL_TREE) || is_interrupt_bank_func (NULL_TREE)) + { + //add 4 bytes for the saved PSW + current_function_static_stack_size += 4; + } + } /* If we use any of the callee-saved registers, save them now. */ if (mask) { /* Push registers in reverse order. */ - for (reg = CC_REGNUM; reg --;) + for (reg = FIRST_DOUBLE_REG; reg --;) if (mask & (1 << reg)) { low = high = reg; @@ -1767,6 +2002,38 @@ rx_expand_prologue (void) } else if (low) push_regs (high, low); +if (is_interrupt_func (NULL_TREE) && (rx_tfu_version == RX_TFUV2) && !TARGET_NO_SAVE_TFU) + { + if(optimize_size) + { + emit_insn(gen_movsi(gen_rtx_REG (SImode, 1), gen_rtx_CONST_INT (SImode, 0x81430))); + rtx addr = gen_rtx_PLUS(SImode, gen_rtx_REG (SImode, 1), gen_rtx_CONST_INT (SImode, 4)); + emit_insn(gen_movsi(gen_rtx_REG (SImode, 3), gen_rtx_MEM(SImode, addr))); + emit_insn(gen_movsi(gen_rtx_REG (SImode, 2), gen_rtx_MEM(SImode, gen_rtx_REG (SImode, 1)))); + push_regs(3, 1); + } + else + emit_insn(gen_movsi(gen_rtx_REG (SImode, 1), gen_rtx_CONST_INT (SImode, 0x81430))); + rtx addr = gen_rtx_PLUS(SImode, gen_rtx_REG (SImode, 1), gen_rtx_CONST_INT (SImode, 4)); + emit_insn(gen_movsi(gen_rtx_REG (SImode, 3), gen_rtx_MEM(SImode, addr))); + emit_insn(gen_movsi(gen_rtx_REG (SImode, 2), gen_rtx_MEM(SImode, gen_rtx_REG (SImode, 1)))); + push_regs(2, 2); + push_regs(3, 3); + } + if(dr_low != 0) + { + rtx insn = emit_insn(gen_stack_pushm(GEN_INT(((dr_high - dr_low) + 1) * UNITS_PER_WORD), gen_rx_store_vector(dr_low, dr_high))); + increase_stack_usage_info(((dr_high - dr_low) + 1) * UNITS_PER_WORD); + mark_frame_related (insn); + if(flag_dfpu && TARGET_RXV3) + { + insn = emit_insn(gen_stack_dpushm()); + increase_stack_usage_info(1 * UNITS_PER_WORD); + mark_frame_related (insn); + } + + + } if (MUST_SAVE_ACC_REGISTER) { @@ -1779,7 +2046,7 @@ rx_expand_prologue (void) { acc_low = acc_high = 0; - for (reg = 1; reg < CC_REGNUM; reg ++) + for (reg = 1; reg < FIRST_DOUBLE_REG; reg ++) if (mask & (1 << reg)) { if (acc_low == 0) @@ -1790,16 +2057,37 @@ rx_expand_prologue (void) 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))); + if(TARGET_RXV2) + { + emit_insn (gen_mvfaclo_A0 (gen_rtx_REG (SImode, acc_low), gen_rtx_CONST_INT(SImode, 0))); + 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))); + emit_insn (gen_mvfacgu_A0 (gen_rtx_REG (SImode, acc_low), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_mvfaclo_A1 (gen_rtx_REG (SImode, acc_high), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_mvfachi_A1 (gen_rtx_REG (SImode, acc_low), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_mvfacgu_A1 (gen_rtx_REG (SImode, acc_high), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_stack_push (gen_rtx_REG (SImode, acc_high))); + + increase_stack_usage_info(6*UNITS_PER_WORD); + } + else + { + /* 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))); + + increase_stack_usage_info(2*UNITS_PER_WORD); + } } else { @@ -1808,11 +2096,33 @@ rx_expand_prologue (void) /* 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), + if(TARGET_RXV2) + { + /* TODO: improve this to only one pushm */ + emit_insn (gen_mvfaclo_A0 (gen_rtx_REG (SImode, acc_low), gen_rtx_CONST_INT(SImode, 0))); + 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))); + emit_insn (gen_mvfacgu_A0 (gen_rtx_REG (SImode, acc_low), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_mvfaclo_A1 (gen_rtx_REG (SImode, acc_high), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD), + gen_rx_store_vector (acc_low, acc_high))); + emit_insn (gen_mvfachi_A1 (gen_rtx_REG (SImode, acc_low), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_mvfacgu_A1 (gen_rtx_REG (SImode, acc_high), gen_rtx_CONST_INT(SImode, 0))); + emit_insn (gen_stack_pushm (GEN_INT (2 * UNITS_PER_WORD), + gen_rx_store_vector (acc_low, acc_high))); + + increase_stack_usage_info(3*2*UNITS_PER_WORD); + } + else + { + 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))); + + increase_stack_usage_info(2*UNITS_PER_WORD); + } } } @@ -1921,6 +2231,10 @@ rx_output_function_prologue (FILE * file) if (is_naked_func (NULL_TREE)) asm_fprintf (file, "\t; Note: Naked Function\n"); + if (is_interrupt_bank_func (NULL_TREE)) + asm_fprintf (file, "\t; Note: Interrupt Bank Function\n"); + + if (cfun->static_chain_decl != NULL) asm_fprintf (file, "\t; Note: Nested function declared " "inside another function.\n"); @@ -1940,7 +2254,7 @@ rx_emit_stack_popm (rtx * operands, bool is_popm) gcc_assert (CONST_INT_P (operands[0])); stack_adjust = INTVAL (operands[0]); - + gcc_assert (GET_CODE (operands[1]) == PARALLEL); last_reg = XVECLEN (operands[1], 0) - (is_popm ? 2 : 3); @@ -1949,7 +2263,15 @@ rx_emit_stack_popm (rtx * operands, bool is_popm) first_push = SET_DEST (first_push); gcc_assert (REG_P (first_push)); - if (is_popm) + if(REGNO(first_push) >= FIRST_DOUBLE_REG) + { + gcc_assert(flag_dfpu); + + asm_fprintf (asm_out_file, "\tdpopm.d\t%s-%s\n", + reg_names [REGNO (first_push) & (~1)], + reg_names [(REGNO (first_push) + last_reg) & (~1)]); + } + else if (is_popm) asm_fprintf (asm_out_file, "\tpopm\t%s-%s\n", reg_names [REGNO (first_push)], reg_names [REGNO (first_push) + last_reg]); @@ -1988,13 +2310,13 @@ gen_rx_rtsd_vector (unsigned int adjust, unsigned int low, unsigned int high) return vector; } - + /* Generate a PARALLEL which will satisfy the rx_load_multiple_vector predicate. */ static rtx gen_rx_popm_vector (unsigned int low, unsigned int high) { - unsigned int i; + unsigned int i; unsigned int count = (high - low) + 2; rtx vector; @@ -2023,21 +2345,24 @@ rx_can_use_simple_return (void) { unsigned int low; unsigned int high; + unsigned int dr_low; + unsigned int dr_high; unsigned int frame_size; unsigned int stack_size; unsigned int register_mask; if (is_naked_func (NULL_TREE) || is_fast_interrupt_func (NULL_TREE) - || is_interrupt_func (NULL_TREE)) + || is_interrupt_func (NULL_TREE) + || is_interrupt_bank_func (NULL_TREE)) return false; - rx_get_stack_layout (& low, & high, & register_mask, + rx_get_stack_layout (& low, & high, & dr_low, & dr_high, & register_mask, & frame_size, & stack_size); return (register_mask == 0 && (frame_size + stack_size) == 0 - && low == 0); + && low == 0 && dr_low == 0); } static void @@ -2058,12 +2383,15 @@ rx_expand_epilogue (bool is_sibcall) { unsigned int low; unsigned int high; + unsigned int dr_low; + unsigned int dr_high; unsigned int frame_size; unsigned int stack_size; unsigned int register_mask; unsigned int regs_size; unsigned int reg; unsigned HOST_WIDE_INT total_size; + tree inter_bank_attr = lookup_attribute ("interrupt_bank", DECL_ATTRIBUTES (current_function_decl)); /* FIXME: We do not support indirect sibcalls at the moment becaause we cannot guarantee that the register holding the function address is a @@ -2091,9 +2419,26 @@ rx_expand_epilogue (bool is_sibcall) emit_jump_insn (gen_naked_return ()); return; } - - rx_get_stack_layout (& low, & high, & register_mask, + rx_get_stack_layout (& low, & high, & dr_low, & dr_high, & register_mask, & frame_size, & stack_size); + if (inter_bank_attr && TARGET_RXV3) + { + int num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (inter_bank_attr))); + emit_insn (gen_rstr (GEN_INT (num))); + low = 0; + high = 0; + dr_low = 0; + dr_high = 0; + register_mask = 0; + } + if (is_interrupt_func (NULL_TREE) && (rx_tfu_version == RX_TFUV2) && !TARGET_NO_SAVE_TFU) + { + if(low == 0) + low = 1; + for(unsigned int reg = low ; reg<=high ; ++reg) + register_mask |= 1 << reg; + register_mask |= 0xe; + } total_size = frame_size + stack_size; regs_size = ((high - low) + 1) * UNITS_PER_WORD; @@ -2114,6 +2459,7 @@ rx_expand_epilogue (bool is_sibcall) if (is_sibcall || is_fast_interrupt_func (NULL_TREE) || is_interrupt_func (NULL_TREE) + || is_interrupt_bank_func (NULL_TREE) || register_mask) { /* Cannot use the special instructions - deconstruct by hand. */ @@ -2132,7 +2478,7 @@ rx_expand_epilogue (bool is_sibcall) { acc_low = acc_high = 0; - for (reg = 1; reg < CC_REGNUM; reg ++) + for (reg = 1; reg < FIRST_DOUBLE_REG; reg ++) if (register_mask & (1 << reg)) { if (acc_low == 0) @@ -2143,27 +2489,96 @@ rx_expand_epilogue (bool is_sibcall) break; } } - emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high))); - emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low))); + if(TARGET_RXV2) + { + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtachi_A1 (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtacgu_A1 (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtacgu_A0 (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtaclo_A1 (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high))); + } + else + { + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, acc_low))); + 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))); + } } 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))); + if(TARGET_RXV2) + { + /* TODO: do this better */ + emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD), + gen_rx_popm_vector (acc_low, acc_high))); + emit_insn (gen_mvtachi_A1 (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtacgu_A1 (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD), + gen_rx_popm_vector (acc_low, acc_high))); + emit_insn (gen_mvtacgu_A0 (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtaclo_A1 (gen_rtx_REG (SImode, acc_high))); + emit_insn (gen_stack_popm (GEN_INT (2 * UNITS_PER_WORD), + gen_rx_popm_vector (acc_low, acc_high))); + emit_insn (gen_mvtaclo (gen_rtx_REG (SImode, acc_low))); + emit_insn (gen_mvtachi (gen_rtx_REG (SImode, acc_high))); + } + else + { + 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))); + } } - 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) + if(dr_low != 0) { - for (reg = 0; reg < CC_REGNUM; reg ++) + if (flag_dfpu && TARGET_RXV3) + { + emit_insn(gen_stack_dpopm()); + } + emit_insn(gen_stack_popm(GEN_INT(((dr_high - dr_low) + 1) * UNITS_PER_WORD), gen_rx_popm_vector(dr_low, dr_high))); + } + if (is_interrupt_func (NULL_TREE) && (rx_tfu_version == RX_TFUV2) && !TARGET_NO_SAVE_TFU) + { + if(optimize_size) + { + pop_regs(3, 1); + emit_insn(gen_movsi(gen_rtx_MEM (SImode, gen_rtx_REG (SImode, 1)), gen_rtx_REG(SImode, 2))); + rtx addrs = gen_rtx_PLUS(SImode, gen_rtx_REG (SImode, 1), gen_rtx_CONST_INT (SImode, 4)); + emit_insn(gen_movsi(gen_rtx_MEM(SImode, addrs), gen_rtx_REG (SImode, 3))); + } + else + { + pop_regs(3, 3); + pop_regs(2, 2); + emit_insn(gen_movsi(gen_rtx_REG (SImode, 1), gen_rtx_CONST_INT (SImode, 0x81430))); + emit_insn(gen_movsi(gen_rtx_MEM (SImode, gen_rtx_REG (SImode, 1)), gen_rtx_REG(SImode, 2))); + rtx addrs = gen_rtx_PLUS(SImode, gen_rtx_REG (SImode, 1), gen_rtx_CONST_INT (SImode, 4)); + emit_insn(gen_movsi(gen_rtx_MEM(SImode, addrs), gen_rtx_REG (SImode, 3))); + } + } + if (register_mask) + { + for (reg = 0; reg < FIRST_DOUBLE_REG; reg ++) if (register_mask & (1 << reg)) { low = high = reg; @@ -2175,13 +2590,12 @@ rx_expand_epilogue (bool is_sibcall) } else if (low) pop_regs (high, low); - if (is_fast_interrupt_func (NULL_TREE)) { gcc_assert (! is_sibcall); emit_jump_insn (gen_fast_interrupt_return ()); } - else if (is_interrupt_func (NULL_TREE)) + else if (is_interrupt_func (NULL_TREE) || is_interrupt_bank_func (NULL_TREE)) { gcc_assert (! is_sibcall); emit_jump_insn (gen_exception_return ()); @@ -2192,6 +2606,30 @@ rx_expand_epilogue (bool is_sibcall) return; } + /* if we need to pop any DFPU regs we cannot use rtsd */ + if(dr_low != 0) + { + if (total_size) + { + gen_safe_add (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (total_size), false); + } + + if(flag_dfpu && TARGET_RXV3) + { + emit_insn(gen_stack_dpopm()); + } + + emit_insn(gen_stack_popm(GEN_INT(((dr_high - dr_low) + 1) * UNITS_PER_WORD), gen_rx_popm_vector(dr_low, dr_high))); + + if (low) + pop_regs (high, low); + + emit_jump_insn (gen_simple_return ()); + + return; + } + /* If we allocated space on the stack, free it now. */ if (total_size) { @@ -2234,11 +2672,13 @@ rx_initial_elimination_offset (int from, int to) { unsigned int low; unsigned int high; + unsigned int dr_low; + unsigned int dr_high; unsigned int frame_size; unsigned int stack_size; unsigned int mask; - rx_get_stack_layout (& low, & high, & mask, & frame_size, & stack_size); + rx_get_stack_layout (& low, & high, & dr_low, & dr_high, & mask, & frame_size, & stack_size); if (from == ARG_POINTER_REGNUM) { @@ -2249,6 +2689,11 @@ rx_initial_elimination_offset (int from, int to) else frame_size += bit_count (mask) * UNITS_PER_WORD; + if(dr_low) { + frame_size += ((dr_high - dr_low) + 1) * UNITS_PER_WORD; + if(flag_dfpu && TARGET_RXV3) + frame_size += 1 * UNITS_PER_WORD; + } /* Remember to include the return address. */ frame_size += 1 * UNITS_PER_WORD; @@ -2371,9 +2816,88 @@ enum rx_builtin RX_BUILTIN_RACW, RX_BUILTIN_REVW, RX_BUILTIN_RMPA, + RX_BUILTIN_RMPA8, + RX_BUILTIN_RMPA16, + RX_BUILTIN_RMPA32, RX_BUILTIN_ROUND, + RX_BUILTIN_DROUND, RX_BUILTIN_SETPSW, RX_BUILTIN_WAIT, + RX_BUILTIN_BSET, + RX_BUILTIN_BCLR, + RX_BUILTIN_BNOT, + RX_BUILTIN_BSET_MEM, + RX_BUILTIN_BCLR_MEM, + RX_BUILTIN_BNOT_MEM, + RX_BUILTIN_XCHG, + /* RXv2 builtins */ + RX_BUILTIN_EMULA_A0, + RX_BUILTIN_EMULA_A1, + RX_BUILTIN_EMACA_A0, + RX_BUILTIN_EMACA_A1, + RX_BUILTIN_EMSBA_A0, + RX_BUILTIN_EMSBA_A1, + RX_BUILTIN_MULLH_A0, + RX_BUILTIN_MULLH_A1, + /* no need for RX_BUILTIN_MULHI_A0, */ + RX_BUILTIN_MULHI_A1, + /* no need for RX_BUILTIN_MULLO_A0, */ + RX_BUILTIN_MULLO_A1, + RX_BUILTIN_MACLH_A0, + RX_BUILTIN_MACLH_A1, + RX_BUILTIN_MACHI_A0, + RX_BUILTIN_MACHI_A1, + RX_BUILTIN_MACLO_A0, + RX_BUILTIN_MACLO_A1, + RX_BUILTIN_MSBLH_A0, + RX_BUILTIN_MSBLH_A1, + RX_BUILTIN_MSBHI_A0, + RX_BUILTIN_MSBHI_A1, + RX_BUILTIN_MSBLO_A0, + RX_BUILTIN_MSBLO_A1, + RX_BUILTIN_RDACW_A0, + RX_BUILTIN_RDACW_A1, + RX_BUILTIN_RDACL_A0, + RX_BUILTIN_RDACL_A1, + /* no need for RX_BUILTIN_RACW_A0, */ + RX_BUILTIN_RACW_A1, + RX_BUILTIN_RACL_A0, + RX_BUILTIN_RACL_A1, + RX_BUILTIN_MVFACHI_A0, + RX_BUILTIN_MVFACHI_A1, + RX_BUILTIN_MVFACMI_A0, + RX_BUILTIN_MVFACMI_A1, + RX_BUILTIN_MVFACLO_A0, + RX_BUILTIN_MVFACLO_A1, + RX_BUILTIN_MVFACGU_A0, + RX_BUILTIN_MVFACGU_A1, + /* no need for RX_BUILTIN_MVTACHI_A0, */ + RX_BUILTIN_MVTACHI_A1, + /* no need for RX_BUILTIN_MVTACLO_A0, */ + RX_BUILTIN_MVTACLO_A1, + RX_BUILTIN_MVTACGU_A0, + RX_BUILTIN_MVTACGU_A1, + /* RXv3 builtins */ + RX_BUILTIN_SAVE, + RX_BUILTIN_RSTR, + RX_BUILTIN_MVFDC, + RX_BUILTIN_MVTDC, + RX_BUILTIN_MVFDR, + RX_BUILTIN_BFMOV, + RX_BUILTIN_BFMOVZ, + RX_TFU_INIT, + RX_BUILTIN_SINCOSF, + RX_BUILTIN_SINCOSFX, + RX_BUILTIN_ATAN2HYPOTF, + RX_BUILTIN_ATAN2HYPOTFX, + RX_BUILTIN_SINF, + RX_BUILTIN_SINFX, + RX_BUILTIN_COSF, + RX_BUILTIN_COSFX, + RX_BUILTIN_ATAN2F, + RX_BUILTIN_ATAN2FX, + RX_BUILTIN_HYPOTF, + RX_BUILTIN_HYPOTFX, RX_BUILTIN_max }; @@ -2420,26 +2944,166 @@ rx_init_builtins (void) RX_BUILTIN_##UC_NAME, \ BUILT_IN_MD, NULL, NULL_TREE) - ADD_RX_BUILTIN0 (BRK, "brk", void); - ADD_RX_BUILTIN1 (CLRPSW, "clrpsw", void, integer); - ADD_RX_BUILTIN1 (SETPSW, "setpsw", void, integer); - ADD_RX_BUILTIN1 (INT, "int", void, integer); - ADD_RX_BUILTIN2 (MACHI, "machi", void, intSI, intSI); - ADD_RX_BUILTIN2 (MACLO, "maclo", void, intSI, intSI); - ADD_RX_BUILTIN2 (MULHI, "mulhi", void, intSI, intSI); - ADD_RX_BUILTIN2 (MULLO, "mullo", void, intSI, intSI); - ADD_RX_BUILTIN0 (MVFACHI, "mvfachi", intSI); - ADD_RX_BUILTIN0 (MVFACMI, "mvfacmi", intSI); - ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void, intSI); - ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void, intSI); - ADD_RX_BUILTIN0 (RMPA, "rmpa", 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); - ADD_RX_BUILTIN0 (WAIT, "wait", void); +#define ADD_RX_BUILTIN4(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3,ARG_TYPE4) \ + rx_builtins[RX_BUILTIN_##UC_NAME] = \ + add_builtin_function ("__builtin_rx_" LC_NAME, \ + build_function_type_list (RET_TYPE##_type_node, \ + ARG_TYPE1##_type_node,\ + ARG_TYPE2##_type_node,\ + ARG_TYPE3##_type_node,\ + ARG_TYPE4##_type_node,\ + NULL_TREE), \ + RX_BUILTIN_##UC_NAME, \ + BUILT_IN_MD, NULL, NULL_TREE) + +#define ADD_RX_BUILTIN5(UC_NAME,LC_NAME,RET_TYPE,ARG_TYPE1,ARG_TYPE2,ARG_TYPE3,ARG_TYPE4,ARG_TYPE5) \ + rx_builtins[RX_BUILTIN_##UC_NAME] = \ + add_builtin_function ("__builtin_rx_" LC_NAME, \ + build_function_type_list (RET_TYPE##_type_node, \ + ARG_TYPE1##_type_node,\ + ARG_TYPE2##_type_node,\ + ARG_TYPE3##_type_node,\ + ARG_TYPE4##_type_node,\ + ARG_TYPE5##_type_node,\ + NULL_TREE), \ + RX_BUILTIN_##UC_NAME, \ + BUILT_IN_MD, NULL, NULL_TREE) + +#define ADD_RX_TFU_BUILTIN(UC_NAME, LC_NAME, RET_TYPE) \ + rx_builtins[RX_TFU_##UC_NAME] = \ + add_builtin_function (LC_NAME, \ + build_function_type_list (RET_TYPE##_type_node, \ + NULL_TREE), \ + RX_TFU_##UC_NAME, \ + BUILT_IN_MD, NULL, NULL_TREE) + + // now add missing pointer types + static tree char_ptr_type_node; + static tree int16_ptr_type_node; + static tree volatile_char_ptr_type_node; + + ADD_RX_BUILTIN0 (BRK, "brk", void); + ADD_RX_BUILTIN1 (CLRPSW, "clrpsw", void, integer); + ADD_RX_BUILTIN1 (SETPSW, "setpsw", void, integer); + ADD_RX_BUILTIN1 (INT, "int", void, integer); + ADD_RX_BUILTIN2 (MACHI, "machi", void, intSI, intSI); + ADD_RX_BUILTIN2 (MACLO, "maclo", void, intSI, intSI); + ADD_RX_BUILTIN2 (MULHI, "mulhi", void, intSI, intSI); + ADD_RX_BUILTIN2 (MULLO, "mullo", void, intSI, intSI); + ADD_RX_BUILTIN0 (MVFACHI, "mvfachi", intSI); + ADD_RX_BUILTIN0 (MVFACMI, "mvfacmi", intSI); + ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void, intSI); + ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void, intSI); + ADD_RX_BUILTIN0 (RMPA, "rmpa", void); + ADD_RX_BUILTIN4 (RMPA8, "rmpa8", intDI, intDI, char_ptr, char_ptr, unsigned_intSI); + ADD_RX_BUILTIN4 (RMPA16, "rmpa16", intDI, intDI, int16_ptr, int16_ptr, unsigned_intSI); + ADD_RX_BUILTIN4 (RMPA32, "rmpa32", intDI, intDI, integer_ptr, integer_ptr, unsigned_intSI); + 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); + ADD_RX_BUILTIN0 (WAIT, "wait", void); + ADD_RX_BUILTIN2 (BSET, "bset", intSI, intSI, intSI); + ADD_RX_BUILTIN2 (BCLR, "bclr", intSI, intSI, intSI); + ADD_RX_BUILTIN2 (BNOT, "bnot", intSI, intSI, intSI); + ADD_RX_BUILTIN2 (BSET_MEM, "bset_mem", void, volatile_char_ptr, intQI); + ADD_RX_BUILTIN2 (BCLR_MEM, "bclr_mem", void, volatile_char_ptr, intQI); + ADD_RX_BUILTIN2 (BNOT_MEM, "bnot_mem", void, volatile_char_ptr, intQI); + ADD_RX_BUILTIN2 (XCHG, "xchg", void, integer_ptr, integer_ptr); + if(TARGET_RXV2) + { + ADD_RX_BUILTIN2 (EMULA_A0, "emula_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (EMULA_A1, "emula_A1", void, intSI, intSI); + ADD_RX_BUILTIN2 (EMACA_A0, "emaca_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (EMACA_A1, "emaca_A1", void, intSI, intSI); + ADD_RX_BUILTIN2 (EMSBA_A0, "emsba_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (EMSBA_A1, "emsba_A1", void, intSI, intSI); + ADD_RX_BUILTIN2 (MULLH_A0, "mullh_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (MULLH_A1, "mullh_A1", void, intSI, intSI); + /* mulhi_A0 is not present we have mulhi from RXV1 */ + ADD_RX_BUILTIN2 (MULHI_A1, "mulhi_A1", void, intSI, intSI); + /* mullo_A0 is not present we have mullo from RXV1 */ + ADD_RX_BUILTIN2 (MULLO_A1, "mullo_A1", void, intSI, intSI); + ADD_RX_BUILTIN2 (MACLH_A0, "maclh_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (MACLH_A1, "maclh_A1", void, intSI, intSI); + /* machi_A0 is not present we have machi from RXV1 */ + ADD_RX_BUILTIN2 (MACHI_A1, "machi_A1", void, intSI, intSI); + /* maclo_A0 is not present we have maclo from RXV1 */ + ADD_RX_BUILTIN2 (MACLO_A1, "maclo_A1", void, intSI, intSI); + ADD_RX_BUILTIN2 (MSBLH_A0, "msblh_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (MSBLH_A1, "msblh_A1", void, intSI, intSI); + ADD_RX_BUILTIN2 (MSBHI_A0, "msbhi_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (MSBHI_A1, "msbhi_A1", void, intSI, intSI); + ADD_RX_BUILTIN2 (MSBLO_A0, "msblo_A0", void, intSI, intSI); + ADD_RX_BUILTIN2 (MSBLO_A1, "msblo_A1", void, intSI, intSI); + ADD_RX_BUILTIN1 (RDACW_A0, "rdacw_A0", void, integer); + ADD_RX_BUILTIN1 (RDACW_A1, "rdacw_A1", void, integer); + ADD_RX_BUILTIN1 (RDACL_A0, "rdacl_A0", void, integer); + ADD_RX_BUILTIN1 (RDACL_A1, "rdacl_A1", void, integer); + /* racw_A0 is not present we have racw from RXV1 */ + ADD_RX_BUILTIN1 (RACW_A1, "racw_A1", void, integer); + ADD_RX_BUILTIN1 (RACL_A0, "racl_A0", void, integer); + ADD_RX_BUILTIN1 (RACL_A1, "racl_A1", void, integer); + ADD_RX_BUILTIN1 (MVFACHI_A0, "mvfachi_A0", intSI, integer); + ADD_RX_BUILTIN1 (MVFACHI_A1, "mvfachi_A1", intSI, integer); + ADD_RX_BUILTIN1 (MVFACMI_A0, "mvfacmi_A0", intSI, integer); + ADD_RX_BUILTIN1 (MVFACMI_A1, "mvfacmi_A1", intSI, integer); + ADD_RX_BUILTIN1 (MVFACLO_A0, "mvfaclo_A0", intSI, integer); + ADD_RX_BUILTIN1 (MVFACLO_A1, "mvfaclo_A1", intSI, integer); + ADD_RX_BUILTIN1 (MVFACGU_A0, "mvfacgu_A0", intSI, integer); + ADD_RX_BUILTIN1 (MVFACGU_A1, "mvfacgu_A1", intSI, integer); + /* no need for RX_BUILTIN_MVFACHI_A0: */ + /*ADD_RX_BUILTIN1 (MVFACHI_A1, "mvfachi_A1", intSI, void);*/ + /* no need for RX_BUILTIN_MVFACMI_A0: */ + /*ADD_RX_BUILTIN1 (MVFACMI_A1, "mvfacmi_A1", intSI, void); + ADD_RX_BUILTIN1 (MVFACLO_A0, "mvfaclo_A0", intSI, void); + ADD_RX_BUILTIN1 (MVFACLO_A1, "mvfaclo_A1", intSI, void); + ADD_RX_BUILTIN1 (MVFACGU_A0, "mvfacgu_A0", intSI, void); + ADD_RX_BUILTIN1 (MVFACGU_A1, "mvfacgu_A1", intSI, void);*/ + /* no need for RX_BUILTIN_MVTACHI_A0: */ + ADD_RX_BUILTIN1 (MVTACHI_A1, "mvtachi_A1", void, intSI); + /* no need for RX_BUILTIN_MVTACLO_A0: */ + ADD_RX_BUILTIN1 (MVTACLO_A1, "mvtaclo_A1", void, intSI); + ADD_RX_BUILTIN1 (MVTACGU_A0, "mvtacgu_A0", void, intSI); + ADD_RX_BUILTIN1 (MVTACGU_A1, "mvtacgu_A1", void, intSI); + } + if (TARGET_RXV3) + { + ADD_RX_BUILTIN1 (SAVE, "save", void, integer); + ADD_RX_BUILTIN1 (RSTR, "rstr", void, integer); + ADD_RX_BUILTIN4 (BFMOVZ, "bfmovz", intSI, intSI, intSI, intSI, intSI); + ADD_RX_BUILTIN5 (BFMOV, "bfmov", intSI, intSI, intSI, intSI, intSI, intSI); + if (flag_dfpu) + { + ADD_RX_BUILTIN0 (MVFDR, "mvfdr", void); + ADD_RX_BUILTIN1 (MVFDC, "mvfdc", intSI, intSI); + ADD_RX_BUILTIN2 (MVTDC, "mvtdc", void, intSI, intSI); + ADD_RX_BUILTIN1 (DROUND, "dround", intSI, double); + } + } + /* TFU builtins defs depend only on -mtfu and -mtfu-version, not on -misa */ + if (TARGET_TFU) + { + if (rx_tfu_version == RX_TFUV1) /* this is available only for TFU v1 */ + ADD_RX_TFU_BUILTIN(INIT, "__init_tfu", void); + ADD_RX_BUILTIN3(SINCOSF, "sincosf", void, float, float_ptr, float_ptr); + ADD_RX_BUILTIN4(ATAN2HYPOTF, "atan2hypotf", void, float, float, float_ptr, float_ptr); + ADD_RX_BUILTIN1(SINF, "sinf", float, float); + ADD_RX_BUILTIN1(COSF, "cosf", float, float); + ADD_RX_BUILTIN2(ATAN2F, "atan2f", float, float, float); + ADD_RX_BUILTIN2(HYPOTF, "hypotf", float, float, float); + if (rx_tfu_version == RX_TFUV2) + { + ADD_RX_BUILTIN3(SINCOSFX, "sincosfx", void, intSI, integer_ptr, integer_ptr); + ADD_RX_BUILTIN4(ATAN2HYPOTFX, "atan2hypotfx", void, intSI, intSI, integer_ptr, integer_ptr); + ADD_RX_BUILTIN1(SINFX, "sinfx", intSI, intSI); + ADD_RX_BUILTIN1(COSFX, "cosfx", intSI, intSI); + ADD_RX_BUILTIN2(ATAN2FX, "atan2fx", intSI, intSI, intSI); + ADD_RX_BUILTIN2(HYPOTFX, "hypotfx", intSI, intSI, intSI); + } + } } /* Return the RX builtin for CODE. */ @@ -2464,6 +3128,50 @@ rx_expand_void_builtin_1_arg (rtx arg, rtx (* gen_func)(rtx), bool reg) return NULL_RTX; } +static rtx +rx_expand_void_builtin_1_int_arg (rtx arg, rtx (* gen_func)(rtx)) +{ + if (CONST_INT_P (arg)) + emit_insn (gen_func (arg)); + else + error ("__builtin_int only takes a numerical argument"); + + return NULL_RTX; +} + +static rtx +rx_expand_builtin_mvfdc (tree exp, rtx target) +{ + rtx arg = expand_normal (CALL_EXPR_ARG (exp, 0)); + + if (! CONST_INT_P (arg)) + error ("__builtin_mvfdc only takes a numerical argument as first parameter"); + + if (target == NULL_RTX || ! REG_P (target)) + target = gen_reg_rtx (SImode); + + emit_insn (gen_mvfdc (target, arg)); + + return target; +} + +static rtx +rx_expand_builtin_mvtdc (tree exp) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + if (! CONST_INT_P (arg1)) + error ("__builtin_mvtdc only takes a numerical argument as first parameter"); + + if (! REG_P (arg2)) + arg2 = force_reg (SImode, arg2); + + emit_insn (gen_mvtdc (arg1, arg2)); + + return NULL_RTX; +} + static rtx rx_expand_builtin_mvtc (tree exp) { @@ -2476,7 +3184,7 @@ rx_expand_builtin_mvtc (tree exp) if (! REG_P (arg2)) arg2 = force_reg (SImode, arg2); - if (INTVAL (arg1) == 1) + if (INTVAL (arg1) == 1/*PC*/) { warning (0, "invalid control register %d for mvtc; using %", (int) INTVAL (arg1)); @@ -2488,6 +3196,60 @@ rx_expand_builtin_mvtc (tree exp) return NULL_RTX; } +static rtx +rx_expand_builtin_rmpa (tree exp, rtx target, enum machine_mode mode) +{ + rtx arg0 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 1)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 2)); + rtx arg3 = expand_normal (CALL_EXPR_ARG (exp, 3)); + + rtx reg1 = gen_rtx_REG (SImode, 1); + rtx reg2 = gen_rtx_REG (SImode, 2); + rtx reg3 = gen_rtx_REG (SImode, 3); + rtx reg4 = gen_rtx_REG (DImode, 4); + rtx reg5 = gen_rtx_REG (SImode, 6); + + //emit_insn (gen_stack_push (reg5)); + emit_move_insn(reg1, arg1); + emit_move_insn(reg2, arg2); + emit_move_insn(reg3, arg3); + emit_move_insn(reg4, arg0); + + if (REG_P (arg1)) + emit_use (reg1); + if (REG_P (arg2)) + emit_use (reg2); + if (REG_P (arg3)) + emit_use (reg3); + + if (CONST_INT_P (arg0)) + { + rtx flag; + if (INTVAL (arg0) & 0x80000000) + flag = gen_rtx_CONST_INT (SImode, -1); + else + flag = gen_rtx_CONST_INT (SImode, 0); + emit_move_insn (reg5, flag); + } + else + { + emit_insn (gen_ashrsi3 (reg5, gen_highpart(SImode, reg4), gen_rtx_CONST_INT (SImode, 31))); + } + target = reg4; + + if (mode == QImode) + emit_insn(gen_rmpa8 (reg1, reg2, reg3, target, reg5)); + else if(mode == HImode) + emit_insn(gen_rmpa16 (reg1, reg2, reg3, target, reg5)); + else + emit_insn(gen_rmpa32 (reg1, reg2, reg3, target, reg5)); + + //emit_insn (gen_stack_pop (reg5)); + + return target; +} + static rtx rx_expand_builtin_mvfc (tree t_arg, rtx target) { @@ -2512,101 +3274,854 @@ rx_expand_builtin_mvtipl (rtx arg) { /* The RX610 does not support the MVTIPL instruction. */ if (rx_cpu_type == RX610) + { + warning(0, "The RX610 does not support the MVTIPL instruction."); return NULL_RTX; + } - if (! CONST_INT_P (arg) || ! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1)) + if (! CONST_INT_P (arg)) + { + warning(0, "Invalid operand format, src must be an immediate value."); + return NULL_RTX; + } + + if (! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1)) + { + warning(0, "The value of src must be an unsigned integer in the range of [0, 15]."); return NULL_RTX; + } emit_insn (gen_mvtipl (arg)); return NULL_RTX; } +static rtx +rx_expand_builtin_xchg (tree exp) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + /* if arg2 is a reg than we can safely use the form xchg [Rs].memex, Rd, othewise only xchg Rs, Rd */ + if(REG_P(arg2)) + { + rtx mem1 = gen_rtx_MEM (SImode, arg1); + rtx mem2 = gen_rtx_MEM (SImode, arg2); + + rtx mem1toreg = copy_to_reg(mem1); + + MEM_VOLATILE_P (mem1) = 1; + MEM_VOLATILE_P (mem2) = 1; + + emit_insn (gen_exchangesi (mem1toreg, mem2)); + emit_move_insn(mem1, mem1toreg); + } + else if (GET_CODE (arg2) == SYMBOL_REF) + { + rtx mem1 = gen_rtx_MEM (SImode, arg1); + rtx mem2 = gen_rtx_MEM (SImode, force_reg (SImode, arg2)); + + rtx mem1toreg = copy_to_reg(mem1); + + MEM_VOLATILE_P (mem1) = 1; + MEM_VOLATILE_P (mem2) = 1; + + emit_insn (gen_exchangesi (mem1toreg, mem2)); + emit_move_insn(mem1, mem1toreg); + } + else + { + rtx mem1 = gen_rtx_MEM (SImode, arg1); + rtx mem2 = gen_rtx_MEM (SImode, arg2); + + rtx mem1toreg = copy_to_reg(mem1); + rtx mem2toreg = copy_to_reg(mem2); + + MEM_VOLATILE_P (mem1) = 1; + MEM_VOLATILE_P (mem2) = 1; + + emit_insn (gen_exchangesi (mem1toreg, mem2toreg)); + emit_move_insn(mem1, mem1toreg); + emit_move_insn(mem2, mem2toreg); + } + + 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)); rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); - if (! REG_P (arg1)) + if (! REG_P (arg1)) + arg1 = force_reg (SImode, arg1); + + if (! REG_P (arg2)) + arg2 = force_reg (SImode, arg2); + + emit_insn (gen_func (arg1, arg2)); + + return NULL_RTX; +} + +static rtx +rx_expand_int_builtin_1_arg (rtx arg, + rtx target, + rtx (* gen_func)(rtx, rtx), + bool mem_ok, bool reg) +{ + if (reg && (! REG_P (arg))) + if (!mem_ok || ! MEM_P (arg)) + arg = force_reg (SImode, arg); + + if (target == NULL_RTX || ! REG_P (target)) + target = gen_reg_rtx (SImode); + + emit_insn (gen_func (target, arg)); + + return target; +} + +static rtx +rx_expand_int_builtin_0_arg (rtx target, rtx (* gen_func)(rtx)) +{ + if (target == NULL_RTX || ! REG_P (target)) + target = gen_reg_rtx (SImode); + + emit_insn (gen_func (target)); + + return target; +} + +static rtx +rx_expand_builtin_round (rtx arg, rtx target) +{ + if ((! REG_P (arg) && ! MEM_P (arg)) + || GET_MODE (arg) != SFmode) + arg = force_reg (SFmode, arg); + + if (target == NULL_RTX || ! REG_P (target)) + target = gen_reg_rtx (SImode); + + emit_insn (gen_lrintsf2 (target, arg)); + + return target; +} + +static rtx +rx_expand_builtin_dround (rtx arg, rtx target) +{ + if ((!REG_P (arg)) || (GET_MODE (arg) != DFmode)) + arg = force_reg (DFmode, arg); + + if ((target == NULL_RTX) || (!REG_P (target))) + target = gen_reg_rtx (SImode); + + emit_insn (gen_lrintdf2 (target, arg)); + + return target; +} + +static rtx +rx_expand_builtin_bit_manip(tree exp, rtx target, rtx (* gen_func)(rtx, rtx, rtx)) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + if (! REG_P (arg1)) + arg1 = force_reg (SImode, arg1); + + if (! REG_P (arg2)) + arg2 = force_reg (SImode, arg2); + + if (target == NULL_RTX || ! REG_P (target)) + target = gen_reg_rtx (SImode); + + emit_insn(gen_func(target, arg2, arg1)); + + return target; +} + +static rtx +rx_expand_builtin_bit_manip_mem(tree exp,rtx (* gen_func)(rtx, rtx)) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + rtx cptoreg = arg2; + if (! REG_P(arg1)) + { + arg1=force_reg(SImode,arg1); + } + + arg1=gen_rtx_MEM(QImode,arg1); + MEM_VOLATILE_P (arg1) = 1; + + if (MEM_P(arg2)) + { + cptoreg=copy_to_reg(arg2); + } + + emit_insn(gen_func(arg1,cptoreg)); + + return NULL_RTX; +} + +static int +valid_psw_flag (rtx op, const char *which) +{ + static int mvtc_inform_done = 0; + + if (GET_CODE (op) == CONST_INT) + switch (INTVAL (op)) + { + case 0: case 'c': case 'C': + case 1: case 'z': case 'Z': + case 2: case 's': case 'S': + case 3: case 'o': case 'O': + case 8: case 'i': case 'I': + case 9: case 'u': case 'U': + return 1; + } + + error ("%<__builtin_rx_%s%> takes %, %, %, %, %, " + "or %", which); + if (!mvtc_inform_done) + error ("use %<__builtin_rx_mvtc (0, ... )%> to write arbitrary values to PSW"); + mvtc_inform_done = 1; + + return 0; +} + +static rtx +rx_expand_builtin_bitfield_2(tree exp, rtx target) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + rtx arg3 = expand_normal (CALL_EXPR_ARG (exp, 2)); + rtx arg4 = expand_normal (CALL_EXPR_ARG (exp, 3)); + rtx arg5 = expand_normal (CALL_EXPR_ARG (exp, 4)); + + if (!CONST_INT_P (arg3) || !IN_RANGE (INTVAL (arg3), 0, 31)) + error ("slsb can only be a numerical argument in interval [0,31]"); + + if (!CONST_INT_P (arg4) || !IN_RANGE (INTVAL (arg4), 0, 31)) + error ("dlsb can only be a numerical argument in interval [0,31]"); + + if (!CONST_INT_P (arg5) || !IN_RANGE (INTVAL (arg5), 1, 31)) + error ("width can only be a numerical argument in interval [1,31]"); + + if (! REG_P (arg1)) + arg1 = force_reg (SImode, arg1); + if (! REG_P (arg2)) + arg2 = force_reg (SImode, arg2); + target = arg1; + emit_insn (gen_bfmov(target, arg2, arg3, arg4, arg5)); + + return target; +} + +static rtx +rx_expand_builtin_bitfield(tree exp, rtx target) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + rtx arg3 = expand_normal (CALL_EXPR_ARG (exp, 2)); + rtx arg4 = expand_normal (CALL_EXPR_ARG (exp, 3)); + + if (target == NULL_RTX || ! REG_P (target)) + target = gen_reg_rtx (SImode); + if (!CONST_INT_P (arg2) || !IN_RANGE (INTVAL (arg2), 0, 31)) + error ("slsb can only be a numerical argument in interval [0,31]"); + + if (!CONST_INT_P (arg3) || !IN_RANGE (INTVAL (arg3), 0, 31)) + error ("dlsb can only be a numerical argument in interval [0,31]"); + + if (!CONST_INT_P (arg4) || !IN_RANGE (INTVAL (arg4), 1, 31)) + error ("width can only be a numerical argument in interval [1,31]"); + + if (! REG_P (arg1)) + arg1 = force_reg (SImode, arg1); + + emit_insn (gen_bfmovz(target, arg1, arg2, arg3, arg4)); + + return target; +} + +static rtx +rx_expand_tfu_sincosf (tree exp) +{ + rtx arg = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx xsin = expand_normal (CALL_EXPR_ARG (exp, 1)); + rtx xcos = expand_normal (CALL_EXPR_ARG (exp, 2)); + + if (!REG_P (arg)) + arg = force_reg (SFmode, arg); + + if (!REG_P (xsin)) + xsin = force_reg (SImode, xsin); + + if (!REG_P (xcos)) + xcos = force_reg (SImode, xcos); + + if (!MEM_P (xsin)) + xsin = gen_rtx_MEM (SImode, xsin); + MEM_VOLATILE_P (xsin) = 1; + + if (!MEM_P (xcos)) + xcos = gen_rtx_MEM (SImode, xcos); + MEM_VOLATILE_P (xcos) = 1; + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081410); + rtx emit = gen_reg_rtx (SImode); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + rtx memit; + + emit_move_insn (emit, addr); + memit = gen_rtx_MEM (SFmode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit) = 1; + emit_move_insn (memit, arg); + memit = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit) = 1; + emit_move_insn (xsin, memit); + memit = gen_rtx_MEM (SImode, emit); + MEM_VOLATILE_P (memit) = 1; + emit_move_insn (xcos, memit); + + return NULL_RTX; +} +static rtx +rx_expand_tfu_sincosfx (tree exp) +{ + rtx arg = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx xsin = expand_normal (CALL_EXPR_ARG (exp, 1)); + rtx xcos = expand_normal (CALL_EXPR_ARG (exp, 2)); + + if (!REG_P (arg)) + arg = force_reg (SImode, arg); + + if (!REG_P (xsin)) + xsin = force_reg (SImode, xsin); + + if (!REG_P (xcos)) + xcos = force_reg (SImode, xcos); + + if (!MEM_P (xsin)) + xsin = gen_rtx_MEM (SImode, xsin); + MEM_VOLATILE_P (xsin) = 1; + + if (!MEM_P (xcos)) + xcos = gen_rtx_MEM (SImode, xcos); + MEM_VOLATILE_P (xcos) = 1; + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081420); + rtx emit = gen_reg_rtx (SImode); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + rtx memit; + + emit_move_insn (emit, addr); + memit = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit) = 1; + emit_move_insn (memit, arg); + memit = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit) = 1; + emit_move_insn (xsin, memit); + memit = gen_rtx_MEM (SImode, emit); + MEM_VOLATILE_P (memit) = 1; + emit_move_insn (xcos, memit); + + return NULL_RTX; +} + +static rtx +rx_expand_tfu_atan2hypotf (tree exp) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + rtx xatan2 = expand_normal (CALL_EXPR_ARG (exp, 2)); + rtx xhypot = expand_normal (CALL_EXPR_ARG (exp, 3)); + + if (!REG_P (arg1)) + { + arg1 = force_reg (SFmode, arg1); + } + + if (!REG_P (arg2)) + { + arg2 = force_reg (SFmode, arg2); + } + + if (!REG_P (xatan2)) + { + xatan2 = force_reg (SImode, xatan2); + } + + if (!REG_P (xhypot)) + { + xhypot = force_reg (SImode, xhypot); + } + + if (GET_CODE (xhypot) == MEM) + { + if (GET_CODE (XEXP (xhypot, 0)) != PLUS) + { + xhypot = force_reg (SImode, xhypot); + } + } + + if (GET_CODE (xatan2) == MEM) + { + if (GET_CODE (XEXP (xatan2, 0)) != PLUS) + { + xatan2 = force_reg (SImode, xatan2); + } + } + + if (!MEM_P (xatan2)) + { + xatan2 = gen_rtx_MEM (SImode, xatan2); + } + MEM_VOLATILE_P (xatan2) = 1; + + if (!MEM_P (xhypot)) + { + xhypot = gen_rtx_MEM (SFmode, xhypot); + } + MEM_VOLATILE_P (xhypot) = 1; + + if (GET_MODE (xhypot) == SImode) + { + PUT_MODE (xhypot, SFmode); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081418); + rtx emit = gen_reg_rtx (SImode); + rtx valMul = gen_reg_rtx (SImode); + rtx valMul2 = gen_reg_rtx (SFmode); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + REAL_VALUE_TYPE r; + real_from_string (&r, "0.607252955437"); + rtx fmul = const_double_from_real_value (r, SFmode); + + rtx memit = gen_rtx_MEM (SFmode, emit); + rtx memit2; + MEM_VOLATILE_P (memit) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit, arg2); + memit2 = gen_rtx_MEM (SFmode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit2) = 1; + emit_move_insn (memit2, arg1); + + gen_movsi (valMul, gen_rtx_CONST_INT (SImode, 0)); + emit_move_insn (valMul2, memit); + + + memit2 = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit2) = 1; + emit_move_insn (xatan2, memit2); + emit_insn (gen_mulsf3 (valMul2, valMul2, fmul)); + emit_move_insn (xhypot, valMul2); + + return NULL_RTX; +} + +static rtx +rx_expand_tfu_atan2hypotfx (tree exp) +{ + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + rtx xatan2 = expand_normal (CALL_EXPR_ARG (exp, 2)); + rtx xhypot = expand_normal (CALL_EXPR_ARG (exp, 3)); + + if (!REG_P (arg1)) + { + arg1 = force_reg (SImode, arg1); + } + + if (!REG_P (arg2)) + { + arg2 = force_reg (SImode, arg2); + } + + if (!REG_P (xatan2)) + { + xatan2 = force_reg (SImode, xatan2); + } + + if (!REG_P (xhypot)) + { + xhypot = force_reg (SImode, xhypot); + } + + if (GET_CODE (xhypot) == MEM) + { + if (GET_CODE (XEXP (xhypot, 0)) != PLUS) + { + xhypot = force_reg (SImode, xhypot); + } + } + + if (GET_CODE (xatan2) == MEM) + { + if (GET_CODE (XEXP (xatan2, 0)) != PLUS) + { + xatan2 = force_reg (SImode, xatan2); + } + } + + if (!MEM_P (xatan2)) + { + xatan2 = gen_rtx_MEM (SImode, xatan2); + } + MEM_VOLATILE_P (xatan2) = 1; + + if (!MEM_P (xhypot)) + { + xhypot = gen_rtx_MEM (SImode, xhypot); + } + MEM_VOLATILE_P (xhypot) = 1; + + if (GET_MODE (xhypot) == SImode) + { + PUT_MODE (xhypot, SImode); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081428); + rtx emit = gen_reg_rtx (SImode); + rtx valMul = gen_reg_rtx (SImode); + rtx valMul2 = gen_reg_rtx (SImode); + rtx valMul3 = gen_reg_rtx (DImode); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + + rtx fmul = gen_rtx_CONST_INT (SImode, -1686835800); + rtx fmul2 = gen_reg_rtx (SImode); + + rtx memit = gen_rtx_MEM (SImode, emit); + rtx memit2; + MEM_VOLATILE_P (memit) = 1; + + emit_move_insn (emit, addr); + emit_move_insn(fmul2, fmul); + emit_move_insn (memit, arg2); + memit2 = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit2) = 1; + emit_move_insn (memit2, arg1); + + gen_movsi (valMul, gen_rtx_CONST_INT (SImode, 0)); + emit_move_insn (valMul2, memit); + + + memit2 = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit2) = 1; + emit_move_insn (xatan2, memit2); + emit_insn (gen_umulsidi3 (valMul3, valMul2, fmul2)); + emit_move_insn (xhypot, gen_rtx_SUBREG (SImode, valMul3, 4)); + + return NULL_RTX; +} + +static rtx +rx_expand_tfu_sinf (rtx op, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + if (!REG_P (op)) + { + op = force_reg (SFmode, op); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081414); + rtx emit = gen_reg_rtx (SImode); + rtx memit = gen_rtx_MEM (SFmode, emit); + + MEM_VOLATILE_P (memit) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit, op); + emit_move_insn (target, memit); + + return target; +} + +static rtx +rx_expand_tfu_sinfx (rtx op, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + if (!REG_P (op)) + { + op = force_reg (SImode, op); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081424); + rtx emit = gen_reg_rtx (SImode); + rtx memit = gen_rtx_MEM (SImode, emit); + + MEM_VOLATILE_P (memit) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit, op); + emit_move_insn (target, memit); + + return target; +} + + +static rtx +rx_expand_tfu_cosf (rtx op, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + if (!REG_P (op)) + { + op = force_reg (SFmode, op); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081410); + rtx emit = gen_reg_rtx (SImode); + rtx memit = gen_rtx_MEM (SFmode, emit); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + rtx memit2 = gen_rtx_MEM (SFmode, gen_rtx_PLUS(SImode, emit, inc)); + + MEM_VOLATILE_P (memit) = 1; + MEM_VOLATILE_P (memit2) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit2, op); + emit_move_insn (target, memit); + + return target; +} +static rtx +rx_expand_tfu_cosfx (rtx op, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + if (!REG_P (op)) + { + op = force_reg (SImode, op); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081420); + rtx emit = gen_reg_rtx (SImode); + rtx memit = gen_rtx_MEM (SImode, emit); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + rtx memit2 = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + + MEM_VOLATILE_P (memit) = 1; + MEM_VOLATILE_P (memit2) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit2, op); + emit_move_insn (target, memit); + + return target; +} +static rtx +rx_expand_tfu_atan2f (tree exp, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + if (!REG_P (arg1)) + { + arg1 = force_reg (SFmode, arg1); + } + + if (!REG_P (arg2)) + { + arg2 = force_reg (SFmode, arg2); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081418); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + + rtx emit = gen_reg_rtx (SImode); + rtx memit = gen_rtx_MEM (SFmode, emit); + rtx memit4 = gen_rtx_MEM (SFmode, gen_rtx_PLUS(SImode, emit, inc)); + + MEM_VOLATILE_P (memit) = 1; + MEM_VOLATILE_P (memit4) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit, arg2); + emit_move_insn (memit4, arg1); + emit_move_insn (target, memit4); + + return target; +} +static rtx +rx_expand_tfu_atan2fx (tree exp, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + if (!REG_P (arg1)) + { + arg1 = force_reg (SImode, arg1); + } + + if (!REG_P (arg2)) + { + arg2 = force_reg (SImode, arg2); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081428); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + + rtx emit = gen_reg_rtx (SImode); + rtx memit = gen_rtx_MEM (SImode, emit); + rtx memit4 = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + + MEM_VOLATILE_P (memit) = 1; + MEM_VOLATILE_P (memit4) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit, arg2); + emit_move_insn (memit4, arg1); + emit_move_insn (target, memit4); + + return target; +} +static rtx +rx_expand_tfu_hypot (tree exp, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + if (!REG_P (arg1)) + { + arg1 = force_reg (SFmode, arg1); + } + + if (!REG_P (arg2)) + { + arg2 = force_reg (SFmode, arg2); + } + + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081418); + + REAL_VALUE_TYPE r; + real_from_string (&r, "0.607252955437"); + + rtx fmul = const_double_from_real_value (r, SFmode); + + rtx valMul = gen_reg_rtx (SImode); + rtx valMul2 = gen_reg_rtx (SFmode); + + rtx emit = gen_reg_rtx (SImode); + rtx inc = gen_rtx_CONST_INT (SImode, 4); + + rtx memit1 = gen_rtx_MEM (SFmode, emit); + rtx memit2; + + MEM_VOLATILE_P (memit1) = 1; + + emit_move_insn (emit, addr); + emit_move_insn (memit1, arg1); + memit2 = gen_rtx_MEM (SFmode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit2) = 1; + emit_move_insn (memit2, arg2); + + gen_movsi (valMul, gen_rtx_CONST_INT (SImode, 0)); + + + emit_move_insn (valMul2, memit1); + + + emit_insn (gen_mulsf3 (valMul2, valMul2, fmul)); + + emit_move_insn (target, valMul2); + + return target; +} +static rtx +rx_expand_tfu_hypotfx (tree exp, rtx target) +{ + if (target == NULL_RTX) + return NULL_RTX; + + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1)); + + if (!REG_P (arg1)) + { arg1 = force_reg (SImode, arg1); + } - if (! REG_P (arg2)) + if (!REG_P (arg2)) + { arg2 = force_reg (SImode, arg2); + } - emit_insn (gen_func (arg1, arg2)); + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081428); - return NULL_RTX; -} + rtx fmul = gen_rtx_CONST_INT (SImode, -1686835800); + rtx fmul2 = gen_reg_rtx (SImode); -static rtx -rx_expand_int_builtin_1_arg (rtx arg, - rtx target, - rtx (* gen_func)(rtx, rtx), - bool mem_ok) -{ - if (! REG_P (arg)) - if (!mem_ok || ! MEM_P (arg)) - arg = force_reg (SImode, arg); + rtx valMul = gen_reg_rtx (SImode); + rtx valMul2 = gen_reg_rtx (SImode); + rtx valMul3 = gen_reg_rtx (DImode); - if (target == NULL_RTX || ! REG_P (target)) - target = gen_reg_rtx (SImode); + rtx emit = gen_reg_rtx (SImode); - emit_insn (gen_func (target, arg)); + rtx inc = gen_rtx_CONST_INT (SImode, 4); - return target; -} + rtx memit1 = gen_rtx_MEM (SImode, emit); + rtx memit2; -static rtx -rx_expand_int_builtin_0_arg (rtx target, rtx (* gen_func)(rtx)) -{ - if (target == NULL_RTX || ! REG_P (target)) - target = gen_reg_rtx (SImode); + MEM_VOLATILE_P (memit1) = 1; - emit_insn (gen_func (target)); + emit_move_insn (emit, addr); + emit_move_insn(fmul2, fmul); + emit_move_insn (memit1, arg1); + memit2 = gen_rtx_MEM (SImode, gen_rtx_PLUS(SImode, emit, inc)); + MEM_VOLATILE_P (memit2) = 1; + emit_move_insn (memit2, arg2); - return target; -} + gen_movsi (valMul, gen_rtx_CONST_INT (SImode, 0)); -static rtx -rx_expand_builtin_round (rtx arg, rtx target) -{ - if ((! REG_P (arg) && ! MEM_P (arg)) - || GET_MODE (arg) != SFmode) - arg = force_reg (SFmode, arg); - if (target == NULL_RTX || ! REG_P (target)) - target = gen_reg_rtx (SImode); + emit_move_insn (valMul2, memit1); - emit_insn (gen_lrintsf2 (target, arg)); + + emit_insn (gen_umulsidi3 (valMul3, valMul2, fmul2)); + + emit_move_insn (target, gen_rtx_SUBREG (SImode, valMul3, 4)); return target; } - -static int -valid_psw_flag (rtx op, const char *which) +static rtx +rx_expand_builtin_tfu_init () { - static int mvtc_inform_done = 0; + rtx addr = gen_rtx_CONST_INT (SImode, 0x00081400); + rtx emit = gen_reg_rtx (SImode); + rtx memit = gen_rtx_MEM (QImode, emit); + rtx inc = gen_rtx_CONST_INT (SImode, 1); + rtx constVal = gen_rtx_CONST_INT (SImode, 7); - if (GET_CODE (op) == CONST_INT) - switch (INTVAL (op)) - { - case 0: case 'c': case 'C': - case 1: case 'z': case 'Z': - case 2: case 's': case 'S': - case 3: case 'o': case 'O': - case 8: case 'i': case 'I': - case 9: case 'u': case 'U': - return 1; - } - error ("%<__builtin_rx_%s%> takes %, %, %, %, %, " - "or %", which); - if (!mvtc_inform_done) - error ("use %<__builtin_rx_mvtc (0, ... )%> to write arbitrary values to PSW"); - mvtc_inform_done = 1; + MEM_VOLATILE_P (memit) = 1; - return 0; + emit_move_insn (emit, addr); + emit_move_insn (memit, constVal); + emit_move_insn (gen_rtx_MEM (QImode, gen_rtx_PLUS(SImode, emit, inc)), constVal); + + return NULL_RTX; } static rtx @@ -2632,8 +4147,8 @@ rx_expand_builtin (tree exp, if (!valid_psw_flag (op, "setpsw")) return NULL_RTX; return rx_expand_void_builtin_1_arg (op, gen_setpsw, false); - case RX_BUILTIN_INT: return rx_expand_void_builtin_1_arg - (op, gen_int, false); + case RX_BUILTIN_INT: return rx_expand_void_builtin_1_int_arg + (op, gen_int); case RX_BUILTIN_MACHI: return rx_expand_builtin_mac (exp, gen_machi); case RX_BUILTIN_MACLO: return rx_expand_builtin_mac (exp, gen_maclo); case RX_BUILTIN_MULHI: return rx_expand_builtin_mac (exp, gen_mulhi); @@ -2653,16 +4168,118 @@ rx_expand_builtin (tree exp, error ("%<-mno-allow-string-insns%> forbids the generation " "of the RMPA instruction"); return NULL_RTX; + case RX_BUILTIN_RMPA8: + if (rx_allow_string_insns) + return rx_expand_builtin_rmpa (exp, target, QImode); + else + error ("-mno-allow-string-insns forbids the generation of the RMPA instruction"); + return NULL_RTX; + case RX_BUILTIN_RMPA16: + if (rx_allow_string_insns) + return rx_expand_builtin_rmpa (exp, target, HImode); + else + error ("-mno-allow-string-insns forbids the generation of the RMPA instruction"); + return NULL_RTX; + case RX_BUILTIN_RMPA32: + if (rx_allow_string_insns) + return rx_expand_builtin_rmpa (exp, target, SImode); + else + error ("-mno-allow-string-insns forbids the generation of the RMPA instruction"); + 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); + case RX_BUILTIN_DROUND: return rx_expand_builtin_dround (op, target); case RX_BUILTIN_REVW: return rx_expand_int_builtin_1_arg - (op, target, gen_revw, false); + (op, target, gen_revw, false, true); case RX_BUILTIN_WAIT: emit_insn (gen_wait ()); return NULL_RTX; - + case RX_BUILTIN_BSET: return rx_expand_builtin_bit_manip(exp, target, gen_bset); + case RX_BUILTIN_BCLR: return rx_expand_builtin_bit_manip(exp, target, gen_bclr); + case RX_BUILTIN_BNOT: return rx_expand_builtin_bit_manip(exp, target, gen_binvert); + case RX_BUILTIN_BSET_MEM: return rx_expand_builtin_bit_manip_mem(exp, gen_bitset_in_memory); + case RX_BUILTIN_BCLR_MEM: return rx_expand_builtin_bit_manip_mem(exp, gen_bclr_memory); + case RX_BUILTIN_BNOT_MEM: return rx_expand_builtin_bit_manip_mem(exp, gen_bnot_memory); + case RX_BUILTIN_XCHG: return rx_expand_builtin_xchg(exp); + /* RXV2 builtins */ + case RX_BUILTIN_EMULA_A0: return rx_expand_builtin_mac(exp, gen_emula_A0); + case RX_BUILTIN_EMULA_A1: return rx_expand_builtin_mac(exp, gen_emula_A1); + case RX_BUILTIN_EMACA_A0: return rx_expand_builtin_mac(exp, gen_emaca_A0); + case RX_BUILTIN_EMACA_A1: return rx_expand_builtin_mac(exp, gen_emaca_A1); + case RX_BUILTIN_EMSBA_A0: return rx_expand_builtin_mac(exp, gen_emsba_A0); + case RX_BUILTIN_EMSBA_A1: return rx_expand_builtin_mac(exp, gen_emsba_A1); + case RX_BUILTIN_MULLH_A0: return rx_expand_builtin_mac(exp, gen_mullh_A0); + case RX_BUILTIN_MULLH_A1: return rx_expand_builtin_mac(exp, gen_mullh_A1); + /* no need for RX_BUILTIN_MULHI_A0: */ + case RX_BUILTIN_MULHI_A1: return rx_expand_builtin_mac(exp, gen_mulhi_A1); + /* no need for RX_BUILTIN_MULLO_A0: */ + case RX_BUILTIN_MULLO_A1: return rx_expand_builtin_mac(exp, gen_mullo_A1); + case RX_BUILTIN_MACLH_A0: return rx_expand_builtin_mac(exp, gen_maclh_A0); + case RX_BUILTIN_MACLH_A1: return rx_expand_builtin_mac(exp, gen_maclh_A1); + /* no need for RX_BUILTIN_MACHI_A0: */ + case RX_BUILTIN_MACHI_A1: return rx_expand_builtin_mac(exp, gen_machi_A1); + /* no need for RX_BUILTIN_MACLO_A0: */ + case RX_BUILTIN_MACLO_A1: return rx_expand_builtin_mac(exp, gen_maclo_A1); + case RX_BUILTIN_MSBLH_A0: return rx_expand_builtin_mac(exp, gen_msblh_A0); + case RX_BUILTIN_MSBLH_A1: return rx_expand_builtin_mac(exp, gen_msblh_A1); + case RX_BUILTIN_MSBHI_A0: return rx_expand_builtin_mac(exp, gen_msbhi_A0); + case RX_BUILTIN_MSBHI_A1: return rx_expand_builtin_mac(exp, gen_msbhi_A1); + case RX_BUILTIN_MSBLO_A0: return rx_expand_builtin_mac(exp, gen_msblo_A0); + case RX_BUILTIN_MSBLO_A1: return rx_expand_builtin_mac(exp, gen_msblo_A1); + case RX_BUILTIN_RDACW_A0: return rx_expand_void_builtin_1_int_arg(op, gen_rdacw_A0); + case RX_BUILTIN_RDACW_A1: return rx_expand_void_builtin_1_int_arg(op, gen_rdacw_A1); + case RX_BUILTIN_RDACL_A0: return rx_expand_void_builtin_1_arg(op, gen_rdacl_A0, false); + case RX_BUILTIN_RDACL_A1: return rx_expand_void_builtin_1_arg(op, gen_rdacl_A1, false); + /* no need for RX_BUILTIN_RACW_A0: */ + case RX_BUILTIN_RACW_A1: return rx_expand_void_builtin_1_arg(op, gen_racw_A1, false); + case RX_BUILTIN_RACL_A0: return rx_expand_void_builtin_1_arg(op, gen_racl_A0, false); + case RX_BUILTIN_RACL_A1: return rx_expand_void_builtin_1_arg(op, gen_racl_A1, false); + case RX_BUILTIN_MVFACHI_A0: return rx_expand_int_builtin_1_arg(op, target, gen_mvfachi_A0, false, false); + case RX_BUILTIN_MVFACHI_A1: return rx_expand_int_builtin_1_arg(op, target, gen_mvfachi_A1, false, false); + case RX_BUILTIN_MVFACMI_A0: return rx_expand_int_builtin_1_arg(op, target, gen_mvfacmi_A0, false, false); + case RX_BUILTIN_MVFACMI_A1: return rx_expand_int_builtin_1_arg(op, target, gen_mvfacmi_A1, false, false); + case RX_BUILTIN_MVFACLO_A0: return rx_expand_int_builtin_1_arg(op, target, gen_mvfaclo_A0, false, false); + case RX_BUILTIN_MVFACLO_A1: return rx_expand_int_builtin_1_arg(op, target, gen_mvfaclo_A1, false, false); + case RX_BUILTIN_MVFACGU_A0: return rx_expand_int_builtin_1_arg(op, target, gen_mvfacgu_A0, false, false); + case RX_BUILTIN_MVFACGU_A1: return rx_expand_int_builtin_1_arg(op, target, gen_mvfacgu_A1, false, false); + /* no need for RX_BUILTIN_MVFACHI_A0: */ + /*case RX_BUILTIN_MVFACHI_A1: return rx_expand_int_builtin_0_arg(target, gen_mvfachi_A1);*/ + /* no need for RX_BUILTIN_MVFACMI_A0: */ + /*case RX_BUILTIN_MVFACMI_A1: return rx_expand_int_builtin_0_arg(target, gen_mvfacmi_A1); + case RX_BUILTIN_MVFACLO_A0: return rx_expand_int_builtin_0_arg(target, gen_mvfaclo_A0); + case RX_BUILTIN_MVFACLO_A1: return rx_expand_int_builtin_0_arg(target, gen_mvfaclo_A1); + case RX_BUILTIN_MVFACLO_A0: return rx_expand_int_builtin_2_arg(target, gen_mvfaclo_A0); + case RX_BUILTIN_MVFACLO_A1: return rx_expand_int_builtin_2_arg(target, gen_mvfaclo_A1); + case RX_BUILTIN_MVFACGU_A0: return rx_expand_int_builtin_0_arg(target, gen_mvfacgu_A0); + case RX_BUILTIN_MVFACGU_A1: return rx_expand_int_builtin_0_arg(target, gen_mvfacgu_A1);*/ + /* no need for RX_BUILTIN_MVTACHI_A0: */ + case RX_BUILTIN_MVTACHI_A1: return rx_expand_void_builtin_1_arg(op, gen_mvtachi_A1, true); + /* no need for RX_BUILTIN_MVTACLO_A0: */ + case RX_BUILTIN_MVTACLO_A1: return rx_expand_void_builtin_1_arg(op, gen_mvtaclo_A1, true); + case RX_BUILTIN_MVTACGU_A0: return rx_expand_void_builtin_1_arg(op, gen_mvtacgu_A0, true); + case RX_BUILTIN_MVTACGU_A1: return rx_expand_void_builtin_1_arg(op, gen_mvtacgu_A1, true); + case RX_BUILTIN_SAVE: return rx_expand_void_builtin_1_arg(op, gen_save, true); + case RX_BUILTIN_RSTR: return rx_expand_void_builtin_1_arg(op, gen_rstr, true); + case RX_BUILTIN_MVFDC: return rx_expand_builtin_mvfdc(exp, target); + case RX_BUILTIN_MVTDC: return rx_expand_builtin_mvtdc(exp); + case RX_BUILTIN_MVFDR: emit_insn (gen_mvfdr ()); return NULL_RTX; + case RX_BUILTIN_BFMOV: return rx_expand_builtin_bitfield_2(exp, target); + case RX_BUILTIN_BFMOVZ: return rx_expand_builtin_bitfield(exp, target); + case RX_TFU_INIT: return rx_expand_builtin_tfu_init (); + case RX_BUILTIN_SINCOSF: return rx_expand_tfu_sincosf (exp); + case RX_BUILTIN_SINCOSFX: return rx_expand_tfu_sincosfx (exp); + case RX_BUILTIN_ATAN2HYPOTF: return rx_expand_tfu_atan2hypotf (exp); + case RX_BUILTIN_ATAN2HYPOTFX: return rx_expand_tfu_atan2hypotfx (exp); + case RX_BUILTIN_SINF: return rx_expand_tfu_sinf (op, target); + case RX_BUILTIN_SINFX: return rx_expand_tfu_sinfx (op, target); + case RX_BUILTIN_COSF: return rx_expand_tfu_cosf (op, target); + case RX_BUILTIN_COSFX: return rx_expand_tfu_cosfx (op, target); + case RX_BUILTIN_ATAN2F: return rx_expand_tfu_atan2f (exp, target); + case RX_BUILTIN_ATAN2FX: return rx_expand_tfu_atan2fx (exp, target); + case RX_BUILTIN_HYPOTF: return rx_expand_tfu_hypot (exp, target); + case RX_BUILTIN_HYPOTFX: return rx_expand_tfu_hypotfx (exp, target); default: internal_error ("bad builtin code"); break; @@ -2759,6 +4376,46 @@ rx_handle_vector_attribute (tree * node, return NULL_TREE; } +static tree +rx_handle_interbank_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + gcc_assert (DECL_P (* node)); + gcc_assert (args != NULL_TREE); + + if (!TARGET_RXV3) + { + error ("%qE attribute only applies to RXV3", + name); + *no_add_attrs = true; + } + + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute only applies to functions", + name); + *no_add_attrs = true; + } + else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST) + { + /* The argument must be a constant integer. */ + warning (OPT_Wattributes, "%qE attribute argument not an " + "integer constant", name); + *no_add_attrs = true; + } + else if ((long int)TREE_INT_CST_LOW (TREE_VALUE (args)) < 0 + || TREE_INT_CST_LOW (TREE_VALUE (args)) > 255) + { + /* The argument value must be between 1 to 255. */ + warning (OPT_Wattributes, + "%qE attribute argument should be between 0 to 255", + name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Table of RX specific attributes. */ TARGET_GNU_ATTRIBUTES (rx_attribute_table, { @@ -2770,43 +4427,72 @@ TARGET_GNU_ATTRIBUTES (rx_attribute_table, rx_handle_func_attribute, NULL }, { "naked", 0, 0, true, false, false, false, rx_handle_func_attribute, NULL }, + { "interrupt_bank", 1, 1, true, false, false, false, + rx_handle_interbank_attribute, NULL }, { "vector", 1, -1, true, false, false, false, rx_handle_vector_attribute, NULL } }); -/* Implement TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. */ static void -rx_override_options_after_change (void) +rx_option_override (void) { - static bool first_time = TRUE; + unsigned int i; + cl_deferred_option *opt; + vec *v = (vec *) rx_deferred_options; - if (first_time) - { - /* If this is the first time through and the user has not disabled - the use of RX FPU hardware then enable -ffinite-math-only, - since the FPU instructions do not support NaNs and infinities. */ - if (TARGET_USE_FPU) - flag_finite_math_only = 1; + /* Default to DWARF4 debug info. */ + if (!OPTION_SET_P(dwarf_version)) + dwarf_version = 4; - first_time = FALSE; + if(flag_morder) { + if (strlen(flag_morder) != 1 || (flag_morder[0] != '0' && atoi(flag_morder) != 1 && atoi(flag_morder) != 2)) { + error("Invalid option! Valid options are -morder0, -morder1 or -morder2."); + } + } + + if(TARGET_RELAX && TARGET_PID) + warning(0, "Enabling both -mrelax and -mpid options together might result in undesired behavior"); + + if (!TARGET_NO_USE_FPU) + { + if(flag_dfpu && TARGET_32BIT_DOUBLES) + { + error("DFPU is not supported with 32 bit doubles"); } + if (flag_dfpu && !TARGET_64BIT_DOUBLES) + { + target_flags |= MASK_64BIT_DOUBLES; + } + } + else if (TARGET_NO_USE_FPU && flag_dfpu) + { + warning(0, "Enabling both -mdfpu and -mnofpu options together might result in undesired behavior. We disabled -dfpu."); + flag_dfpu = 0; + } + + if (flag_optimize_strlen + &&(optimize_size || optimize >= 2)) + { + flag_optimize_strlen = 1; + } else + { + if (flag_optimize_strlen != 1) { - /* Alert the user if they are changing the optimization options - to use IEEE compliant floating point arithmetic with RX FPU insns. */ - if (TARGET_USE_FPU - && !flag_finite_math_only) - warning (0, "RX FPU instructions do not support NaNs and infinities"); + flag_optimize_strlen = 0; } -} + } -static void -rx_option_override (void) -{ - unsigned int i; - cl_deferred_option *opt; - vec *v = (vec *) rx_deferred_options; + if (flag_web && optimize_size) + { + flag_web = 1; + } + + if (flag_tree_loop_if_convert < 0 && optimize_size) + { + flag_tree_loop_if_convert = 1; + } if (v) FOR_EACH_VEC_ELT (*v, i, opt) @@ -2816,9 +4502,6 @@ rx_option_override (void) case OPT_mint_register_: switch (opt->value) { - case 4: - fixed_regs[10] = call_used_regs [10] = 1; - /* Fall through. */ case 3: fixed_regs[11] = call_used_regs [11] = 1; /* Fall through. */ @@ -2844,25 +4527,87 @@ rx_option_override (void) } } + /* Since we can only use r13-r11 for small data and mpid, + limit the accepted values of mint-register accordingly.*/ + if (rx_num_interrupt_regs > 1 && rx_small_data_limit > 0 && TARGET_PID) + error ("Using -mpid and -msmall-data-limit together restricts -mint-register to the [0,1] range!"); + else if (rx_num_interrupt_regs > 2 && rx_small_data_limit > 0) + error ("Using -msmall-data-limit restricts -mint-register to the [0,2] range!"); + else if (rx_num_interrupt_regs > 2 && TARGET_PID) + error ("Using -mpid restricts -mint-register to the [0,2] range!"); + /* This target defaults to strict volatile bitfields. */ if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2)) flag_strict_volatile_bitfields = 1; - rx_override_options_after_change (); - + switch (rx_isa_version) + { + case RX_ISAV1: + /* all cpu's support v1 (backward compatible) */ + break; + case RX_ISAV2: + if ((rx_cpu_type != RX_CPUUNINIT) && (rx_cpu_type != RX64M) && + (rx_cpu_type != RX71M) && (rx_cpu_type != RX230) && + (rx_cpu_type != RX66T) && (rx_cpu_type != RX72T) && + (rx_cpu_type != RX140)) + error ("RXv2 ISA is not supported for this CPU"); + break; + case RX_ISAV3: + if ((rx_cpu_type != RX_CPUUNINIT) && (rx_cpu_type != RX66T) && + (rx_cpu_type != RX72T)) + error ("RXv3 ISA is not supported for this CPU"); + break; + case RX_ISAUNINIT: + /* if no CPU/ISA is specified default to RX600 */ + if(rx_cpu_type == RX_CPUUNINIT) + rx_cpu_type = RX600; + /* set ISA depending on CPU type */ + if((rx_cpu_type == RX66T) || (rx_cpu_type == RX72T)) + rx_isa_version = RX_ISAV3; + else if ((rx_cpu_type == RX64M) || (rx_cpu_type == RX71M) || + (rx_cpu_type == RX230) || (rx_cpu_type == RX140)) + rx_isa_version = RX_ISAV2; + else + rx_isa_version = RX_ISAV1; + break; + } + + /* DFPU is only available for v3 */ + if(flag_dfpu && (rx_isa_version != RX_ISAV3)) + { + error("DFPU is not supported for this ISA/CPU"); + } + if ((rx_tfu_version != RX_TFUV2) && TARGET_NO_SAVE_TFU) + { + error("-mnosave-tfu option needs the -mtfu-version=v2"); + } + if (!TARGET_TFU && (rx_tfu_version != RX_TFUVUNINIT)) + { + error("-mtfu-version option needs the -mtfu option"); + } + /* Specifying -mtfu without -mtfu-version defaults the latter to v1. */ + if (TARGET_TFU && (rx_tfu_version == RX_TFUVUNINIT)) + { + rx_tfu_version = RX_TFUV1; + } /* These values are bytes, not log. */ if (! optimize_size) { if (flag_align_jumps && !str_align_jumps) - str_align_jumps = ((rx_cpu_type == RX100 + str_align_jumps = ((rx_cpu_type == RX100 || rx_cpu_type == RX13T || rx_cpu_type == RX140 || rx_cpu_type == RX200) ? "4" : "8"); if (flag_align_loops && !str_align_loops) - str_align_loops = ((rx_cpu_type == RX100 + str_align_loops = ((rx_cpu_type == RX100 || rx_cpu_type == RX13T || rx_cpu_type == RX140 || rx_cpu_type == RX200) ? "4" : "8"); if (flag_align_labels && !str_align_labels) - str_align_labels = ((rx_cpu_type == RX100 + str_align_labels = ((rx_cpu_type == RX100 || rx_cpu_type == RX13T || rx_cpu_type == RX140 || rx_cpu_type == RX200) ? "4" : "8"); } + + /* LTO compression is not reliable on all hosts, + so change the default to no_compression. */ + if (flag_lto_compression_level < 0) + flag_lto_compression_level = 0; } @@ -2878,7 +4623,8 @@ rx_func_attr_inlinable (const_tree decl) { return ! is_fast_interrupt_func (decl) && ! is_interrupt_func (decl) - && ! is_naked_func (decl); + && ! is_interrupt_bank_func (decl) + && ! is_naked_func (decl); } static bool @@ -2906,6 +4652,7 @@ rx_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) /* Never tailcall from inside interrupt handlers or naked functions. */ if (is_fast_interrupt_func (NULL_TREE) || is_interrupt_func (NULL_TREE) + || is_interrupt_bank_func (NULL_TREE) || is_naked_func (NULL_TREE)) return false; @@ -2962,7 +4709,7 @@ rx_is_legitimate_constant (machine_mode mode ATTRIBUTE_UNUSED, rtx x) gcc_unreachable (); } break; - + case LABEL_REF: case SYMBOL_REF: return true; @@ -3002,7 +4749,7 @@ rx_address_cost (rtx addr, machine_mode mode ATTRIBUTE_UNUSED, && ((INTVAL (b) > 128) || INTVAL (b) < -127)) /* Try to discourage REG + when optimizing for size. */ return COSTS_N_INSNS (2); - + return COSTS_N_INSNS (1); } @@ -3080,12 +4827,12 @@ rx_trampoline_template (FILE * file) /* Output assembler code for a block containing the constant part of a trampoline, leaving space for the variable parts. - On the RX, (where r8 is the static chain regnum) the trampoline + On the RX, (where r14 is the static chain regnum) the trampoline looks like: - mov #, r8 - mov #, r9 - jmp r9 + mov #, r14 + mov #, r5 + jmp r5 In big-endian-data-mode however instructions are read into the CPU 4 bytes at a time. These bytes are then swapped around before being @@ -3098,11 +4845,11 @@ rx_trampoline_template (FILE * file) nop nop - mov.l #<...>, r8 + mov.l #<...>, r14 nop nop - mov.l #<...>, r9 - jmp r9 + mov.l #<...>, r5 + jmp r5 nop nop */ @@ -3115,23 +4862,23 @@ rx_trampoline_template (FILE * file) else { char r8 = '0' + STATIC_CHAIN_REGNUM; - char r9 = '0' + TRAMPOLINE_TEMP_REGNUM; + char rt = '0' + TRAMPOLINE_TEMP_REGNUM; if (TARGET_AS100_SYNTAX) { asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H, 003H\n", r8); asm_fprintf (file, "\t.BYTE 0deH, 0adH, 0beH, 0efH\n"); - asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H, 003H\n", r9); + asm_fprintf (file, "\t.BYTE 0%c2H, 0fbH, 003H, 003H\n", rt); asm_fprintf (file, "\t.BYTE 0deH, 0adH, 0beH, 0efH\n"); - asm_fprintf (file, "\t.BYTE 003H, 003H, 00%cH, 07fH\n", r9); + asm_fprintf (file, "\t.BYTE 003H, 003H, 00%cH, 07fH\n", rt); } else { asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03, 0x03\n", r8); asm_fprintf (file, "\t.byte 0xde, 0xad, 0xbe, 0xef\n"); - asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03, 0x03\n", r9); + asm_fprintf (file, "\t.byte 0x%c2, 0xfb, 0x03, 0x03\n", rt); asm_fprintf (file, "\t.byte 0xde, 0xad, 0xbe, 0xef\n"); - asm_fprintf (file, "\t.byte 0x03, 0x03, 0x0%c, 0x7f\n", r9); + asm_fprintf (file, "\t.byte 0x03, 0x03, 0x0%c, 0x7f\n", rt); } } } @@ -3315,6 +5062,80 @@ rx_match_ccmode (rtx insn, machine_mode cc_mode) return true; } + + #undef TARGET_INSERT_ATTRIBUTES + #define TARGET_INSERT_ATTRIBUTES rx_insert_attributes + +/* Hash table of pragma info. */ +// m32c.c +static GTY(()) hash_map *pragma_htab; + +struct GTY(()) pragma_entry { + const char *varname; + unsigned address; +}; +typedef struct pragma_entry pragma_entry; + +static bool +rx_get_pragma_address (const char *varname, unsigned *address) +{ + if (!pragma_htab) + return false; + unsigned int *slot = pragma_htab->get (varname); + if (slot) + { + *address = *slot; + return true; + } + return false; +} + +void +rx_note_pragma_address (const char *varname, unsigned address) +{ + if (!pragma_htab) + pragma_htab = hash_map::create_ggc (31); + + const char *name = ggc_strdup (varname); + unsigned int *slot = &pragma_htab->get_or_insert (name); + *slot = address; +} + +void +rx_output_aligned_common (FILE *stream, tree decl ATTRIBUTE_UNUSED, + const char *name, + int size, int align) +{ + unsigned int address; + if (rx_get_pragma_address (name, &address)) + { + fprintf (stream, "\t.set "); + assemble_name (stream, name); + fprintf (stream, ", 0x%08x\n", address); + } + else + { + fprintf (stream, "\t.comm\t"); + assemble_name (stream, name); + fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT); + } +} + +static void +rx_insert_attributes (tree node, tree * attr_ptr ATTRIBUTE_UNUSED) +{ + unsigned addr; + /* See if we need to make #pragma address variables volatile. */ + if ((TREE_CODE (node) == VAR_DECL) && DECL_NAME (node)) + { + const char *name = IDENTIFIER_POINTER (DECL_NAME (node)); + if (rx_get_pragma_address (name, &addr)) + { + TREE_THIS_VOLATILE (node) = true; + } + } +} + static int @@ -3364,7 +5185,7 @@ rx_align_log_for_label (rtx_insn *lab, int uses_threshold) return 0; /* These values are log, not bytes. */ - if (rx_cpu_type == RX100 || rx_cpu_type == RX200) + if (rx_cpu_type == RX100 || rx_cpu_type == RX140 || rx_cpu_type == RX200) return 2; /* 4 bytes */ return 3; /* 8 bytes */ } @@ -3422,7 +5243,7 @@ rx_adjust_insn_length (rtx_insn *insn, int current_length) zero = false; factor = 2; break; - + case CODE_FOR_plussi3_zero_extendqi: case CODE_FOR_andsi3_zero_extendqi: case CODE_FOR_iorsi3_zero_extendqi: @@ -3437,7 +5258,7 @@ rx_adjust_insn_length (rtx_insn *insn, int current_length) zero = true; factor = 1; break; - + case CODE_FOR_plussi3_sign_extendqi: case CODE_FOR_andsi3_sign_extendqi: case CODE_FOR_iorsi3_sign_extendqi: @@ -3452,7 +5273,7 @@ rx_adjust_insn_length (rtx_insn *insn, int current_length) zero = false; factor = 1; break; - } + } /* We are expecting: (SET (REG) ( (REG) ( (MEM)))). */ extend = single_set (insn); @@ -3467,7 +5288,7 @@ rx_adjust_insn_length (rtx_insn *insn, int current_length) gcc_assert ((zero && (GET_CODE (extend) == ZERO_EXTEND)) || (! zero && (GET_CODE (extend) == SIGN_EXTEND))); - + mem = XEXP (extend, 0); gcc_checking_assert (MEM_P (mem)); if (REG_P (XEXP (mem, 0))) @@ -3511,6 +5332,332 @@ rx_ok_to_inline (tree caller, tree callee) || lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (callee)) != NULL_TREE; } +void +rx_adjust_reg_alloc_order (void) +{ + unsigned int i; + const int *order; + /* CyberTHOR Studios order */ + static const int order_0[] = { + 7, 10, 5, 4, 3, 2, 1, 6, 11, 12, 9, 8, 13, 14, 15 + }; + /* Renesas order */ + static const int order_1[] = { + 14, 1, 2, 3, 4, 5, 6, 7, 10, 11, 8, 9, 12, 13, 15 + }; + /* Red Hat order */ + static const int order_2[] = { + 7, 10, 11, 12, 13, 14, 4, 3, 2, 1, 9, 8, 6, 5, 15 + }; + + order = order_0; + + if (flag_morder && strlen(flag_morder) == 1) + { + if (atoi(flag_morder) == 1) + { + order = order_1; + } + if (atoi(flag_morder) == 2) + { + order = order_2; + } + } + + for (i=0; i < ARRAY_SIZE (order_0); ++i) + reg_alloc_order[i] = order[i]; +} + + +enum dual_issue_mode +{ + x = 0, /* not applicable */ + DW, /* applicable if both no Data and no WAW(write after write) dependence */ + D, /* applicable if no Data (including flag) dependence between instructions */ + F, /* applicable if no Flag(OSZC) dependence between instructions */ + A /* always applicable */ +}; + +const dual_issue_mode dual_issue_matrix[] = +{ +/* IEX IEP IML IBC IBR IBS ILS ILSP IFE IFM IF1 SEC/PRI */ + F, x, D, F, D, D, D, x, D, D, D, /* IEX */ + D, x, D, F, D, D, D, x, D, D, D, /* IEP */ + D, x, x, A, D, D, D, x, D, x, D, /* IML */ + A, x, A, A, A, A, A, x, A, A, A, /* IBC */ + x, x, x, x, x, x, x, x, x, x, x, /* IBR */ + x, x, x, x, x, x, x, x, x, x, x, /* IBS */ + DW, x, DW, A, DW, x, x, x, DW, DW, DW, /* ILS */ + DW, x, DW, A, DW, x, x, x, DW, DW, DW, /* ILSP */ + x, x, x, x, x, x, x, x, x, x, x, /* IFE */ + x, x, x, x, x, x, x, x, x, x, x, /* IFM */ + D, x, D, x, D, D, D, x, x, x, x, /* IF1 */ +}; + +struct rx_sched_data { + rtx_code code; + int regno; + op_type type; +}; + +static int +rx_issue_rate (void) +{ + return 2; +} + +static int +rx_sched_solve_dependency(dual_issue_mode mode, rx_sched_data *pri, int pri_size, rx_sched_data *sec, int sec_size) +{ + int dependency = 0; + int i, j; + + switch (mode) + { + case x: + /* if selected mode is not applicable, we have single issue */ + dependency++; + break; + case DW: + /* check for write after write */ + for (i=0; i=0; i--) + if ((pri[i].code == REG) && (pri[i].type != OP_IN) && (pri[i].regno == CC_REGNUM)) + { + for (j=sec_size-1; j>=0; j--) + if ((sec[j].code == REG) && (sec[j].type != OP_OUT) && (sec[j].regno == CC_REGNUM)) + { + /* flag deps not met */ + dependency++; + break; + } + /* early exit */ + break; + } + /* fallthrough */ + default: + /* ideal case, nothing to do */ + break; + } + return dependency; +} + +static bool +rx_insn_clobbers_cc (rtx insn) +{ + if (INSN_P (insn) + && GET_CODE (PATTERN (insn)) == PARALLEL) + { + rtx parallel = PATTERN (insn); + rtx clobber; + int j; + for (j = XVECLEN (parallel, 0) - 1; j >= 0; j--) + { + clobber = XVECEXP (parallel, 0, j); + if (GET_CODE (clobber) == CLOBBER) + { + if (GET_CODE (XEXP (clobber, 0)) == REG + && REGNO (XEXP (clobber, 0)) == CC_REGNUM) + return 1; + } + } + } + return 0; +} + +static int +rx_sched_reorder (FILE *dump ATTRIBUTE_UNUSED, + int sched_verbose ATTRIBUTE_UNUSED, + rtx_insn **ready ATTRIBUTE_UNUSED, + int *pn_ready ATTRIBUTE_UNUSED, int clock_var) +{ + int more = 2; + int pri_idx = *pn_ready-1; + int sec_idx = *pn_ready-2; + + /* skip insn that are asm or do not generate insns */ + if ( (pri_idx < 0) \ + || (GET_CODE (PATTERN (ready[pri_idx])) == ASM_INPUT) \ + || (GET_CODE (PATTERN (ready[pri_idx])) == USE) \ + || (GET_CODE (PATTERN (ready[pri_idx])) == CLOBBER) ) + pri_idx = -1; + if ( (sec_idx < 0) \ + || (GET_CODE (PATTERN (ready[sec_idx])) == ASM_INPUT) \ + || (GET_CODE (PATTERN (ready[sec_idx])) == USE) \ + || (GET_CODE (PATTERN (ready[sec_idx])) == CLOBBER) ) + sec_idx = -1; + + if ((pri_idx < 0) || (sec_idx < 0)) + { + more = 1; + if ((sched_verbose > 1) && (dump != NULL)) + fprintf(dump, "RX reorder algorithm scheduled the last insn at clock: %d.\n", clock_var); + } + else + { + int insn_size = INSN_GROUP_ISNG; + attr_insn_group pri_group = get_attr_insn_group(ready[pri_idx]); + attr_insn_group sec_group = get_attr_insn_group(ready[sec_idx]); + + /* early exit in case of single instructions */ + if (pri_group == INSN_GROUP_ISNG) + { + more = 1; + } + else if (sec_group == INSN_GROUP_ISNG) + { + rtx_insn * pri_insn = ready[pri_idx]; + rtx_insn * sec_insn = ready[sec_idx]; + ready[pri_idx] = sec_insn; + ready[sec_idx] = pri_insn; + more = 1; + } + /* get dependency conditions from matrix and solve for every combination */ + else + { + dual_issue_mode forward_mode = dual_issue_matrix[insn_size*pri_group+sec_group]; + dual_issue_mode inverse_mode = dual_issue_matrix[insn_size*sec_group+pri_group]; + rx_sched_data pri_data[MAX_RECOG_OPERANDS], sec_data[MAX_RECOG_OPERANDS]; + int i, pri_operands, sec_operands; + bool is_clobber, is_append; + + /* extract first insn to resolve dependencies */ + is_clobber = rx_insn_clobbers_cc (ready[pri_idx]); + is_append = true; + insn_extract (ready[pri_idx]); + pri_operands = recog_data.n_operands; + for (i=0; i 1) && (dump != NULL)) + fprintf(dump, "\nRX reorder resulted in insn inversion at clock: %d.", clock_var); + } + else + { + /* fallback and try forward order */ + if (rx_sched_solve_dependency(forward_mode, pri_data, pri_operands, sec_data, sec_operands) != 0) + /* both dependencies fail, must issue single insn */ + more = 1; + } + } + else + { + /* solve dependencies in forward order */ + if (rx_sched_solve_dependency(forward_mode, pri_data, pri_operands, sec_data, sec_operands) != 0) + { + /* fallback and try inverse order */ + if (rx_sched_solve_dependency(inverse_mode, sec_data, sec_operands, pri_data, pri_operands) == 0) + { + /* inverse order is good to go, so swap insns */ + rtx_insn * pri_insn = ready[pri_idx]; + rtx_insn * sec_insn = ready[sec_idx]; + ready[pri_idx] = sec_insn; + ready[sec_idx] = pri_insn; + if ((sched_verbose > 1) && (dump != NULL)) + fprintf(dump, "\nRX reorder resulted in insn inversion at clock: %d.", clock_var); + } + else + /* both dependencies fail, must issue single insn */ + more = 1; + } + } + } + if ((sched_verbose > 1) && (dump != NULL)) + { + fprintf(dump, "\nRX reorder algorithm scheduled insns %d out of %d at clock: %d.", \ + more, *pn_ready, clock_var); + } + } + return more; +} + + static bool rx_enable_lra (void) { @@ -3632,12 +5779,19 @@ rx_hard_regno_nregs (unsigned int, machine_mode mode) /* Implement TARGET_HARD_REGNO_MODE_OK. */ -static bool -rx_hard_regno_mode_ok (unsigned int regno, machine_mode) +bool +rx_hard_regno_mode_ok (unsigned regno, machine_mode mode) { + if (TARGET_RXV3 && IS_DFPU) + { + if (mode == DFmode) + { + return ((REGNO_REG_CLASS (regno) == DOUBLE_REGS) && (regno % 2 == 0)) || + ((REGNO_REG_CLASS (regno) == GR_REGS) && (regno <= 14)); + } + } return REGNO_REG_CLASS (regno) == GR_REGS; } - /* Implement TARGET_MODES_TIEABLE_P. */ static bool @@ -3648,7 +5802,63 @@ rx_modes_tieable_p (machine_mode mode1, machine_mode mode2) == (GET_MODE_CLASS (mode2) == MODE_FLOAT || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT)); } - + +/* Implement TARGET_NOCE_CONVERSION_PROFITABLE_P. */ +static bool +rx_noce_conversion_profitable_p (rtx_insn *seq, struct noce_if_info *if_info) +{ + /* Only when optimizing for size and just one instruction in sequence. */ + if (!if_info->speed_p && !NEXT_INSN (seq)) + { + /* If it looks like a movsicc */ + if (rtx set = single_set (seq); + set && GET_CODE (SET_SRC (set)) == IF_THEN_ELSE) + { + /* Determine 'factor' as the rtx_cost() impl. from rtlanal.cc. */ + machine_mode mode = GET_MODE (SET_DEST (set)); + unsigned mode_size = estimated_poly_value (GET_MODE_SIZE (mode)); + int factor = mode_size > UNITS_PER_WORD ? mode_size / UNITS_PER_WORD : 1; + + /* Cost up the new sequence. */ + unsigned int cost = seq_cost (seq, false); + /* Favor the conversion (up to the cost of one extra instruction). */ + return (cost <= if_info->original_cost + factor * COSTS_N_INSNS (1)); + } + } + return default_noce_conversion_profitable_p (seq, if_info); +} + +bool +rx_scalar_mode_supported_p(scalar_mode mode) +{ + int precision = GET_MODE_PRECISION(mode); + + /* Keep default behavior for integer and float modes */ + switch (GET_MODE_CLASS(mode)) { + case MODE_FLOAT: + /* Only allow DF if TARGET_64BIT_DOUBLES */ +#ifdef __RX_32BIT_DOUBLES__ + if (mode == DFmode) + return false; // disable DFmode +#endif + return default_scalar_mode_supported_p(mode); + + default: + return default_scalar_mode_supported_p(mode); + } +} + +bool +rx_libgcc_floating_mode_supported_p(scalar_float_mode mode) +{ +#ifdef __RX_32BIT_DOUBLES__ + if (mode == E_DFmode) + return false; // DF mode not supported in libgcc +#endif + + return default_libgcc_floating_mode_supported_p(mode); +} + #undef TARGET_NARROW_VOLATILE_BITFIELD #define TARGET_NARROW_VOLATILE_BITFIELD rx_narrow_volatile_bitfield @@ -3740,7 +5950,7 @@ rx_modes_tieable_p (machine_mode mode1, machine_mode mode2) #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true #undef TARGET_MAX_ANCHOR_OFFSET -#define TARGET_MAX_ANCHOR_OFFSET 32 +#define TARGET_MAX_ANCHOR_OFFSET 65536 #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST rx_address_cost @@ -3775,9 +5985,6 @@ rx_modes_tieable_p (machine_mode mode1, machine_mode mode2) #undef TARGET_PROMOTE_FUNCTION_MODE #define TARGET_PROMOTE_FUNCTION_MODE rx_promote_function_mode -#undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE -#define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE rx_override_options_after_change - #undef TARGET_FLAGS_REGNUM #define TARGET_FLAGS_REGNUM CC_REG @@ -3785,7 +5992,10 @@ rx_modes_tieable_p (machine_mode mode1, machine_mode mode2) #define TARGET_LEGITIMATE_CONSTANT_P rx_is_legitimate_constant #undef TARGET_LEGITIMIZE_ADDRESS -#define TARGET_LEGITIMIZE_ADDRESS rx_legitimize_address +#define TARGET_LEGITIMIZE_ADDRESS rx_legitimize_address + +#undef TARGET_DELAY_SCHED2 +#define TARGET_DELAY_SCHED2 true #undef TARGET_WARN_FUNC_RETURN #define TARGET_WARN_FUNC_RETURN rx_warn_func_return @@ -3793,6 +6003,12 @@ rx_modes_tieable_p (machine_mode mode1, machine_mode mode2) #undef TARGET_LRA_P #define TARGET_LRA_P rx_enable_lra +#undef TARGET_SCHED_ISSUE_RATE +#define TARGET_SCHED_ISSUE_RATE rx_issue_rate + +#undef TARGET_SCHED_REORDER +#define TARGET_SCHED_REORDER rx_sched_reorder + #undef TARGET_HARD_REGNO_NREGS #define TARGET_HARD_REGNO_NREGS rx_hard_regno_nregs #undef TARGET_HARD_REGNO_MODE_OK @@ -3807,6 +6023,17 @@ rx_modes_tieable_p (machine_mode mode1, machine_mode mode2) #undef TARGET_HAVE_SPECULATION_SAFE_VALUE #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed +#undef TARGET_NOCE_CONVERSION_PROFITABLE_P +#define TARGET_NOCE_CONVERSION_PROFITABLE_P rx_noce_conversion_profitable_p + +#undef TARGET_SCALAR_MODE_SUPPORTED_P +#define TARGET_SCALAR_MODE_SUPPORTED_P rx_scalar_mode_supported_p + +#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P +#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \ + rx_libgcc_floating_mode_supported_p + + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-rx.h" diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h index b1ec8655da0e6..9474e822db860 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -45,6 +45,53 @@ builtin_assert ("machine=RX600"); \ } \ \ + if (rx_cpu_type == RX66T) \ + { \ + builtin_define ("__RX66T__"); \ + builtin_assert ("machine=RX66T"); \ + } \ + if (rx_cpu_type == RX64M) \ + { \ + builtin_define ("__RX64M__"); \ + builtin_assert ("machine=RX64M"); \ + } \ + if (rx_cpu_type == RX71M) \ + { \ + builtin_define ("__RX71M__"); \ + builtin_assert ("machine=RX71M"); \ + } \ + if (rx_cpu_type == RX72T) \ + { \ + builtin_define ("__RX72T__"); \ + builtin_assert ("machine=RX72T"); \ + } \ + if (rx_cpu_type == RX230) \ + { \ + builtin_define ("__RX230__"); \ + builtin_assert ("machine=RX230"); \ + } \ + if (rx_cpu_type == RX13T) \ + { \ + builtin_define ("__RX13T__"); \ + builtin_assert ("machine=R13T"); \ + } \ + if (rx_cpu_type == RX140) \ + { \ + builtin_define ("__RX140__"); \ + builtin_assert ("machine=RX140"); \ + } \ + if (rx_isa_version == RX_ISAV2) \ + { \ + builtin_define ("__RXv2__"); \ + } \ + else if (rx_isa_version == RX_ISAV3) \ + { \ + builtin_define ("__RXv3__"); \ + } \ + else \ + { \ + builtin_define ("__RXv1__"); \ + } \ if (TARGET_BIG_ENDIAN_DATA) \ builtin_define ("__RX_BIG_ENDIAN__"); \ else \ @@ -58,28 +105,49 @@ if (ALLOW_RX_FPU_INSNS) \ builtin_define ("__RX_FPU_INSNS__"); \ \ + if(flag_dfpu) \ + builtin_define ("__RX_DFPU_INSNS__"); \ + \ + /* Override __LIBGCC_HAVE_HWDBL__ from common code */ \ + /* Only define when we have both DFPU and 64-bit doubles */ \ + cpp_undef (pfile, "__LIBGCC_HAVE_HWDBL__"); \ + if (flag_dfpu && TARGET_64BIT_DOUBLES) \ + builtin_define ("__LIBGCC_HAVE_HWDBL__"); \ + \ + if (TARGET_TFU) \ + builtin_define_with_int_value ("__TFU", \ + (rx_tfu_version == RX_TFUV2) ? 2 : 1); \ + \ if (TARGET_AS100_SYNTAX) \ builtin_define ("__RX_AS100_SYNTAX__"); \ else \ builtin_define ("__RX_GAS_SYNTAX__"); \ \ - if (TARGET_GCC_ABI) \ - builtin_define ("__RX_GCC_ABI__"); \ - else \ builtin_define ("__RX_ABI__"); \ \ if (rx_allow_string_insns) \ builtin_define ("__RX_ALLOW_STRING_INSNS__"); \ else \ builtin_define ("__RX_DISALLOW_STRING_INSNS__");\ - } \ + \ + if (rx_tfu_type == RX_MATHLIB) \ + { \ + builtin_define_with_value("sinf(x)", "__builtin_rx_sinf(x)", 0); \ + builtin_define_with_value("cosf(x)", "__builtin_rx_cosf(x)", 0); \ + builtin_define_with_value("atan2f(x, y)", "__builtin_rx_atan2f(x,y)", 0); \ + builtin_define_with_value("hypotf(x, y)", "__builtin_rx_hypotf(x, y)", 0); \ + } \ + } \ while (0) +#define TARGET_RXV1 ((rx_isa_version == RX_ISAV1) || (rx_isa_version == RX_ISAV2) || (rx_isa_version == RX_ISAV3)) +#define TARGET_RXV2 ((rx_isa_version == RX_ISAV2) || (rx_isa_version == RX_ISAV3)) +#define TARGET_RXV3 ((rx_isa_version == RX_ISAV3)) + +#define TARGET_TFU ((rx_tfu_type == RX_INTRINSIC) || (rx_tfu_type == RX_MATHLIB)) + #undef CC1_SPEC -#define CC1_SPEC "\ - %{mas100-syntax:%{gdwarf*:%e-mas100-syntax is incompatible with -gdwarf}} \ - %{mcpu=rx100:%{fpu:%erx100 cpu does not have FPU hardware}} \ - %{mcpu=rx200:%{fpu:%erx200 cpu does not have FPU hardware}}" +#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" @@ -98,29 +166,35 @@ #define ASM_SPEC "\ %{mbig-endian-data:-mbig-endian-data} \ %{m64bit-doubles:-m64bit-doubles} \ -%{!m64bit-doubles:-m32bit-doubles} \ +%{mdfpu:-m64bit-doubles} \ +%{!m64bit-doubles: %{!mdfpu: -m32bit-doubles}} \ %{msmall-data-limit*:-msmall-data-limit} \ %{mrelax:-relax} \ %{mpid} \ %{mno-allow-string-insns} \ %{mint-register=*} \ -%{mgcc-abi:-mgcc-abi} %{!mgcc-abi:-mrx-abi} \ %{mcpu=*} \ +%{misa=*} \ +%{mdfpu:-dfpu} \ " #undef LIB_SPEC -#define LIB_SPEC \ - "--start-group " \ - "-lc " \ - "%{msim:-lsim}%{!msim:-lnosys} " \ - "%{fprofile-arcs|fprofile-generate|coverage:-lgcov} " \ - "--end-group " \ - "%{!r:%{!T*:" \ - "%{msim:%:if-exists-then-else(%:find-file(rx-sim.ld) %Trx-sim.ld)}" \ - "%{!msim:%:if-exists-then-else(%:find-file(rx.ld) %Trx.ld)}}}" +#define LIB_SPEC " \ +--start-group \ +-lc \ +%{msim:-lsim}%{!msim:-lnosys} \ +%{fprofile-arcs|fprofile-generate|coverage:-lgcov} \ +--end-group \ +%{!T*: %{msim:%Trx-sim.ld}%{!msim:%Trx.ld}} \ +" #undef LINK_SPEC -#define LINK_SPEC "%{mbig-endian-data:--oformat elf32-rx-be} %{mrelax:-relax}" +#define LINK_SPEC " \ +%{mbig-endian-data:--oformat elf32-rx-be} \ +%{mrelax:-relax} \ +%{Os:%{!r:--gc-sections}} \ +%{Os:-relax} \ +" #define BITS_BIG_ENDIAN 0 @@ -141,13 +215,13 @@ /* RX load/store instructions can handle unaligned addresses. */ #define STRICT_ALIGNMENT 0 -#define FUNCTION_BOUNDARY ((rx_cpu_type == RX100 || rx_cpu_type == RX200) ? 4 : 8) +#define FUNCTION_BOUNDARY ((rx_cpu_type == RX100 || rx_cpu_type == RX13T || rx_cpu_type == RX140 || rx_cpu_type == RX200) ? 4 : 8) #define BIGGEST_ALIGNMENT 32 #define STACK_BOUNDARY 32 #define PARM_BOUNDARY 8 #define STACK_GROWS_DOWNWARD 1 -#define FRAME_GROWS_DOWNWARD 0 +#define FRAME_GROWS_DOWNWARD (flag_stack_protect) #define FIRST_PARM_OFFSET(FNDECL) 0 #define MAX_REGS_PER_ADDRESS 2 @@ -180,11 +254,14 @@ #define STORE_FLAG_VALUE 1 #define LOAD_EXTEND_OP(MODE) SIGN_EXTEND #define SHORT_IMMEDIATES_SIGN_EXTEND 1 + +#define IS_DFPU flag_dfpu enum reg_class { NO_REGS, /* No registers in set. */ GR_REGS, /* Integer registers. */ + DOUBLE_REGS, /* Double registers. */ ALL_REGS, /* All registers. */ LIM_REG_CLASSES /* Max value + 1. */ }; @@ -193,14 +270,16 @@ enum reg_class { \ "NO_REGS", \ "GR_REGS", \ + "DOUBLE_REGS", \ "ALL_REGS" \ } #define REG_CLASS_CONTENTS \ { \ - { 0x00000000 }, /* No registers, */ \ - { 0x0000ffff }, /* Integer registers. */ \ - { 0x0000ffff } /* All registers. */ \ + { 0x00000000, 0x00000000 }, /* No registers, */ \ + { 0x0000ffff, 0x00000000 }, /* Integer registers. */ \ + { 0xffff0000, 0x0000ffff }, /* Double registers. */ \ + { 0xffffffff, 0x0000ffff } /* All registers. */ \ } #define N_REG_CLASSES (int) LIM_REG_CLASSES @@ -212,19 +291,19 @@ enum reg_class #define BASE_REG_CLASS GR_REGS #define INDEX_REG_CLASS GR_REGS -#define FIRST_PSEUDO_REGISTER 17 +#define FIRST_PSEUDO_REGISTER 49 +#define FIRST_DOUBLE_REG 16 -#define REGNO_REG_CLASS(REGNO) ((REGNO) < FIRST_PSEUDO_REGISTER \ - ? GR_REGS : NO_REGS) +#define REGNO_REG_CLASS(REGNO) rx_regno_class (REGNO) #define STACK_POINTER_REGNUM 0 #define FUNC_RETURN_REGNUM 1 -#define FRAME_POINTER_REGNUM 6 +#define FRAME_POINTER_REGNUM 10 #define ARG_POINTER_REGNUM 7 -#define STATIC_CHAIN_REGNUM 8 -#define TRAMPOLINE_TEMP_REGNUM 9 +#define STATIC_CHAIN_REGNUM 14 +#define TRAMPOLINE_TEMP_REGNUM 5 #define STRUCT_VAL_REGNUM 15 -#define CC_REGNUM 16 +#define CC_REGNUM 48 /* This is the register which will probably be used to hold the address of the start of the small data area, if -msmall-data-limit is being used, @@ -254,12 +333,22 @@ enum reg_class #define FIXED_REGISTERS \ { \ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 \ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + /* DFPU */ \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + /* cc */ \ + 1 \ } #define CALL_USED_REGISTERS \ { \ - 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 \ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,\ + /* DFPU */ \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ + /* cc */ \ + 1 \ } #define LIBCALL_VALUE(MODE) \ @@ -272,10 +361,23 @@ enum reg_class FUNC_RETURN_REGNUM) /* Order of allocation of registers. */ +#define REG_ALLOC_ORDER \ +{ 7, 10, 11, 12, 13, 14, 4, 3, 2, 1, 9, 8, 6, 5, 15, \ + 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, \ + 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47 \ + } -#define REG_ALLOC_ORDER \ -{ 7, 10, 11, 12, 13, 14, 4, 3, 2, 1, 9, 8, 6, 5, 15 \ -} +/*DFPU registers can only work in double mode */ + +/*#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ + ? reg_classes_intersect_p (DOUBLE_REGS, CLASS) : 0)*/ + + +/* We must somehow disable register remapping for interrupt functions. */ +extern char rx_leaf_registers[]; +#define LEAF_REGISTERS rx_leaf_registers +#define LEAF_REG_REMAP(REG) (REG) #define REGNO_IN_RANGE(REGNO, MIN, MAX) \ (IN_RANGE ((REGNO), (MIN), (MAX)) \ @@ -329,10 +431,16 @@ typedef unsigned int CUMULATIVE_ARGS; fprintf (FILE, "\tbsr\t__mcount\n"); + #define REGISTER_NAMES \ { \ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc" \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \ + "dr0", "", "dr1", "", "dr2", "", "dr3", "", \ + "dr4", "", "dr5", "", "dr6", "", "dr7", "", \ + "dr8", "", "dr9", "", "dr10", "", "dr11", "", \ + "dr12", "", "dr13", "", "dr14", "", "dr15", "", \ + "cc" \ } #define ADDITIONAL_REGISTER_NAMES \ @@ -437,8 +545,13 @@ typedef unsigned int CUMULATIVE_ARGS; else \ fprintf (STREAM, "\t.ALIGN 2\n"); \ } \ - else \ - fprintf (STREAM, "\t.balign %d,3,%d\n", 1 << (LOG), (MAX_SKIP)); \ + else \ + { \ + if (TARGET_NOBALIGN) \ + fprintf (STREAM, "\t;.balign %d,3,%d\n", 1 << (LOG), (MAX_SKIP)); \ + else \ + fprintf (STREAM, "\t.balign %d,3,%d\n", 1 << (LOG), (MAX_SKIP)); \ + } \ } \ while (0) @@ -455,7 +568,12 @@ typedef unsigned int CUMULATIVE_ARGS; fprintf (STREAM, "\t.ALIGN 2\n"); \ } \ else \ - fprintf (STREAM, "\t.balign %d\n", 1 << (LOG)); \ + { \ + if (TARGET_NOBALIGN) \ + fprintf (STREAM, "\t;.balign %d\n", 1 << (LOG)); \ + else \ + fprintf (STREAM, "\t.balign %d\n", 1 << (LOG)); \ + } \ } \ while (0) @@ -627,16 +745,22 @@ typedef unsigned int CUMULATIVE_ARGS; #define DWARF2_DEBUGGING_INFO 1 #define INCOMING_FRAME_SP_OFFSET 4 -#define ARG_POINTER_CFA_OFFSET(FNDECL) 4 +#define ARG_POINTER_CFA_OFFSET(FNDECL) 0 +#define FRAME_POINTER_CFA_OFFSET(FNDECL) (FRAME_GROWS_DOWNWARD ? 0 : rx_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM)) + #define TARGET_USE_FPU (! TARGET_NO_USE_FPU) +#define ALLOW_HW_SQRT (TARGET_RXV2 && TARGET_RX_SQRT) + /* This macro is used to decide when RX FPU instructions can be used. */ #define ALLOW_RX_FPU_INSNS (TARGET_USE_FPU) #define BRANCH_COST(SPEED,PREDICT) 1 #define REGISTER_MOVE_COST(MODE,FROM,TO) 2 +#define NO_FUNCTION_CSE 1 + #define SELECT_CC_MODE(OP,X,Y) rx_select_cc_mode(OP, X, Y) #define ADJUST_INSN_LENGTH(INSN,LENGTH) \ @@ -645,3 +769,15 @@ typedef unsigned int CUMULATIVE_ARGS; (LENGTH) = rx_adjust_insn_length ((INSN), (LENGTH)); \ } \ while (0) + +#define ADJUST_REG_ALLOC_ORDER rx_adjust_reg_alloc_order () + +#undef ASM_OUTPUT_ALIGNED_DECL_COMMON +#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGNMENT) \ + rx_output_aligned_common (STREAM, DECL, NAME, SIZE, ALIGNMENT) + +#define REGISTER_TARGET_PRAGMAS() rx_register_pragmas() + +#define DBX_REGISTER_NUMBER(regno) rx_dbx_register_number(regno) + +#define PC_REGNUM 49 diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 63546b6e0cc15..7bc769a70fc7f 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -30,12 +30,12 @@ ;; then all operations on doubles have to be handled by ;; library functions. (define_mode_iterator register_modes - [(SF "") (SI "") (HI "") (QI "")]) + [(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")]) (define_constants [ (SP_REG 0) - (CC_REG 16) + (CC_REG 48) (UNSPEC_LOW_REG 0) (UNSPEC_HIGH_REG 1) @@ -44,7 +44,7 @@ (UNSPEC_RTFI 11) (UNSPEC_NAKED 12) (UNSPEC_CONST 13) - + (UNSPEC_MOVSTR 20) (UNSPEC_CPYMEM 21) (UNSPEC_SETMEM 22) @@ -69,11 +69,68 @@ (UNSPEC_BUILTIN_RACW 45) (UNSPEC_BUILTIN_REVW 46) (UNSPEC_BUILTIN_RMPA 47) + (UNSPEC_BUILTIN_RMPA8 102) + (UNSPEC_BUILTIN_RMPA16 103) + (UNSPEC_BUILTIN_RMPA32 104) (UNSPEC_BUILTIN_ROUND 48) + (UNSPEC_BUILTIN_DROUND 148) (UNSPEC_BUILTIN_SAT 49) (UNSPEC_BUILTIN_SETPSW 50) (UNSPEC_BUILTIN_WAIT 51) - + (UNSPEC_BUILTIN_BSET 52) + (UNSPEC_BUILTIN_BCLR 53) + (UNSPEC_BUILTIN_BNOT 54) + (UNSPEC_BUILTIN_BSET_MEM 95) + (UNSPEC_BUILTIN_BCLR_MEM 96) + (UNSPEC_BUILTIN_BNOT_MEM 97) + + (UNSPEC_BUILTIN_EMULA_A0 55) + (UNSPEC_BUILTIN_EMULA_A1 56) + (UNSPEC_BUILTIN_EMACA_A0 57) + (UNSPEC_BUILTIN_EMACA_A1 58) + (UNSPEC_BUILTIN_EMSBA_A0 59) + (UNSPEC_BUILTIN_EMSBA_A1 60) + (UNSPEC_BUILTIN_MULLH_A0 61) + (UNSPEC_BUILTIN_MULLH_A1 62) + (UNSPEC_BUILTIN_MULHI_A1 63) + (UNSPEC_BUILTIN_MULLO_A1 64) + (UNSPEC_BUILTIN_MACLH_A0 65) + (UNSPEC_BUILTIN_MACLH_A1 66) + (UNSPEC_BUILTIN_MACHI_A1 67) + (UNSPEC_BUILTIN_MACLO_A1 68) + (UNSPEC_BUILTIN_MSBLH_A0 69) + (UNSPEC_BUILTIN_MSBLH_A1 70) + (UNSPEC_BUILTIN_MSBHI_A0 71) + (UNSPEC_BUILTIN_MSBHI_A1 72) + (UNSPEC_BUILTIN_MSBLO_A0 73) + (UNSPEC_BUILTIN_MSBLO_A1 74) + (UNSPEC_BUILTIN_RDACW_A0 75) + (UNSPEC_BUILTIN_RDACW_A1 76) + (UNSPEC_BUILTIN_RDACL_A0 77) + (UNSPEC_BUILTIN_RDACL_A1 78) + (UNSPEC_BUILTIN_RACW_A1 79) + (UNSPEC_BUILTIN_RACL_A0 80) + (UNSPEC_BUILTIN_RACL_A1 81) + (UNSPEC_BUILTIN_MVFACHI_A0 82) + (UNSPEC_BUILTIN_MVFACHI_A1 83) + (UNSPEC_BUILTIN_MVFACMI_A0 84) + (UNSPEC_BUILTIN_MVFACMI_A1 85) + (UNSPEC_BUILTIN_MVFACLO_A0 86) + (UNSPEC_BUILTIN_MVFACLO_A1 87) + (UNSPEC_BUILTIN_MVFACGU_A0 88) + (UNSPEC_BUILTIN_MVFACGU_A1 89) + (UNSPEC_BUILTIN_MVTACHI_A1 90) + (UNSPEC_BUILTIN_MVTACLO_A1 91) + (UNSPEC_BUILTIN_MVTACGU_A0 92) + (UNSPEC_BUILTIN_MVTACGU_A1 93) + (UNSPEC_BUILTIN_XCHG 94) + (UNSPEC_BUILTIN_SAVE 95) + (UNSPEC_BUILTIN_RSTR 96) + (UNSPEC_BUILTIN_MVFDC 97) + (UNSPEC_BUILTIN_MVTDC 98) + (UNSPEC_BUILTIN_MVFDR 99) + (UNSPEC_BUILTIN_BFMOV 100) + (UNSPEC_BUILTIN_BFMOVZ 101) (UNSPEC_PID_ADDR 52) (CTRLREG_PSW 0) @@ -85,6 +142,7 @@ (CTRLREG_ISP 10) (CTRLREG_FINTV 11) (CTRLREG_INTB 12) + (CTRLREG_EXTB 13) ] ) @@ -108,6 +166,10 @@ ;; These values were taken from tables 2.13 and 2.14 in section 2.8 ;; of the RX610 Group Hardware Manual v0.11 +;; The insn_group attribute consists of an enum, representing +;; the instruction issue group, as described in Renesas document +;; RXv2_pipeline_info_180112a.pdf + ;; Note - it would be nice to use strings rather than integers for ;; the possible values of this attribute, so that we can have the ;; gcc build mechanism check for values that are not supported by @@ -116,37 +178,39 @@ (define_attr "timings" "" (const_int 11)) +(define_attr "insn_group" "IEX,IEP,IML,IBC,IBR,IBS,ILS,ILSP,IFE,IFM,IF1,ISNG" (const_string "ISNG")) + (define_automaton "pipelining") -(define_cpu_unit "throughput" "pipelining") +(define_cpu_unit "throughput_pri,throughput_sec" "pipelining") (define_insn_reservation "throughput__1_latency__1" 1 - (eq_attr "timings" "11") "throughput") + (eq_attr "timings" "11") "throughput_pri|throughput_sec") (define_insn_reservation "throughput__1_latency__2" 2 - (eq_attr "timings" "12") "throughput,nothing") + (eq_attr "timings" "12") "throughput_pri|throughput_sec,nothing") (define_insn_reservation "throughput__2_latency__2" 1 - (eq_attr "timings" "22") "throughput*2") + (eq_attr "timings" "22") "throughput_pri*2|throughput_sec*2") (define_insn_reservation "throughput__3_latency__3" 1 - (eq_attr "timings" "33") "throughput*3") + (eq_attr "timings" "33") "throughput_pri*3|throughput_sec*3") (define_insn_reservation "throughput__3_latency__4" 2 - (eq_attr "timings" "34") "throughput*3,nothing") + (eq_attr "timings" "34") "throughput_pri*3|throughput_sec*3,nothing") (define_insn_reservation "throughput__4_latency__4" 1 - (eq_attr "timings" "44") "throughput*4") + (eq_attr "timings" "44") "throughput_pri*4|throughput_sec*4") (define_insn_reservation "throughput__4_latency__5" 2 - (eq_attr "timings" "45") "throughput*4,nothing") + (eq_attr "timings" "45") "throughput_pri*4|throughput_sec*4,nothing") (define_insn_reservation "throughput__5_latency__5" 1 - (eq_attr "timings" "55") "throughput*5") + (eq_attr "timings" "55") "throughput_pri*5|throughput_sec*5") (define_insn_reservation "throughput__5_latency__6" 2 - (eq_attr "timings" "56") "throughput*5,nothing") + (eq_attr "timings" "56") "throughput_pri*5|throughput_sec*5,nothing") (define_insn_reservation "throughput__6_latency__6" 1 - (eq_attr "timings" "66") "throughput*6") + (eq_attr "timings" "66") "throughput_pri*6|throughput_sec*6") (define_insn_reservation "throughput_10_latency_10" 1 - (eq_attr "timings" "1010") "throughput*10") + (eq_attr "timings" "1010") "throughput_pri*10|throughput_sec*10") (define_insn_reservation "throughput_11_latency_11" 1 - (eq_attr "timings" "1111") "throughput*11") + (eq_attr "timings" "1111") "throughput_pri*11|throughput_sec*11") (define_insn_reservation "throughput_16_latency_16" 1 - (eq_attr "timings" "1616") "throughput*16") + (eq_attr "timings" "1616") "throughput_pri*16|throughput_sec*16") (define_insn_reservation "throughput_18_latency_18" 1 - (eq_attr "timings" "1818") "throughput*18") + (eq_attr "timings" "1818") "throughput_pri*18|throughput_sec*18") ;; ---------------------------------------------------------------------------- @@ -163,18 +227,39 @@ (if_then_else (match_operator 0 "comparison_operator" [(match_operand:SI 1 "register_operand") - (match_operand:SI 2 "rx_source_operand")]) + (match_operand:SI 2 "rx_speed_source_operand")]) (label_ref (match_operand 3 "")) (pc)))] "" + " + operands[2] = rx_maybe_pidify_operand (operands[2], 1); + " ) +(define_insn_and_split "*cbranchsi4_mem" + [(set (pc) + (if_then_else + (match_operator 3 "comparison_operator" + [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_restricted_mem_operand" "Q")]) + (match_operand 2 "label_ref_operand" "") + (pc)))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + rx_split_cbranch (CCmode, GET_CODE (operands[3]), + operands[0], operands[1], operands[2]); + DONE; +}) + (define_insn_and_split "*cbranchsi4" [(set (pc) (if_then_else (match_operator 3 "comparison_operator" [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "rx_source_operand" "riQ")]) + (match_operand:SI 1 "rx_speed_source_operand" "ri")]) (match_operand 2 "label_ref_operand" "") (pc)))] "" @@ -187,23 +272,65 @@ DONE; }) -(define_insn "*cmpsi" +(define_expand "cmpsi" + [(set (reg:CC CC_REG) + (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r") + (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))] + "" + " + operands[1] = rx_maybe_pidify_operand (operands[1], 1); + " + ) + +(define_insn "*cmpsi_mem" + [(set (reg:CC CC_REG) + (compare:CC (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_restricted_mem_operand" "Q")))] + "reload_completed" + "cmp\t%Q1, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "cmpsi_internal" [(set (reg:CC CC_REG) - (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r") - (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))] + (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r") + (match_operand:SI 1 "rx_speed_source_operand" "r,Uint04,Int08,Sint16,Sint24,i")))] "reload_completed" "cmp\t%Q1, %0" - [(set_attr "timings" "11,11,11,11,11,11,33") - (set_attr "length" "2,2,3,4,5,6,5")] + [(set_attr "timings" "11,11,11,11,11,11") + (set_attr "length" "2,2,3,4,5,6") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX")] ) ;; Canonical method for representing TST. +(define_insn_and_split "*cbranchsi4_tst_mem" + [(set (pc) + (if_then_else + (match_operator 3 "rx_zs_comparison_operator" + [(and:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_restricted_mem_operand" "Q")) + (const_int 0)]) + (match_operand 2 "label_ref_operand" "") + (pc)))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]), + XEXP (operands[3], 0), XEXP (operands[3], 1), + operands[2]); + DONE; +}) + (define_insn_and_split "*cbranchsi4_tst" [(set (pc) (if_then_else (match_operator 3 "rx_zs_comparison_operator" [(and:SI (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "rx_source_operand" "riQ")) + (match_operand:SI 1 "rx_speed_source_operand" "ri")) (const_int 0)]) (match_operand 2 "label_ref_operand" "") (pc)))] @@ -249,16 +376,30 @@ DONE; }) +(define_insn "*tstsi_mem" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_restricted_mem_operand" "Q")) + (const_int 0)))] + "reload_completed" + "tst\t%Q1, %0" + [(set_attr "timings" "33") + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] +) + (define_insn "*tstsi" [(set (reg:CC_ZS CC_REG) (compare:CC_ZS - (and:SI (match_operand:SI 0 "register_operand" "r,r,r") - (match_operand:SI 1 "rx_source_operand" "r,i,Q")) + (and:SI (match_operand:SI 0 "register_operand" "r,r") + (match_operand:SI 1 "rx_speed_source_operand" "r,i")) (const_int 0)))] "reload_completed" "tst\t%Q1, %0" - [(set_attr "timings" "11,11,33") - (set_attr "length" "3,7,6")] + [(set_attr "timings" "11,11") + (set_attr "length" "3,7") + (set_attr "insn_group" "IEX,IEX")] ) (define_expand "cbranchsf4" @@ -266,18 +407,36 @@ (if_then_else (match_operator 0 "rx_fp_comparison_operator" [(match_operand:SF 1 "register_operand") - (match_operand:SF 2 "rx_source_operand")]) + (match_operand:SF 2 "rx_speed_source_operand")]) (label_ref (match_operand 3 "")) (pc)))] "ALLOW_RX_FPU_INSNS" ) +(define_insn_and_split "*cbranchsf4_mem" + [(set (pc) + (if_then_else + (match_operator 3 "rx_fp_comparison_operator" + [(match_operand:SF 0 "register_operand" "r") + (match_operand:SF 1 "rx_restricted_mem_operand" "Q")]) + (match_operand 2 "label_ref_operand" "") + (pc)))] + "ALLOW_RX_FPU_INSNS" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]), + operands[0], operands[1], operands[2]); + DONE; +}) + (define_insn_and_split "*cbranchsf4" [(set (pc) (if_then_else (match_operator 3 "rx_fp_comparison_operator" [(match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "rx_source_operand" "rFQ")]) + (match_operand:SF 1 "rx_speed_source_operand" "rF")]) (match_operand 2 "label_ref_operand" "") (pc)))] "ALLOW_RX_FPU_INSNS" @@ -290,15 +449,77 @@ DONE; }) +(define_insn "*cmpsf_mem" + [(set (reg:CC_F CC_REG) + (compare:CC_F + (match_operand:SF 0 "register_operand" "r") + (match_operand:SF 1 "rx_restricted_mem_operand" "Q")))] + "ALLOW_RX_FPU_INSNS && reload_completed" + "fcmp\t%1, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] +) + (define_insn "*cmpsf" [(set (reg:CC_F CC_REG) (compare:CC_F - (match_operand:SF 0 "register_operand" "r,r,r") - (match_operand:SF 1 "rx_source_operand" "r,F,Q")))] + (match_operand:SF 0 "register_operand" "r,r") + (match_operand:SF 1 "rx_speed_source_operand" "r,F")))] "ALLOW_RX_FPU_INSNS && reload_completed" "fcmp\t%1, %0" - [(set_attr "timings" "11,11,33") - (set_attr "length" "3,7,5")] + [(set_attr "timings" "11,11") + (set_attr "length" "3,7") + (set_attr "insn_group" "IF1,IF1")] +) + +(define_insn "cbranchdf4" + [(set (pc) + (if_then_else + (match_operator 0 "comparison_operator" + [(match_operand:DF 1 "register_operand" "DFPUreg") + (match_operand:DF 2 "register_operand" "DFPUreg")]) + (label_ref (match_operand 3 "")) + (pc)))] + "flag_dfpu" + { + switch(GET_CODE(operands[0])) + { + case ORDERED: + return "dcmpun\t%2, %1\n\tmvfdr\n\tbz\t%3"; + case UNORDERED: + return "dcmpun\t%2, %1\n\tmvfdr\n\tbnz\t%3"; + case EQ: + return "dcmpeq\t%2, %1\n\tmvfdr\n\tbz\t%3"; + case NE: + return "dcmpeq\t%2, %1\n\tmvfdr\n\tbnz\t%3"; + case LT: + return "dcmplt\t%2, %1\n\tmvfdr\n\tbz\t%3"; + case LE: + return "dcmple\t%2, %1\n\tmvfdr\n\tbz\t%3"; + case GT: + return "dcmplt\t%1, %2\n\tmvfdr\n\tbz\t%3"; + case GE: + return "dcmple\t%1, %2\n\tmvfdr\n\tbz\t%3"; + case UNEQ: + return "dcmpun\t%2, %1\n\tmvfdr\n\tbnz\t%3\n\tdcmpeq\t%2, %1\n\tmvfdr\n\tbz\t%3"; + case UNLT: + return "dcmpun\t%2, %1\n\tmvfdr\n\tbnz\t%3\n\tdcmplt\t%2, %1\n\tmvfdr\n\tbz\t%3"; + case UNLE: + return "dcmpun\t%2, %1\n\tmvfdr\n\tbnz\t%3\n\tdcmple\t%2, %1\n\tmvfdr\n\tbz\t%3"; + case UNGT: + return "dcmpun\t%2, %1\n\tmvfdr\n\tbnz\t%3\n\tdcmplt\t%1, %2\n\tmvfdr\n\tbz\t%3"; + case UNGE: + return "dcmpun\t%2, %1\n\tmvfdr\n\tbnz\t%3\n\tdcmple\t%1, %2\n\tmvfdr\n\tbz\t%3"; + case LTGT: + return "dcmplt\t%2, %1\n\tmvfdr\n\tbz\t%3\n\tdcmplt\t%1, %2\n\tmvfdr\n\tbz\t%3"; + default: + gcc_unreachable (); + } + } + [(set_attr "timings" "11") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] ) ;; Flow Control Instructions: @@ -314,7 +535,8 @@ "b%B1\t%0" [(set_attr "length" "8") ;; This length is wrong, but it is ;; too hard to compute statically. - (set_attr "timings" "33")] ;; The timing assumes that the branch is taken. + (set_attr "timings" "33") ;; The timing assumes that the branch is taken. + (set_attr "insn_group" "IBC")] ) ;; ---------------------------------------------------------------------------- @@ -325,7 +547,8 @@ "" "bra\t%0" [(set_attr "length" "4") - (set_attr "timings" "33")] + (set_attr "timings" "33") + (set_attr "insn_group" "IBR")] ) (define_insn "indirect_jump" @@ -334,7 +557,8 @@ "" "jmp\t%0" [(set_attr "length" "2") - (set_attr "timings" "33")] + (set_attr "timings" "33") + (set_attr "insn_group" "IBR")] ) (define_insn "tablejump" @@ -347,7 +571,8 @@ : "\n1:jmp\t%0"; } [(set_attr "timings" "33") - (set_attr "length" "2")] + (set_attr "length" "2") + (set_attr "insn_group" "IBR")] ) (define_expand "return" @@ -361,7 +586,8 @@ "" "rts" [(set_attr "length" "1") - (set_attr "timings" "55")] + (set_attr "timings" "55") + (set_attr "insn_group" "ISNG")] ) ;; Unspec used so that the constant will not be invalid @@ -374,7 +600,8 @@ "" "rtsd\t%0" [(set_attr "length" "2") - (set_attr "timings" "55")] + (set_attr "timings" "55") + (set_attr "insn_group" "ISNG")] ) (define_insn "pop_and_return" @@ -389,7 +616,8 @@ return ""; } [(set_attr "length" "3") - (set_attr "timings" "56")] + (set_attr "timings" "56") + (set_attr "insn_group" "ISNG")] ) (define_insn "fast_interrupt_return" @@ -397,7 +625,8 @@ "" "rtfi" [(set_attr "length" "2") - (set_attr "timings" "33")] + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] ) (define_insn "exception_return" @@ -405,7 +634,8 @@ "" "rte" [(set_attr "length" "2") - (set_attr "timings" "66")] + (set_attr "timings" "66") + (set_attr "insn_group" "ISNG")] ) (define_insn "naked_return" @@ -446,7 +676,8 @@ jsr\t%0 bsr\t%A0" [(set_attr "length" "2,4") - (set_attr "timings" "33")] + (set_attr "timings" "33") + (set_attr "insn_group" "IBS,IBS")] ) (define_expand "call_value" @@ -474,7 +705,8 @@ jsr\t%1 bsr\t%A1" [(set_attr "length" "2,4") - (set_attr "timings" "33")] + (set_attr "timings" "33") + (set_attr "insn_group" "IBS,IBS")] ) ;; Note - we do not allow indirect sibcalls (with the address @@ -503,7 +735,8 @@ "" "bra\t%A0" [(set_attr "length" "4") - (set_attr "timings" "33")] + (set_attr "timings" "33") + (set_attr "insn_group" "IBR")] ) (define_expand "sibcall_value" @@ -529,7 +762,8 @@ "" "bra\t%A1" [(set_attr "length" "4") - (set_attr "timings" "33")] + (set_attr "timings" "33") + (set_attr "insn_group" "IBR")] ) ;; Function Prologue/Epilogue Instructions @@ -594,13 +828,58 @@ (define_insn "*mov_internal" [(set (match_operand:register_modes - 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q,r") + 0 "nonimmediate_operand" "=r,r,r,r,r, r,r,r,r,r,Rreg,m, Q,Q,Q,Q,r,Q") (match_operand:register_modes - 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))] + 1 "general_operand" "Uint04,Int08,Sint16,Sint24,i, + r,Rreg,Rd05,Rd08,m,r,r, Int08,Sint16,Sint24,i,RpdaRpid,Q"))] "" { return rx_gen_move_template (operands, false); } - [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8") - (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")] + [(set_attr "length" "2,3,4,5,6, 2,2,2,3,4,2,6, 5,6,7,8,8,2") + (set_attr "timings" "11,11,11,11,11, 11,12,12,12,12,11,11, + 11,11,11,11,11,12") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,ILS,IEX,ILS,ILS,ILS,ILS,ILS,ILS,ISNG")] +) + +;TODO: instead of define_insn what if we use define_expand and/or define_insn_and_split and split the 32 bit movs +; after reload_completed? this is especially useful for case 6 below +(define_insn "movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "=DFPUreg,DFPUreg,Q,r,DFPUreg,DFPUreg,r") + (match_operand:DF 1 "general_operand" "DFPUreg,Q,DFPUreg,DFPUreg,r,DoubleC,r"))] + "flag_dfpu" + { + switch(which_alternative) + { + case 0: return "dmov.D\t%1, %0"; + case 1: return "dmov.D\t%1, %0"; + case 2: return "dmov.D\t%1, %0"; + case 3: + case 4: + return "dmov.L\t%L1, %L0\n\tdmov.L\t%H1, %H0"; + case 5: + { + long t[2]; + REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (operands[1]), t); + t[0] = WORDS_BIG_ENDIAN? t[1] : t[0]; + /* if the lower 32 bits are != 0 */ + if(t[0] != 0) + { + return "dmov.L\t%L1, %L0\n\tdmov.L\t%H1, %H0"; + } + else + { + return "dmov.D\t%H1, %H0"; + } + } + /* TODO: remove this at some point */ + case 6: if(REGNO(operands[1]) > REGNO(operands[0])) + return "mov.L\t%L1, %L0\n\tmov.L\t%H1, %H0"; + else + return "mov.L\t%H1, %H0\n\tmov.L\t%L1, %L0"; + } + } + [(set_attr "length" "2,4,4,4,4,4,4") + (set_attr "timings" "11,12,12,12,12,12,12") + (set_attr "insn_group" "ISNG,ISNG,ISNG,ISNG,ISNG,ISNG,ISNG")] ) (define_insn "extendsi2" @@ -610,7 +889,8 @@ "" { return rx_gen_move_template (operands, false); } [(set_attr "length" "2,6") - (set_attr "timings" "11,12")] + (set_attr "timings" "11,12") + (set_attr "insn_group" "IEX,ILS")] ) (define_insn "zero_extendsi2" @@ -620,7 +900,8 @@ "" { return rx_gen_move_template (operands, true); } [(set_attr "length" "2,4") - (set_attr "timings" "11,12")] + (set_attr "timings" "11,12") + (set_attr "insn_group" "IEX,ILS")] ) (define_insn "stack_push" @@ -631,7 +912,8 @@ (match_operand:SI 0 "register_operand" "r"))] "" "push.l\t%0" - [(set_attr "length" "2")] + [(set_attr "length" "2") + (set_attr "insn_group" "ILS")] ) (define_insn "stack_pushm" @@ -641,11 +923,23 @@ (match_operand:SI 0 "const_int_operand" "n")))])] "reload_completed" { - rx_emit_stack_pushm (operands); + rx_emit_stack_pushm (operands); return ""; } [(set_attr "length" "2") - (set_attr "timings" "44")] ;; The timing is a guesstimate average timing. + (set_attr "timings" "44") ;; The timing is a guesstimate average timing. + (set_attr "insn_group" "ISNG")] +) + +(define_insn "stack_dpushm" +[(set (reg:SI SP_REG) + (minus:SI (reg:SI SP_REG) + (const_int 4)))] + "" + "dpushm.l\tdcmr-dcmr" + + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] ) (define_insn "stack_pop" @@ -657,7 +951,8 @@ "" "pop\t%0" [(set_attr "length" "2") - (set_attr "timings" "12")] + (set_attr "timings" "12") + (set_attr "insn_group" "ILS")] ) (define_insn "stack_popm" @@ -671,14 +966,49 @@ return ""; } [(set_attr "length" "2") - (set_attr "timings" "45")] ;; The timing is a guesstimate average timing. + (set_attr "timings" "45") ;; The timing is a guesstimate average timing. + (set_attr "insn_group" "ISNG")] ) +(define_insn "stack_dpopm" + [(set (reg:SI SP_REG) + (plus:SI (reg:SI SP_REG) + (const_int 4)))] + "" + "dpopm.l\tdcmr-dcmr" + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] +) + +(define_insn_and_split "cstoresi4_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "rx_restricted_mem_operand" "Q")])) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + rtx flags, x; + + flags = gen_rtx_REG (CCmode, CC_REG); + x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]); + x = gen_rtx_SET (flags, x); + emit_insn (x); + + x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx); + x = gen_rtx_SET (operands[0], x); + emit_insn (x); + DONE; +}) + (define_insn_and_split "cstoresi4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "comparison_operator" [(match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "rx_source_operand" "riQ")])) + (match_operand:SI 3 "rx_speed_source_operand" "ri")])) (clobber (reg:CC CC_REG))] "" "#" @@ -704,14 +1034,38 @@ [(reg CC_REG) (const_int 0)]))] "reload_completed" "sc%B1.L\t%0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] ) +(define_insn_and_split "cstoresf4_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "rx_fp_comparison_operator" + [(match_operand:SF 2 "register_operand" "r") + (match_operand:SF 3 "rx_restricted_mem_operand" "Q")]))] + "ALLOW_RX_FPU_INSNS" + "#" + "reload_completed" + [(const_int 0)] +{ + rtx flags, x; + + flags = gen_rtx_REG (CC_Fmode, CC_REG); + x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]); + x = gen_rtx_SET (flags, x); + emit_insn (x); + + x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx); + x = gen_rtx_SET (operands[0], x); + emit_insn (x); + DONE; +}) + (define_insn_and_split "cstoresf4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "rx_fp_comparison_operator" [(match_operand:SF 2 "register_operand" "r") - (match_operand:SF 3 "rx_source_operand" "rFQ")]))] + (match_operand:SF 3 "rx_speed_source_operand" "rF")]))] "ALLOW_RX_FPU_INSNS" "#" "reload_completed" @@ -751,12 +1105,111 @@ FAIL; }) -(define_insn_and_split "*movsicc" +(define_insn_and_split "*movsicc_tst_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (if_then_else:SI + (match_operator 5 "rx_z_comparison_operator" + [(and:SI (match_operand:SI 3 "register_operand" "r") + (match_operand:SI 4 "rx_restricted_mem_operand" "Q")) + (const_int 0)]) + (match_operand:SI 1 "nonmemory_operand" "0") + (match_operand:SI 2 "immediate_operand" "i"))) + (clobber (reg:CC CC_REG))] + "CONSTANT_P (operands[1]) || CONSTANT_P (operands[2])" + "#" + "&& reload_completed" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_dup 3) + (match_dup 4)) + (const_int 0))) + (set (match_dup 0) + (if_then_else:SI + (match_dup 6) + (match_dup 1) + (match_dup 2))) + ] + { + rtx flags = gen_rtx_REG (CC_ZSmode, CC_REG); + operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[5]), CC_ZSmode, flags, const0_rtx); + } +) + +(define_insn_and_split "*movsicc_tst" + [(set (match_operand:SI 0 "register_operand" "=r") + (if_then_else:SI + (match_operator 5 "rx_z_comparison_operator" + [(and:SI (match_operand:SI 3 "register_operand" "r") + (match_operand:SI 4 "rx_speed_source_operand" "ri")) + (const_int 0)]) + (match_operand:SI 1 "nonmemory_operand" "0") + (match_operand:SI 2 "immediate_operand" "i"))) + (clobber (reg:CC CC_REG))] + "CONSTANT_P (operands[1]) || CONSTANT_P (operands[2])" + "#" + "&& reload_completed" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_dup 3) + (match_dup 4)) + (const_int 0))) + (set (match_dup 0) + (if_then_else:SI + (match_dup 6) + (match_dup 1) + (match_dup 2))) + ] + { + rtx flags = gen_rtx_REG (CC_ZSmode, CC_REG); + operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[5]), CC_ZSmode, flags, const0_rtx); + } +) + +(define_insn_and_split "*movsicc_tstz" + [(set (match_operand:SI 0 "register_operand" "=r") + (if_then_else:SI + (match_operator 6 "rx_z_comparison_operator" + [(zero_extract:SI (match_operand:SI 3 "register_operand" "r") + (match_operand:SI 4 "rx_constshift_operand" "i") + (match_operand:SI 5 "rx_constshift_operand" "i")) + (const_int 0)]) + (match_operand:SI 1 "nonmemory_operand" "0") + (match_operand:SI 2 "immediate_operand" "i"))) + (clobber (reg:CC CC_REG))] + "CONSTANT_P (operands[1]) || CONSTANT_P (operands[2])" + "#" + "&& reload_completed" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_dup 3) + (match_dup 7)) + (const_int 0))) + (set (match_dup 0) + (if_then_else:SI + (match_dup 8) + (match_dup 1) + (match_dup 2))) + ] + { + HOST_WIDE_INT mask; + rtx flags = gen_rtx_REG (CC_ZSmode, CC_REG); + + mask = 1; + mask <<= INTVAL (operands[4]); + mask -= 1; + mask <<= INTVAL (operands[5]); + + operands[7] = GEN_INT (mask); + operands[8] = gen_rtx_fmt_ee (GET_CODE (operands[6]), CC_ZSmode, flags, const0_rtx); + } +) + +(define_insn_and_split "*movsicc_mem" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (if_then_else:SI (match_operator 5 "comparison_operator" [(match_operand:SI 3 "register_operand" "r,r,r") - (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")]) + (match_operand:SI 4 "rx_restricted_mem_operand" "Q,Q,Q")]) (match_operand:SI 1 "nonmemory_operand" "i,ri,r") (match_operand:SI 2 "nonmemory_operand" "ri,i,r"))) (clobber (reg:CC CC_REG))] @@ -800,6 +1253,77 @@ DONE; }) +(define_insn_and_split "*movsicc" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (if_then_else:SI + (match_operator 5 "comparison_operator" + [(match_operand:SI 3 "register_operand" "r,r,r") + (match_operand:SI 4 "rx_speed_source_operand" "ri,ri,ri")]) + (match_operand:SI 1 "nonmemory_operand" "i,ri,r") + (match_operand:SI 2 "nonmemory_operand" "ri,i,r"))) + (clobber (reg:CC CC_REG))] + "(CONSTANT_P (operands[1]) || CONSTANT_P (operands[2])) || (REG_P(operands[1]) && REG_P(operands[2]))" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx x, flags, op0, op1, op2; + enum rtx_code cmp_code; + + flags = gen_rtx_REG (CCmode, CC_REG); + x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]); + emit_insn (gen_rtx_SET (flags, x)); + + cmp_code = GET_CODE (operands[5]); + op0 = operands[0]; + op1 = operands[1]; + op2 = operands[2]; + + /* If OP2 is the constant, reverse the sense of the move. */ + if ((!CONSTANT_P (operands[1]) && CONSTANT_P (operands[2])) + || (REG_P(operands[1]) && REG_P(operands[2]) + && rtx_equal_p (op0, op1))) + { + x = op1, op1 = op2, op2 = x; + cmp_code = reverse_condition (cmp_code); + } + + /* If OP2 does not match the output, copy it into place. We have allowed + these alternatives so that the destination can legitimately be one of + the comparison operands without increasing register pressure. */ + if (! rtx_equal_p (op0, op2)) + emit_move_insn (op0, op2); + + x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx); + x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0); + emit_insn (gen_rtx_SET (op0, x)); + DONE; +}) + +;; TODO: didn't add this because it's selected +;; comparing with the imm cases where the flow is: +;; cbranchsi4 -> cstoresi4 -> movsicc +;; for this case cbranchsi4 is not transformed to cstoresi4. +;; TODO: also *stcc_rev +;;(define_insn "*stcc" +;; [(set (match_operand:SI 0 "register_operand" "+r,r,r,r,r") +;; (if_then_else:SI +;; (match_operator 2 "rx_z_comparison_operator" +;; [(reg CC_REG) (const_int 0)]) +;; (match_operand:SI 1 "nonmemory_operand" "Sint08,Sint16,Sint24,i,RXV2") +;; (match_dup 0)))] +;; "reload_completed +;; && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))" +;; { +;; if (GET_CODE (operands[2]) == EQ) +;; return "stz\t%1, %0"; +;; else +;; return "stnz\t%1, %0"; +;; } +;; [(set_attr "length" "4,5,6,7,3") +;; (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX")] +;;) + (define_insn "*stcc" [(set (match_operand:SI 0 "register_operand" "+r,r,r,r") (if_then_else:SI @@ -815,7 +1339,8 @@ else return "stnz\t%1, %0"; } - [(set_attr "length" "4,5,6,7")] + [(set_attr "length" "4,5,6,7") + (set_attr "insn_group" "IEX,IEX,IEX,IEX")] ) (define_insn "*stcc_reg" @@ -831,7 +1356,26 @@ PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2]))); return "b%B2 1f\n\tmov %1, %0\n1:"; } - [(set_attr "length" "3,3,4,5,6,7")] + [(set_attr "length" "3,3,4,5,6,7") + (set_attr "insn_group" "ISNG,ISNG,ISNG,ISNG,ISNG,ISNG")] +) + +(define_insn "*stcc_rev" + [(set (match_operand:SI 0 "register_operand" "+r,r,r,r") + (if_then_else:SI + (match_operator 2 "rx_z_comparison_operator" + [(reg CC_REG) (const_int 0)]) + (match_dup 0) + (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")))] + "reload_completed" +{ + if (GET_CODE (operands[2]) == EQ) + return "stnz\t%1, %0"; + else + return "stz\t%1, %0"; +} + [(set_attr "length" "4,5,6,7") + (set_attr "insn_group" "IEX,IEX,IEX,IEX")] ) ;; Arithmetic Instructions @@ -844,7 +1388,18 @@ "@ abs\t%0 abs\t%1, %0" - [(set_attr "length" "2,3")] + [(set_attr "length" "2,3") + (set_attr "insn_group" "IEP,IEP")] +) + +(define_insn "absdf2" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (abs:DF (match_operand:DF 1 "register_operand" "DFPUreg"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "dabs\t%1, %0" + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] ) (define_insn "*abssi2_flags" @@ -860,7 +1415,8 @@ "@ abs\t%0 abs\t%1, %0" - [(set_attr "length" "2,3")] + [(set_attr "length" "2,3") + (set_attr "insn_group" "IEP,IEP")] ) (define_expand "addsi3" @@ -876,10 +1432,22 @@ " ) +(define_insn "addsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "" + "add\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] +) + (define_insn "addsi3_internal" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0") - (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q"))) + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r") + (match_operand:SI 2 "rx_speed_source_operand" "rQ,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i"))) (clobber (reg:CC CC_REG))] "" "@ @@ -895,18 +1463,32 @@ add\t%2, %1, %0 add\t%2, %1, %0 add\t%2, %1, %0 - add\t%2, %1, %0 - add\t%Q2, %0" - [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33") - (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")] + add\t%2, %1, %0" + [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11") + (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX")] +) + +(define_insn "*addsi3_flags_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (set (reg CC_REG) + (compare (plus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "add\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) (define_insn "*addsi3_flags" [(set (reg CC_REG) - (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0") - (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")) + (compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r") + (match_operand:SI 2 "rx_speed_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r") + (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r") (plus:SI (match_dup 1) (match_dup 2)))] "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" "@ @@ -922,10 +1504,10 @@ add\t%2, %1, %0 add\t%2, %1, %0 add\t%2, %1, %0 - add\t%2, %1, %0 - add\t%Q2, %0" - [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33") - (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")] + add\t%2, %1, %0" + [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11") + (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX")] ) ;; A helper to expand the above with the CC_MODE filled in. @@ -933,36 +1515,74 @@ [(parallel [(set (reg:CC_ZSC CC_REG) (compare:CC_ZSC (plus:SI (match_operand:SI 1 "register_operand") - (match_operand:SI 2 "rx_source_operand")) + (match_operand:SI 2 "rx_speed_source_operand")) (const_int 0))) (set (match_operand:SI 0 "register_operand") (plus:SI (match_dup 1) (match_dup 2)))])] ) +(define_insn "adc_internal_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_operand:SI 1 "register_operand" "%0")) + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "reload_completed" + "adc %2,%0" + [(set_attr "timings" "33") + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] +) + (define_insn "adc_internal" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") (plus:SI (plus:SI (ltu:SI (reg:CC CC_REG) (const_int 0)) - (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")) - (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + (match_operand:SI 1 "register_operand" "%0,0,0,0,0")) + (match_operand:SI 2 "rx_speed_source_operand" "r,Sint08,Sint16,Sint24,i"))) (clobber (reg:CC CC_REG))] "reload_completed" "adc\t%2, %0" - [(set_attr "timings" "11,11,11,11,11,33") - (set_attr "length" "3,4,5,6,7,6")] + [(set_attr "timings" "11,11,11,11,11") + (set_attr "length" "3,4,5,6,7") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX")] ) +(define_insn "*adc_flags_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_operand:SI 1 "register_operand" "%0")) + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (set (reg CC_REG) + (compare + (plus:SI + (plus:SI + (ltu:SI (reg:CC CC_REG) (const_int 0)) + (match_dup 1)) + (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + "adc %2,%0" + [(set_attr "timings" "33") + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] + ) + (define_insn "*adc_flags" [(set (reg CC_REG) (compare (plus:SI (plus:SI (ltu:SI (reg:CC CC_REG) (const_int 0)) - (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")) - (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")) + (match_operand:SI 1 "register_operand" "%0,0,0,0,0")) + (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") + (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") (plus:SI (plus:SI (ltu:SI (reg:CC CC_REG) (const_int 0)) @@ -970,8 +1590,9 @@ (match_dup 2)))] "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" "adc\t%2, %0" - [(set_attr "timings" "11,11,11,11,11,33") - (set_attr "length" "3,4,5,6,7,6")] + [(set_attr "timings" "11,11,11,11,11") + (set_attr "length" "3,4,5,6,7") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX")] ) ;; Peepholes to match: @@ -1010,7 +1631,7 @@ (define_expand "adddi3" [(set (match_operand:DI 0 "register_operand") (plus:DI (match_operand:DI 1 "register_operand") - (match_operand:DI 2 "rx_source_operand")))] + (match_operand:DI 2 "nonmemory_operand")))] "" { rtx op0l, op0h, op1l, op1h, op2l, op2h; @@ -1094,10 +1715,22 @@ DONE; }) +(define_insn "andsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "" + "and\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] +) + (define_insn_and_split "andsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") - (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") - (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") + (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r") + (match_operand:SI 2 "rx_speed_source_operand" "rQ,Uint04,Sint08,Sint16,Sint24,i,0,r"))) (clobber (reg:CC CC_REG))] "" "@ @@ -1108,8 +1741,7 @@ and\t%2, %0 and\t%2, %0 and\t%1, %0 - and\t%2, %1, %0 - and\t%Q2, %0" + and\t%2, %1, %0" "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2]) && pow2p_hwi (~UINTVAL (operands[2]))" [(const_int 0)] @@ -1120,21 +1752,36 @@ FAIL; rx_copy_reg_dead_or_unused_notes (operands[1], curr_insn, - emit_insn (gen_bitclr (operands[0], + emit_insn (gen_bclr (operands[0], GEN_INT (exact_log2 (~UINTVAL (operands[2]))), operands[1]))); DONE; } - [(set_attr "timings" "11,11,11,11,11,11,11,11,33") - (set_attr "length" "2,2,3,4,5,6,2,5,5")] + [(set_attr "timings" "11,11,11,11,11,11,11,11") + (set_attr "length" "2,2,3,4,5,6,2,5") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX")] +) + +(define_insn "*andsi3_flags_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (set (reg CC_REG) + (compare (and:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + "and\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) (define_insn "*andsi3_flags" [(set (reg CC_REG) - (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") - (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")) + (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r") + (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r")) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") + (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") (and:SI (match_dup 1) (match_dup 2)))] "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ @@ -1145,10 +1792,10 @@ and\t%2, %0 and\t%2, %0 and\t%1, %0 - and\t%2, %1, %0 - and\t%Q2, %0" - [(set_attr "timings" "11,11,11,11,11,11,11,11,33") - (set_attr "length" "2,2,3,4,5,6,2,5,5")] + and\t%2, %1, %0" + [(set_attr "timings" "11,11,11,11,11,11,11,11") + (set_attr "length" "2,2,3,4,5,6,2,5") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX")] ) ;; Byte swap (single 32-bit value). @@ -1157,7 +1804,8 @@ (bswap:SI (match_operand:SI 1 "register_operand" "r")))] "" "revl\t%1, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEP")] ) ;; Byte swap (single 16-bit value). Note - we ignore the swapping of the high 16-bits. @@ -1166,31 +1814,59 @@ (bswap:HI (match_operand:HI 1 "register_operand" "r")))] "" "revw\t%1, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEP")] ) +(define_insn "divsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (div:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "(optimize_size || reload_completed)" + "div\t%Q2, %0" + [(set_attr "timings" "1111") ;; Strictly speaking the timing should be + ;; 2222, but that is a worst case sceanario. + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] +) (define_insn "divsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") - (div:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0") - (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") + (div:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0") + (match_operand:SI 2 "rx_speed_source_operand" "r,Sint08,Sint16,Sint24,i"))) (clobber (reg:CC CC_REG))] "" "div\t%Q2, %0" [(set_attr "timings" "1111") ;; Strictly speaking the timing should be ;; 2222, but that is a worst case sceanario. - (set_attr "length" "3,4,5,6,7,6")] + (set_attr "length" "3,4,5,6,7") + (set_attr "insn_group" "ISNG,ISNG,ISNG,ISNG,ISNG")] +) + +(define_insn "udivsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (udiv:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "(optimize_size || reload_completed)" + "divu\t%Q2, %0" + [(set_attr "timings" "1010") ;; Strictly speaking the timing should be + ;; 2020, but that is a worst case sceanario. + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] ) (define_insn "udivsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") - (udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0") - (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") + (udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0") + (match_operand:SI 2 "rx_speed_source_operand" "r,Sint08,Sint16,Sint24,i"))) (clobber (reg:CC CC_REG))] "" "divu\t%Q2, %0" [(set_attr "timings" "1010") ;; Strictly speaking the timing should be ;; 2020, but that is a worst case sceanario. - (set_attr "length" "3,4,5,6,7,6")] + (set_attr "length" "3,4,5,6,7") + (set_attr "insn_group" "ISNG,ISNG,ISNG,ISNG,ISNG")] ) ;; Note - these patterns are suppressed in big-endian mode because they @@ -1198,141 +1874,168 @@ ;; result is placed in the higher numbered register of the destination ;; register pair. +(define_insn "mulsidi3_mem" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (sign_extend:DI (match_operand:SI + 1 "register_operand" "%0")) + (sign_extend:DI (match_operand:SI + 2 "rx_restricted_mem_operand" "Q"))))] + "(optimize_size || reload_completed) && ! TARGET_BIG_ENDIAN_DATA" + "emul\t%Q2, %0" + [(set_attr "length" "6") + (set_attr "timings" "44") + (set_attr "insn_group" "ISNG")] +) + (define_insn "mulsidi3" - [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r") + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r") (mult:DI (sign_extend:DI (match_operand:SI - 1 "register_operand" "%0,0,0,0,0,0")) + 1 "register_operand" "%0,0,0,0,0")) (sign_extend:DI (match_operand:SI - 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q"))))] + 2 "rx_speed_source_operand" + "r,Sint08,Sint16,Sint24,i"))))] "! TARGET_BIG_ENDIAN_DATA" "emul\t%Q2, %0" - [(set_attr "length" "3,4,5,6,7,6") - (set_attr "timings" "22,22,22,22,22,44")] + [(set_attr "length" "3,4,5,6,7") + (set_attr "timings" "22,22,22,22,22") + (set_attr "insn_group" "ISNG,ISNG,ISNG,ISNG,ISNG")] ) ;; See comment for mulsidi3. ;; Note - the zero_extends are to distinguish this pattern from the ;; mulsidi3 pattern. Immediate mode addressing is not supported ;; because gcc cannot handle the expression: (zero_extend (const_int)). +(define_insn "umulsidi3_mem" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) + (zero_extend:DI (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))))] + "(optimize_size || reload_completed) && ! TARGET_BIG_ENDIAN_DATA" + "emulu\t%Q2, %0" + [(set_attr "length" "6") + (set_attr "timings" "44") + (set_attr "insn_group" "ISNG")] +) + (define_insn "umulsidi3" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,0")) - (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))] + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) + (zero_extend:DI (match_operand:SI 2 "rx_speed_compare_operand" "r"))))] "! TARGET_BIG_ENDIAN_DATA" "emulu\t%Q2, %0" - [(set_attr "length" "3,6") - (set_attr "timings" "22,44")] + [(set_attr "length" "3") + (set_attr "timings" "22") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "smaxsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (smax:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q")))] + "(optimize_size || reload_completed)" + "max\t%Q2, %0" + [(set_attr "length" "6") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] ) (define_insn "smaxsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") - (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") - (match_operand:SI 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q")))] + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") + (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0") + (match_operand:SI 2 "rx_speed_source_operand" + "r,Sint08,Sint16,Sint24,i")))] "" "max\t%Q2, %0" - [(set_attr "length" "3,4,5,6,7,6") - (set_attr "timings" "11,11,11,11,11,33")] + [(set_attr "length" "3,4,5,6,7") + (set_attr "timings" "11,11,11,11,11") + (set_attr "insn_group" "IEP,IEP,IEP,IEP,IEP")] +) + +(define_insn "sminsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (smin:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q")))] + "(optimize_size || reload_completed)" + "min\t%Q2, %0" + [(set_attr "length" "6") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] ) (define_insn "sminsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") - (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") - (match_operand:SI 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q")))] + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") + (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0") + (match_operand:SI 2 "rx_speed_source_operand" + "r,Sint08,Sint16,Sint24,i")))] "" "min\t%Q2, %0" - [(set_attr "length" "3,4,5,6,7,6") - (set_attr "timings" "11,11,11,11,11,33")] + [(set_attr "length" "3,4,5,6,7") + (set_attr "timings" "11,11,11,11,11") + (set_attr "insn_group" "IEP,IEP,IEP,IEP,IEP")] ) -(define_insn "umax3_u" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") - (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") - (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand" - "r,Sint08,Sint16,Sint24,i,Q"))))] + +; Need to search for this patch +(define_insn "unsign_maxqi3_mem" + [(set (match_operand:QI 0 "register_operand" "=r") + (umax:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "rx_restricted_mem_operand" "Q")))] "" - "max\t%R2, %0" - [(set_attr "length" "3,4,5,6,7,6") - (set_attr "timings" "11,11,11,11,11,33")] + "movu.B\t%0, %0\n\tmax\t%R2, %0" + [(set_attr "length" "8") + (set_attr "timings" "44") + (set_attr "insn_group" "ISNG")] ) -(define_insn "umin3_ur" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") - (smin:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand" - "r,Sint08,Sint16,Sint24,i,Q")) - (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))] +(define_insn "unsign_maxhi3_mem" + [(set (match_operand:HI 0 "register_operand" "=r") + (umax:HI (match_operand:HI 1 "register_operand" "%0") + (match_operand:HI 2 "rx_restricted_mem_operand" "Q")))] "" - "min\t%R2, %0" - [(set_attr "length" "3,4,5,6,7,6") - (set_attr "timings" "11,11,11,11,11,33")] + "movu.W\t%0, %0\n\tmax\t%R2, %0" + [(set_attr "length" "8") + (set_attr "timings" "44") + (set_attr "insn_group" "ISNG")] ) -(define_insn "umax3_ur" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") - (smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand" - "r,Sint08,Sint16,Sint24,i,Q")) - (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))] +(define_insn "unsign_minhi3_mem" + [(set (match_operand:HI 0 "register_operand" "=r") + (umin:HI (match_operand:HI 1 "register_operand" "%0") + (match_operand:HI 2 "rx_restricted_mem_operand" "Q")))] "" - "max\t%R2, %0" - [(set_attr "length" "3,4,5,6,7,6") - (set_attr "timings" "11,11,11,11,11,33")] + "movu.W\t%0, %0\n\tmin\t%R2, %0" + [(set_attr "length" "8") + (set_attr "timings" "44") + (set_attr "insn_group" "ISNG")] ) -(define_expand "umax3" - [(set (match_dup 4) - (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0"))) - (set (match_dup 3) - (smax:SI (match_dup 4) - (match_operand:small_int_modes 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q"))) - (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r") - (match_dup 6)) - ] + +(define_insn "unsign_minqi3_mem" + [(set (match_operand:QI 0 "register_operand" "=r") + (umin:QI (match_operand:QI 1 "register_operand" "%0") + (match_operand:QI 2 "rx_restricted_mem_operand" "Q")))] "" - "operands[3] = gen_reg_rtx (SImode); - operands[4] = gen_reg_rtx (SImode); - operands[5] = gen_reg_rtx (SImode); - operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3], - TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0); - if (GET_CODE (operands[2]) != CONST_INT) - { - emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2])); - operands[2] = operands[5]; - } - " + "movu.B\t%0, %0\n\tmin\t%R2, %0" + [(set_attr "length" "8") + (set_attr "timings" "44") + (set_attr "insn_group" "ISNG")] ) -(define_expand "umin3" - [(set (match_dup 4) - (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0"))) - (set (match_dup 3) - (smin:SI (match_dup 4) - (match_operand:small_int_modes 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q"))) - (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r") - (match_dup 6)) - ] - "" - "operands[3] = gen_reg_rtx (SImode); - operands[4] = gen_reg_rtx (SImode); - operands[5] = gen_reg_rtx (SImode); - operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3], - TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0); - if (GET_CODE (operands[2]) != CONST_INT) - { - emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2])); - operands[2] = operands[5]; - } - " +(define_insn "mulsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (mult:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q")))] + "(optimize_size || reload_completed)" + "mul\t%Q2, %0" + [(set_attr "length" "5") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] ) (define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") - (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r") - (match_operand:SI 2 "rx_source_operand" - "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))] + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") + (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r") + (match_operand:SI 2 "rx_speed_source_operand" + "r,Uint04,Sint08,Sint16,Sint24,i,0,r")))] "" "@ mul\t%2, %0 @@ -1341,11 +2044,11 @@ mul\t%2, %0 mul\t%2, %0 mul\t%Q2, %0 - mul\t%Q2, %0 mul\t%1, %0 mul\t%2, %1, %0" - [(set_attr "length" "2,2,3,4,5,6,5,2,3") - (set_attr "timings" "11,11,11,11,11,11,33,11,11")] + [(set_attr "length" "2,2,3,4,5,6,2,3") + (set_attr "timings" "11,11,11,11,11,11,11,11") + (set_attr "insn_group" "IML,IML,IML,IML,IML,IML,IML,IML")] ) (define_insn "negsi2" @@ -1356,7 +2059,28 @@ "@ neg\t%0 neg\t%1, %0" - [(set_attr "length" "2,3")] + [(set_attr "length" "2,3") + (set_attr "insn_group" "IEX,IEX")] +) + +(define_insn "negdf2" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (neg:DF (match_operand:DF 1 "register_operand" "DFPUreg"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "dneg\t%1, %0" + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "negsf2" + [(set (match_operand:SF 0 "register_operand" "=r") + (neg:SF (match_operand:SF 1 "register_operand" "r"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "add\t#-2147483648, %1" + [(set_attr "length" "6") + (set_attr "insn_group" "IEX")] ) ;; Note that the O and C flags are not set as per a normal compare, @@ -1371,7 +2095,8 @@ "@ neg\t%0 neg\t%1, %0" - [(set_attr "length" "2,3")] + [(set_attr "length" "2,3") + (set_attr "insn_group" "IEX,IEX")] ) (define_insn "one_cmplsi2" @@ -1382,7 +2107,8 @@ "@ not\t%0 not\t%1, %0" - [(set_attr "length" "2,3")] + [(set_attr "length" "2,3") + (set_attr "insn_group" "IEX,IEX")] ) (define_insn "*one_cmplsi2_flags" @@ -1395,13 +2121,27 @@ "@ not\t%0 not\t%1, %0" - [(set_attr "length" "2,3")] + [(set_attr "length" "2,3") + (set_attr "insn_group" "IEX,IEX")] +) + +(define_insn "iorsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "" + " + or\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) (define_insn_and_split "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") - (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") - (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r") + (match_operand:SI 2 "rx_speed_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r"))) (clobber (reg:CC CC_REG))] "" "@ @@ -1412,8 +2152,7 @@ or\t%2, %0 or\t%Q2, %0 or\t%1, %0 - or\t%2, %1, %0 - or\t%Q2, %0" + or\t%2, %1, %0" "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2]) && pow2p_hwi (UINTVAL (operands[2]))" [(const_int 0)] @@ -1429,17 +2168,33 @@ operands[1]))); DONE; } - [(set_attr "timings" "11,11,11,11,11,11,11,11,33") - (set_attr "length" "2,2,3,4,5,6,2,3,5")] + [(set_attr "timings" "11,11,11,11,11,11,11,11") + (set_attr "length" "2,2,3,4,5,6,2,3") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX")] +) + +(define_insn "*iorsi3_flags_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (set (reg CC_REG) + (compare (ior:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" + " + or\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) (define_insn "*iorsi3_flags" - [(set (reg CC_REG) - (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") - (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")) - (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") - (ior:SI (match_dup 1) (match_dup 2)))] + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r") + (match_operand:SI 2 "rx_speed_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r"))) + (set (reg CC_REG) + (compare (ior:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" "@ or\t%2, %0 @@ -1449,10 +2204,10 @@ or\t%2, %0 or\t%Q2, %0 or\t%1, %0 - or\t%2, %1, %0 - or\t%Q2, %0" - [(set_attr "timings" "11,11,11,11,11,11,11,11,33") - (set_attr "length" "2,2,3,4,5,6,2,3,5")] + or\t%2, %1, %0" + [(set_attr "timings" "11,11,11,11,11,11,11,11") + (set_attr "length" "2,2,3,4,5,6,2,3") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,IEX,IEX,IEX,IEX")] ) (define_insn "rotlsi3" @@ -1462,7 +2217,8 @@ (clobber (reg:CC CC_REG))] "" "rotl\t%2, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEP")] ) (define_insn "*rotlsi3_flags" @@ -1474,7 +2230,8 @@ (rotate:SI (match_dup 1) (match_dup 2)))] "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" "rotl\t%2, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEP")] ) (define_insn "rotrsi3" @@ -1484,7 +2241,8 @@ (clobber (reg:CC CC_REG))] "" "rotr\t%2, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEP")] ) (define_insn "*rotrsi3_flags" @@ -1496,7 +2254,8 @@ (rotatert:SI (match_dup 1) (match_dup 2)))] "reload_completed && rx_match_ccmode (insn, CC_ZSmode)" "rotr\t%2, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEP")] ) (define_insn "ashrsi3" @@ -1509,7 +2268,8 @@ shar\t%2, %0 shar\t%2, %0 shar\t%2, %1, %0" - [(set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3") + (set_attr "insn_group" "IEX,IEX,IEX")] ) (define_insn "*ashrsi3_flags" @@ -1524,7 +2284,8 @@ shar\t%2, %0 shar\t%2, %0 shar\t%2, %1, %0" - [(set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3") + (set_attr "insn_group" "IEX,IEX,IEX")] ) (define_insn "lshrsi3" @@ -1537,7 +2298,8 @@ shlr\t%2, %0 shlr\t%2, %0 shlr\t%2, %1, %0" - [(set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3") + (set_attr "insn_group" "IEX,IEX,IEX")] ) (define_insn "*lshrsi3_flags" @@ -1552,7 +2314,8 @@ shlr\t%2, %0 shlr\t%2, %0 shlr\t%2, %1, %0" - [(set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3") + (set_attr "insn_group" "IEX,IEX,IEX")] ) (define_insn "ashlsi3" @@ -1565,7 +2328,8 @@ shll\t%2, %0 shll\t%2, %0 shll\t%2, %1, %0" - [(set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3") + (set_attr "insn_group" "IEX,IEX,IEX")] ) (define_insn "*ashlsi3_flags" @@ -1580,14 +2344,35 @@ shll\t%2, %0 shll\t%2, %0 shll\t%2, %1, %0" - [(set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3") + (set_attr "insn_group" "IEX,IEX,IEX")] ) ;; Saturate to 32-bits +(define_insn_and_split "ssaddsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (ss_plus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) + (plus:SI (match_dup 1) (match_dup 2))) + (set (reg:CC_ZSC CC_REG) + (compare:CC_ZSC + (plus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))]) + (set (match_dup 0) + (unspec:SI [(match_dup 0) (reg:CC CC_REG)] + UNSPEC_BUILTIN_SAT))] + "" +) + (define_insn_and_split "ssaddsi3" [(set (match_operand:SI 0 "register_operand" "=r") (ss_plus:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "rx_source_operand" "riQ"))) + (match_operand:SI 2 "rx_speed_source_operand" "ri"))) (clobber (reg:CC CC_REG))] "" "#" @@ -1599,7 +2384,7 @@ (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]) (set (match_dup 0) - (unspec:SI [(match_dup 0) (reg:CC CC_REG)] + (unspec:SI [(match_dup 0) (reg:CC CC_REG)] UNSPEC_BUILTIN_SAT))] "" ) @@ -1611,27 +2396,56 @@ UNSPEC_BUILTIN_SAT))] "reload_completed" "sat\t%0" - [(set_attr "length" "2")] + [(set_attr "length" "2") + (set_attr "insn_group" "IEP")] +) + +(define_insn "subsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "(optimize_size || reload_completed)" + " + sub\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) (define_insn "subsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r") - (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0") - (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q"))) + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r") + (match_operand:SI 2 "rx_speed_source_operand" "r,Uint04,n,r"))) (clobber (reg:CC CC_REG))] "" "@ sub\t%2, %0 sub\t%2, %0 add\t%N2, %0 - sub\t%2, %1, %0 - sub\t%Q2, %0" - [(set_attr "timings" "11,11,11,11,33") - (set_attr "length" "2,2,6,3,5")] + sub\t%2, %1, %0" + [(set_attr "timings" "11,11,11,11") + (set_attr "length" "2,2,6,3") + (set_attr "insn_group" "IEX,IEX,IEX,IEX")] ) ;; Note that the O flag is set as if (compare op1 op2) not for ;; what is described here, (compare op0 0). +(define_insn "*subsi3_flags_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "rx_restricted_mem_operand" "m"))) + (set (reg CC_REG) + (compare (minus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] + "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)" + " + sub\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] +) + (define_insn "*subsi3_flags" [(set (reg CC_REG) (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0") @@ -1647,7 +2461,8 @@ sub\t%2, %1, %0 sub\t%Q2, %0" [(set_attr "timings" "11,11,11,11,33") - (set_attr "length" "2,2,6,3,5")] + (set_attr "length" "2,2,6,3,5") + (set_attr "insn_group" "IEX,IEX,IEX,IEX,ISNG")] ) ;; A helper to expand the above with the CC_MODE filled in. @@ -1661,18 +2476,54 @@ (minus:SI (match_dup 1) (match_dup 2)))])] ) +(define_insn "sbb_internal_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI + (minus:SI + (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q")) + (geu:SI (reg:CC CC_REG) (const_int 0)))) + (clobber (reg:CC CC_REG))] + "reload_completed" + "sbb\t%2, %0" + [(set_attr "timings" "33") + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] +) + (define_insn "sbb_internal" - [(set (match_operand:SI 0 "register_operand" "=r,r") + [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (minus:SI - (match_operand:SI 1 "register_operand" " 0,0") - (match_operand:SI 2 "rx_compare_operand" " r,Q")) + (match_operand:SI 1 "register_operand" " 0") + (match_operand:SI 2 "rx_speed_compare_operand" " r")) (geu:SI (reg:CC CC_REG) (const_int 0)))) (clobber (reg:CC CC_REG))] "reload_completed" "sbb\t%2, %0" - [(set_attr "timings" "11,33") - (set_attr "length" "3,6")] + [(set_attr "timings" "11") + (set_attr "length" "3") + (set_attr "insn_group" "IEX")] +) + +(define_insn "*sbb_flags_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI + (minus:SI + (match_operand:SI 1 "register_operand" " 0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q")) + (geu:SI (reg:CC CC_REG) (const_int 0)))) + (set (reg CC_REG) + (compare + (minus:SI + (minus:SI (match_dup 1) (match_dup 2)) + (geu:SI (reg:CC CC_REG) (const_int 0))) + (const_int 0)))] + "reload_completed" + "sbb\t%2, %0" + [(set_attr "timings" "33") + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] ) (define_insn "*sbb_flags" @@ -1680,18 +2531,19 @@ (compare (minus:SI (minus:SI - (match_operand:SI 1 "register_operand" " 0,0") - (match_operand:SI 2 "rx_compare_operand" " r,Q")) + (match_operand:SI 1 "register_operand" " 0") + (match_operand:SI 2 "rx_compare_operand" " r")) (geu:SI (reg:CC CC_REG) (const_int 0))) (const_int 0))) - (set (match_operand:SI 0 "register_operand" "=r,r") + (set (match_operand:SI 0 "register_operand" "=r") (minus:SI (minus:SI (match_dup 1) (match_dup 2)) (geu:SI (reg:CC CC_REG) (const_int 0))))] "reload_completed" "sbb\t%2, %0" - [(set_attr "timings" "11,33") - (set_attr "length" "3,6")] + [(set_attr "timings" "11") + (set_attr "length" "3") + (set_attr "insn_group" "IEX")] ) (define_expand "subdi3" @@ -1713,15 +2565,57 @@ DONE; }) +(define_insn_and_split "subdi3_internal_mem" + [(set (match_operand:SI 0 "register_operand" "=&r") + (minus:SI (match_operand:SI 2 "register_operand" "0") + (match_operand:SI 3 "rx_restricted_mem_operand" "Q"))) + (set (match_operand:SI 1 "register_operand" "=r") + (minus:SI + (minus:SI + (match_operand:SI 4 "register_operand" "1") + (match_operand:SI 5 "rx_restricted_mem_operand" " Q")) + (gtu:SI (match_dup 3) (match_dup 2)))) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3])); + emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5])); + DONE; +}) + +(define_insn_and_split "subdi3_internal_mem2" + [(set (match_operand:SI 0 "register_operand" "=&r") + (minus:SI (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r"))) + (set (match_operand:SI 1 "register_operand" "=r") + (minus:SI + (minus:SI + (match_operand:SI 4 "register_operand" "1") + (match_operand:SI 5 "rx_restricted_mem_operand" "Q")) + (gtu:SI (match_dup 3) (match_dup 2)))) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3])); + emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5])); + DONE; +}) + (define_insn_and_split "subdi3_internal" [(set (match_operand:SI 0 "register_operand" "=&r,&r") (minus:SI (match_operand:SI 2 "register_operand" " 0, r") - (match_operand:SI 3 "rx_compare_operand" "rQ, r"))) + (match_operand:SI 3 "rx_speed_compare_operand" "r, r"))) (set (match_operand:SI 1 "register_operand" "= r, r") (minus:SI (minus:SI (match_operand:SI 4 "register_operand" " 1, 1") - (match_operand:SI 5 "rx_compare_operand" " rQ,rQ")) + (match_operand:SI 5 "rx_speed_compare_operand" " r,r")) (gtu:SI (match_dup 3) (match_dup 2)))) (clobber (reg:CC CC_REG))] "" @@ -1734,6 +2628,19 @@ DONE; }) +(define_insn "xorsi3_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (xor:SI (match_operand:SI 1 "register_operand" "%0") + (match_operand:SI 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "(optimize_size || reload_completed)" + "xor\t%Q2, %0" + [(set_attr "timings" "33") + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] +) + + (define_insn_and_split "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") @@ -1862,7 +2769,8 @@ "(optimize < 3 || optimize_size)" "\t%2, %0" [(set_attr "timings" "33") - (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length + (set_attr "length" "5") ;; This length is corrected in rx_adjust_insn_length + (set_attr "insn_group" "ISNG")] ) (define_insn "si3_" @@ -1873,7 +2781,8 @@ "(optimize < 3 || optimize_size)" "\t%2, %0" [(set_attr "timings" "33") - (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length + (set_attr "length" "5") ;; This length is corrected in rx_adjust_insn_length + (set_attr "insn_group" "ISNG")] ) (define_insn "si3_" @@ -1883,7 +2792,8 @@ "(optimize < 3 || optimize_size)" "\t%2, %0" [(set_attr "timings" "33") - (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length + (set_attr "length" "5") ;; This length is corrected in rx_adjust_insn_length + (set_attr "insn_group" "ISNG")] ) (define_peephole2 @@ -1934,76 +2844,410 @@ "(optimize < 3 || optimize_size)" "cmp\t%1, %0" [(set_attr "timings" "33") - (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length + (set_attr "length" "5") ;; This length is corrected in rx_adjust_insn_length + (set_attr "insn_group" "ISNG")] ) ;; Floating Point Instructions -(define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=r,r,r") - (plus:SF (match_operand:SF 1 "register_operand" "%0,0,0") - (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) +(define_insn "addsf3_mem" + [(set (match_operand:SF 0 "register_operand" "=r") + (plus:SF (match_operand:SF 1 "register_operand" "%0") + (match_operand:SF 2 "rx_restricted_mem_operand" "Q"))) (clobber (reg:CC CC_REG))] - "ALLOW_RX_FPU_INSNS" + "ALLOW_RX_FPU_INSNS && (optimize_size || reload_completed)" "fadd\t%2, %0" - [(set_attr "timings" "44,44,66") - (set_attr "length" "3,7,5")] + [(set_attr "timings" "66") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) -(define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=r,r,r") - (div:SF (match_operand:SF 1 "register_operand" "0,0,0") - (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) +(define_expand "addsf3" + [(set (match_operand:SF 0 "register_operand") + (plus:SF (match_operand:SF 1 "register_operand" ) + (match_operand:SF 2 "rx_speed_source_operand"))) (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" + { + if(TARGET_RXV2) + emit_insn(gen_addsf3v2(operands[0], operands[1], operands[2])); + else + emit_insn(gen_addsf3v1(operands[0], operands[1], operands[2])); + DONE; + } + ) + +(define_insn "addsf3v1" + [(set (match_operand:SF 0 "register_operand" "=r,r") + (plus:SF (match_operand:SF 1 "register_operand" "%0,0") + (match_operand:SF 2 "rx_speed_source_operand" "r,F"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (!TARGET_RXV2)" + "@ + fadd\t%2, %0 + fadd\t%2, %0" + [(set_attr "timings" "44,44") + (set_attr "length" "3,7") + (set_attr "insn_group" "IFE,IFE")] +) + +(define_insn "addsf3v2" + [(set (match_operand:SF 0 "register_operand" "=r,r,r") + (plus:SF (match_operand:SF 1 "register_operand" "%0,0,r") + (match_operand:SF 2 "rx_speed_source_operand" "r,F,r"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && TARGET_RXV2" + "@ + fadd\t%2, %0 + fadd\t%2, %0 + fadd\t%1, %2, %0" + [(set_attr "timings" "44,44,44") + (set_attr "length" "3,7,3") + (set_attr "insn_group" "IFE,IFE,IFE")] +) + +;;for dfpu instructions we don't need to model any CC registers because only for cbranchdf4 we copy the result +;;to the CC reg using mvfdr +(define_insn "adddf3" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (plus:DF (match_operand:DF 1 "register_operand" "DFPUreg") + (match_operand:DF 2 "register_operand" "DFPUreg")))] + "flag_dfpu" + "dadd\t%1, %2, %0" + [(set_attr "timings" "44") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "divdf3" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (div:DF (match_operand:DF 1 "register_operand" "DFPUreg") + (match_operand:DF 2 "register_operand" "DFPUreg"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "ddiv\t%2, %1, %0" + [(set_attr "timings" "1616") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "divsf3_mem" + [(set (match_operand:SF 0 "register_operand" "=r") + (div:SF (match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (optimize_size || reload_completed)" "fdiv\t%2, %0" - [(set_attr "timings" "1616,1616,1818") - (set_attr "length" "3,7,5")] + [(set_attr "timings" "1818") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) -(define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=r,r,r") - (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0") - (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) +(define_insn "divsf3" + [(set (match_operand:SF 0 "register_operand" "=r,r") + (div:SF (match_operand:SF 1 "register_operand" "0,0") + (match_operand:SF 2 "rx_speed_source_operand" "r,F"))) (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" + "fdiv\t%2, %0" + [(set_attr "timings" "1616,1616") + (set_attr "length" "3,7") + (set_attr "insn_group" "ISNG,ISNG")] +) + +(define_insn "mulsf3_mem" + [(set (match_operand:SF 0 "register_operand" "=r") + (mult:SF (match_operand:SF 1 "register_operand" "%0") + (match_operand:SF 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (optimize_size || reload_completed)" "fmul\t%2, %0" - [(set_attr "timings" "33,33,55") - (set_attr "length" "3,7,5")] + [(set_attr "timings" "55") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) -(define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=r,r,r") - (minus:SF (match_operand:SF 1 "register_operand" "0,0,0") - (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) +(define_expand "mulsf3" + [(set (match_operand:SF 0 "register_operand") + (mult:SF (match_operand:SF 1 "register_operand") + (match_operand:SF 2 "rx_speed_source_operand"))) (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" + { + if(TARGET_RXV2) + emit_insn(gen_mulsf3v2(operands[0], operands[1], operands[2])); + else + emit_insn(gen_mulsf3v1(operands[0], operands[1], operands[2])); + DONE; + } + ) + +(define_insn "mulsf3v1" + [(set (match_operand:SF 0 "register_operand" "=r,r") + (mult:SF (match_operand:SF 1 "register_operand" "%0,0") + (match_operand:SF 2 "rx_speed_source_operand" "r,F"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (!TARGET_RXV2)" + "@ + fmul\t%2, %0 + fmul\t%2, %0" + [(set_attr "timings" "33,33") + (set_attr "length" "3,7") + (set_attr "insn_group" "IFM,IFM")] +) + +(define_insn "mulsf3v2" + [(set (match_operand:SF 0 "register_operand" "=r,r,r") + (mult:SF (match_operand:SF 1 "register_operand" "%0,0,r") + (match_operand:SF 2 "rx_speed_source_operand" "r,F,r"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && TARGET_RXV2" + "@ + fmul\t%2, %0 + fmul\t%2, %0 + fmul\t%1, %2, %0" + [(set_attr "timings" "33,33,33") + (set_attr "length" "3,7,3") + (set_attr "insn_group" "IFM,IFM,IFM")] +) + +(define_insn "muldf3" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (mult:DF (match_operand:DF 1 "register_operand" "DFPUreg") + (match_operand:DF 2 "rx_speed_source_operand" "DFPUreg"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "dmul\t%1, %2, %0" + [(set_attr "timings" "33") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "subdf3" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (minus:DF (match_operand:DF 1 "register_operand" "DFPUreg") + (match_operand:DF 2 "rx_speed_source_operand" "DFPUreg"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "dsub\t%2, %1, %0" + [(set_attr "timings" "44") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "subsf3_mem" + [(set (match_operand:SF 0 "register_operand" "=r") + (minus:SF (match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (optimize_size || reload_completed)" "fsub\t%Q2, %0" - [(set_attr "timings" "44,44,66") - (set_attr "length" "3,7,5")] + [(set_attr "timings" "66") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) -(define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q"))) +(define_expand "subsf3" + [(set (match_operand:SF 0 "register_operand") + (minus:SF (match_operand:SF 1 "register_operand") + (match_operand:SF 2 "rx_speed_source_operand"))) (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" + { + if(TARGET_RXV2) + emit_insn(gen_subsf3v2(operands[0], operands[1], operands[2])); + else + emit_insn(gen_subsf3v1(operands[0], operands[1], operands[2])); + DONE; + } +) + +(define_insn "subsf3v1" + [(set (match_operand:SF 0 "register_operand" "=r,r") + (minus:SF (match_operand:SF 1 "register_operand" "0,0") + (match_operand:SF 2 "rx_speed_source_operand" "r,F"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (!TARGET_RXV2)" + "@ + fsub\t%Q2, %0 + fsub\t%Q2, %0" + [(set_attr "timings" "44,44") + (set_attr "length" "3,7") + (set_attr "insn_group" "IFE,IFE")] +) + +(define_insn "subsf3v2" + [(set (match_operand:SF 0 "register_operand" "=r,r,r") + (minus:SF (match_operand:SF 1 "register_operand" "0,0,r") + (match_operand:SF 2 "rx_speed_source_operand" "r,F,r"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && TARGET_RXV2" + "@ + fsub\t%Q2, %0 + fsub\t%Q2, %0 + fsub\t%2, %1, %0" + [(set_attr "timings" "44,44,44") + (set_attr "length" "3,7,3") + (set_attr "insn_group" "IFE,IFE,IFE")] +) + +(define_insn "fix_truncsfsi2_mem" + [(set (match_operand:SI 0 "register_operand" "=r") + (fix:SI (match_operand:SF 1 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (optimize_size || reload_completed)" "ftoi\t%Q1, %0" - [(set_attr "timings" "22,44") - (set_attr "length" "3,5")] + [(set_attr "timings" "44") + (set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) -(define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=r,r") - (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q"))) +(define_insn "fix_truncsfsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (fix:SI (match_operand:SF 1 "rx_speed_compare_operand" "r"))) (clobber (reg:CC CC_REG))] "ALLOW_RX_FPU_INSNS" - "itof\t%Q1, %0" - [(set_attr "timings" "22,44") - (set_attr "length" "3,6")] + "ftoi\t%Q1, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "IFE")] ) - -;; Bit manipulation instructions. + +(define_insn "fix_truncdfsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (fix:SI (match_operand:DF 1 "rx_speed_compare_operand" "DFPUreg"))) + (clobber (match_scratch:DF 2 "=&DFPUreg")) + ] + "flag_dfpu" + "dtoi\t%Q1, %2\n\tdmov.L\t%L2, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "fixuns_truncsfsi2" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (unsigned_fix:SI (match_operand:SF 1 "general_operand" "r,Q"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && TARGET_RXV2" + "ftou\t%1, %0" + [(set_attr "timings" "22,44") + (set_attr "length" "3,4") + (set_attr "insn_group" "IFE,ISNG")] +) + +(define_insn "fixuns_truncdfsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (unsigned_fix:SI (match_operand:DF 1 "general_operand" "DFPUreg"))) + (clobber (match_scratch:DF 2 "=&DFPUreg")) + ] + "flag_dfpu" + "dtou\t%1, %2\n\tdmov.L\t%L2, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "floatunssisf2" + [(set (match_operand:SF 0 "register_operand" "=r,r") + (unsigned_float:SF (match_operand:SI 1 "general_operand" "r,Q"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && TARGET_RXV2" + "utof\t%1, %0" + [(set_attr "timings" "22,44") + (set_attr "length" "3,4") + (set_attr "insn_group" "IFE,ISNG")] +) + +(define_insn "floatunssidf2" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (unsigned_float:DF (match_operand:SI 1 "general_operand" "r"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "utod\t%1, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +;DPFU registers work only with double values anyway so no need to keep it in such registers +(define_insn "truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "=r") + (float_truncate:SF (match_operand:DF 1 "register_operand" "DFPUreg"))) + (clobber (match_scratch:DF 2 "=&DFPUreg")) + ] + "flag_dfpu" + "dtof\t%1, %2\n\tdmov.L\t%L2, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (float_extend:DF (match_operand:SF 1 "register_operand" "r"))) + ] + "flag_dfpu" + "ftod\t%1, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "floatsisf2_mem" + [(set (match_operand:SF 0 "register_operand" "=r") + (float:SF (match_operand:SI 1 "rx_restricted_mem_operand" "Q"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS && (optimize_size || reload_completed)" + "itof\t%Q1, %0" + [(set_attr "timings" "44") + (set_attr "length" "6") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "floatsisf2" + [(set (match_operand:SF 0 "register_operand" "=r") + (float:SF (match_operand:SI 1 "rx_speed_compare_operand" "r"))) + (clobber (reg:CC CC_REG))] + "ALLOW_RX_FPU_INSNS" + "itof\t%Q1, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "IFE")] +) + +(define_insn "floatsidf2" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (float:DF (match_operand:SI 1 "general_operand" "r"))) + (clobber (reg:CC CC_REG))] + "flag_dfpu" + "itod\t%Q1, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "sqrtsf2" + [(set (match_operand:SF 0 "register_operand" "=RXV2,RXV2") + (sqrt:SF (match_operand:SF 1 "general_operand" "r,Q")))] + "ALLOW_RX_FPU_INSNS && ALLOW_HW_SQRT" + "fsqrt %Q1, %0" + [(set_attr "timings" "1616") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG,ISNG")] +) + +(define_insn "sqrtdf2" + [(set (match_operand:DF 0 "register_operand" "=DFPUreg") + (sqrt:DF (match_operand:DF 1 "general_operand" "DFPUreg")))] + "flag_dfpu" + "dsqrt %1, %0" + [(set_attr "timings" "1616") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +;; Bit manipulation instructions. ;; The *_in_memory patterns will not be matched automatically, not even with ;; combiner bridge patterns. Especially when the memory operands have a @@ -2032,15 +3276,76 @@ [(set_attr "length" "3")] ) +(define_insn "*bitset" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (ashift:SI (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "register_operand" "0")))] + "" + "bset\t%1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] +) + +(define_insn "bset" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(ior:SI (ashift:SI (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "register_operand" "0"))] + UNSPEC_BUILTIN_BSET))] + "" + "bset\t%1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] +) + (define_insn "bitset_in_memory" + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") + (unspec:QI [(ior:QI (ashift:QI (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri")) + (match_dup 0))] + UNSPEC_BUILTIN_BSET_MEM))] + "" + "bset\t%1, %0.B" + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "*bitset_in_memory" [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (ior:QI (ashift:QI (const_int 1) (match_operand:QI 1 "nonmemory_operand" "ri")) (match_dup 0)))] "" "bset\t%1, %0.B" - [(set_attr "length" "5") - (set_attr "timings" "33")] + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "*bitset_in_memory2" + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") + (ior:QI (ashift:QI (const_int 1) + (match_operand:SI 1 "nonmemory_operand" "ri")) + (match_dup 0)))] + "" + "bset\t%1, %0.B" + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "*bitset_in_memory_2" + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") + (ior:QI (match_dup 0) + (match_operand 1 "rx_bitset_operand" "i") + ))] + "" + "bset\t%b1, %0.B" + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] ) (define_insn_and_split "bitinvert" @@ -2061,6 +3366,30 @@ [(set_attr "length" "3")] ) +(define_insn "binvert" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(xor:SI (ashift:SI (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri")) + (match_operand:SI 2 "register_operand" "0"))] + UNSPEC_BUILTIN_BNOT))] + "" + "bnot\t%1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] +) + +(define_insn "bnot_memory" + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") + (unspec:QI [(xor:SI (ashift:QI (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri")) + (match_dup 0))] + UNSPEC_BUILTIN_BNOT_MEM))] + "" + "bnot\t%1, %0.B" + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] +) (define_insn "bitinvert_in_memory" [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (xor:QI (ashift:QI (const_int 1) @@ -2072,7 +3401,7 @@ (set_attr "timings" "33")] ) -(define_insn_and_split "bitclr" +(define_insn "*bitclr" [(set (match_operand:SI 0 "register_operand" "=r") (and:SI (not:SI (ashift:SI @@ -2081,6 +3410,20 @@ (match_operand:SI 2 "register_operand" "0")))] "" "bclr\t%1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] +) + +(define_insn_and_split "bclr" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec: SI [(and:SI (not:SI + (ashift:SI + (const_int 1) + (match_operand:SI 1 "rx_shift_operand" "ri"))) + (match_operand:SI 2 "register_operand" "0"))] + UNSPEC_BUILTIN_BCLR))] + "" + "bclr\t%1, %0" "&& can_create_pseudo_p ()" [(const_int 0)] { @@ -2089,7 +3432,22 @@ else FAIL; } - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] +) + +(define_insn "bclr_memory" + [(set(match_operand:QI 0 "rx_restricted_mem_operand" "+Q") + (unspec:QI [(and:QI (not:QI + (ashift:QI (const_int 1) + (match_operand:QI 1 "nonmemory_operand" "ri"))) + (match_dup 0))] + UNSPEC_BUILTIN_BCLR_MEM))] + "" + "bclr\t%1, %0.B" + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] ) (define_insn "bitclr_in_memory" @@ -2101,8 +3459,63 @@ (match_dup 0)))] "" "bclr\t%1, %0.B" - [(set_attr "length" "5") - (set_attr "timings" "33")] +[(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "*bitclr_in_memory2" + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") + (and:QI (not:QI + (ashift:QI + (const_int 1) + (match_operand:SI 1 "nonmemory_operand" "ri"))) + (match_dup 0)))] + "" + "bclr\t%1, %0.B" + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "*bittest" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_operand:SI 0 "register_operand" "r,r") + (ashift:SI + (const_int 1) + (match_operand:SI 1 "rx_speed_source_operand" "r,i"))) + (const_int 0)))] + "" + "btst\t%1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IEX,IEX")] +) + +(define_insn "*bittest_in_memory" +[(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:QI (match_operand:QI 0 "rx_restricted_mem_operand" "Q") + (ashift:QI + (const_int 1) + (match_operand:SI 1 "nonmemory_operand" "ri"))) + (const_int 0)))] + "" + "btst\t%1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "*bitclr_in_memory_2" + [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") + (and:QI (match_dup 0) + (match_operand 1 "rx_bitclr_operand" "i") + ))] + "" + "bclr\t%b1, %0.B" + [(set_attr "length" "3") + (set_attr "timings" "33") + (set_attr "insn_group" "ISNG")] ) (define_insn "*insv_imm" @@ -2118,7 +3531,8 @@ else return "bclr\t%1, %0"; } - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] ) (define_insn_and_split "rx_insv_reg" @@ -2147,6 +3561,32 @@ operands[3] = gen_rtx_NE (SImode, flags, const0_rtx); }) +(define_insn_and_split "*insv_cond_mem" + [(set (zero_extract:SI + (match_operand:SI 0 "register_operand" "+r") + (const_int 1) + (match_operand:SI 1 "const_int_operand" "")) + (match_operator:SI 4 "comparison_operator" + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "rx_restricted_mem_operand" "Q")])) + (clobber (reg:CC CC_REG))] + "" + "#" + "reload_completed" + [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (match_dup 4))] +{ + rtx flags, x; + + flags = gen_rtx_REG (CCmode, CC_REG); + x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]); + x = gen_rtx_SET (flags, x); + emit_insn (x); + + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode, + flags, const0_rtx); +}) + (define_insn_and_split "*insv_cond" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") @@ -2154,7 +3594,7 @@ (match_operand:SI 1 "const_int_operand" "")) (match_operator:SI 4 "comparison_operator" [(match_operand:SI 2 "register_operand" "r") - (match_operand:SI 3 "rx_source_operand" "riQ")])) + (match_operand:SI 3 "rx_speed_source_operand" "ri")])) (clobber (reg:CC CC_REG))] "" "#" @@ -2182,7 +3622,8 @@ [(reg CC_REG) (const_int 0)]))] "reload_completed" "bm%B2\t%1, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEX")] ) ;; Work around the fact that X=Y<0 is preferentially expanded as a shift. @@ -2230,6 +3671,8 @@ ;; Atomic operations. +;; Atomic exchange operation. + (define_code_iterator FETCHOP [plus minus ior xor and]) (define_code_iterator FETCHOP_NO_MINUS [plus ior xor and]) @@ -2250,7 +3693,8 @@ "" "xchg\t%1, %0" [(set_attr "length" "3,6") - (set_attr "timings" "22")] + (set_attr "timings" "22") + (set_attr "insn_group" "ISNG,ISNG")] ) (define_expand "atomic_exchange" @@ -2401,7 +3845,7 @@ (match_operand:BLK 2 "memory_operand")) ;; Source (use (match_operand:SI 0 "register_operand")) ;; Updated Dest ] - "rx_allow_string_insns" + "(rx_allow_string_insns && (!optimize_size))" { rtx addr1 = gen_rtx_REG (SImode, 1); rtx addr2 = gen_rtx_REG (SImode, 2); @@ -2431,7 +3875,8 @@ "rx_allow_string_insns" "smovu" [(set_attr "length" "2") - (set_attr "timings" "1111")] ;; The timing is a guesstimate. + (set_attr "timings" "1111") ;; The timing is a guesstimate. + (set_attr "insn_group" "ISNG")] ) (define_insn "rx_strend" @@ -2446,7 +3891,8 @@ "rx_allow_string_insns" "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0" [(set_attr "length" "10") - (set_attr "timings" "1111")] ;; The timing is a guesstimate. + (set_attr "timings" "1111") ;; The timing is a guesstimate. + (set_attr "insn_group" "ISNG")] ) (define_expand "cpymemsi" @@ -2502,7 +3948,8 @@ "rx_allow_string_insns" "smovf" [(set_attr "length" "2") - (set_attr "timings" "1111")] ;; The timing is a guesstimate. + (set_attr "timings" "1111") ;; The timing is a guesstimate. + (set_attr "insn_group" "ISNG")] ) (define_expand "setmemsi" @@ -2541,9 +3988,9 @@ (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1 (match_operand:BLK 2 "memory_operand")] ;; String2 UNSPEC_CMPSTRN)) - (use (match_operand:SI 3 "nonmemory_operand")) ;; Max Length + (use (match_operand:SI 3 "nonmemory_operand")) ;; Max Length (match_operand:SI 4 "immediate_operand")] ;; Known Align - "rx_allow_string_insns" + "(rx_allow_string_insns && (!optimize_size))" { bool const_len = CONST_INT_P(operands[3]); if (const_len) @@ -2558,16 +4005,17 @@ rtx str1 = gen_rtx_REG (SImode, 1); rtx str2 = gen_rtx_REG (SImode, 2); rtx len = gen_rtx_REG (SImode, 3); - + emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX)); emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX)); - emit_move_insn (len, operands[3]); + emit_move_insn (len, force_operand (operands[3], NULL_RTX)); /* Set flags in case len is zero */ if (!const_len) { emit_insn (gen_setpsw (GEN_INT('C'))); emit_insn (gen_setpsw (GEN_INT('Z'))); } + emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2])); DONE; } @@ -2579,12 +4027,12 @@ (match_operand:BLK 2 "memory_operand")] ;; String2 UNSPEC_CMPSTRN)) (match_operand:SI 3 "immediate_operand")] ;; Known Align - "rx_allow_string_insns" + "(rx_allow_string_insns && (!optimize_size))" { rtx str1 = gen_rtx_REG (SImode, 1); rtx str2 = gen_rtx_REG (SImode, 2); rtx len = gen_rtx_REG (SImode, 3); - + emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0))); emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0))); emit_move_insn (len, GEN_INT (-1)); @@ -2610,12 +4058,13 @@ ; by the SC insn) bnc ?+ ; If Carry is not set skip over scne.L %0 ; Set result based on Z flag -?: +?: " [(set_attr "length" "9") - (set_attr "timings" "1111")] ;; The timing is a guesstimate. + (set_attr "timings" "1111") ;; The timing is a guesstimate. + (set_attr "insn_group" "ISNG")] ) - + ;; Builtin Functions ;; ;; GCC does not have the ability to generate the following instructions @@ -2625,96 +4074,577 @@ ;; ;; int short_byte_swap (int arg) { return __builtin_rx_revw (arg); } +(define_insn "save" + [(unspec_volatile:SI [(match_operand:SI 0 "general_operand" "ri")] + UNSPEC_BUILTIN_SAVE)] + "TARGET_RXV3" + "save\t%0" + [(set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "rstr" + [(unspec_volatile:SI [(match_operand:SI 0 "general_operand" "ri")] + UNSPEC_BUILTIN_RSTR)] + "TARGET_RXV3" + "rstr\t%0" + [(set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "mvfdc" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFDC) + )] + "TARGET_RXV3" + "mvfdc\t%D1, %0" + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] +) + +;;TODO: write a proper pattern for this and if GCC doesn't select it we might write some peepholes, same for bfmovz +(define_insn "bfmov" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_dup 0) + (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "Uint05") + (match_operand:SI 3 "immediate_operand" "Uint05") + (match_operand:SI 4 "immediate_operand" "Uintz5")] + UNSPEC_BUILTIN_BFMOV)) + ] + "TARGET_RXV3" + "bfmov\t%2, %3, %4, %1, %0" + [(set_attr "length" "5") + (set_attr "insn_group" "ISNG")] +) + + +(define_insn "bfmovz" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "Uint05") + (match_operand:SI 3 "immediate_operand" "Uint05") + (match_operand:SI 4 "immediate_operand" "Uintz5")] + UNSPEC_BUILTIN_BFMOVZ))] + "TARGET_RXV3" + "bfmovz\t%2, %3, %4, %1, %0" + [(set_attr "length" "5") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "mvtdc" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i") + (match_operand:SI 1 "nonmemory_operand" "r")] + UNSPEC_BUILTIN_MVTDC)] + "" + "mvtdc\t%1, %D0" + [(set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "mvfdr" + [(unspec_volatile [(const_int 0)] + UNSPEC_BUILTIN_MVFDR)] + "" + "mvfdr" + [(set_attr "length" "1") + (set_attr "timings" "66") + (set_attr "insn_group" "ISNG")] +) ;;---------- Accumulator Support ------------------------ -;; Multiply & Accumulate (high) -(define_insn "machi" - [(unspec:SI [(match_operand:SI 0 "register_operand" "r") +;;Extended MULtiply to Accumulator +(define_insn "emula_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "register_operand" "r")] - UNSPEC_BUILTIN_MACHI)] + UNSPEC_BUILTIN_EMULA_A0)] "" - "machi\t%0, %1" - [(set_attr "length" "3")] + "emula\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) -;; Multiply & Accumulate (low) -(define_insn "maclo" - [(unspec:SI [(match_operand:SI 0 "register_operand" "r") +(define_insn "emula_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "register_operand" "r")] - UNSPEC_BUILTIN_MACLO)] + UNSPEC_BUILTIN_EMULA_A1)] "" - "maclo\t%0, %1" - [(set_attr "length" "3")] + "emula\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) -;; Multiply (high) -(define_insn "mulhi" - [(unspec:SI [(match_operand:SI 0 "register_operand" "r") +(define_insn "emaca_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "register_operand" "r")] - UNSPEC_BUILTIN_MULHI)] + UNSPEC_BUILTIN_EMACA_A0)] "" - "mulhi\t%0, %1" - [(set_attr "length" "3")] + "emaca\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) -;; Multiply (low) -(define_insn "mullo" - [(unspec:SI [(match_operand:SI 0 "register_operand" "r") +(define_insn "emaca_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "register_operand" "r")] - UNSPEC_BUILTIN_MULLO)] + UNSPEC_BUILTIN_EMACA_A1)] "" - "mullo\t%0, %1" - [(set_attr "length" "3")] + "emaca\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) -;; Move from Accumulator (high) -(define_insn "mvfachi" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(const_int 0)] - UNSPEC_BUILTIN_MVFACHI))] +(define_insn "emsba_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_EMSBA_A0)] "" - "mvfachi\t%0" - [(set_attr "length" "3")] + "emsba\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) -;; Move from Accumulator (middle) -(define_insn "mvfacmi" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(const_int 0)] - UNSPEC_BUILTIN_MVFACMI))] +(define_insn "emsba_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_EMSBA_A1)] "" - "mvfacmi\t%0" - [(set_attr "length" "3")] + "emsba\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) -;; Move to Accumulator (high) -(define_insn "mvtachi" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] - UNSPEC_BUILTIN_MVTACHI)] +;; Multiply-ACcumulate Low-order word and High-order word +(define_insn "maclh_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MACLH_A0)] "" - "mvtachi\t%0" - [(set_attr "length" "3")] + "maclh\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) -;; Move to Accumulator (low) -(define_insn "mvtaclo" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] - UNSPEC_BUILTIN_MVTACLO)] +(define_insn "maclh_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MACLH_A1)] "" - "mvtaclo\t%0" - [(set_attr "length" "3")] + "maclh\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Multiply & Accumulate (high) +;; A0 is implicit here for RXV2 +(define_insn "machi" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MACHI)] + "" + "machi\t%0, %1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "machi_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MACHI_A1)] + "" + "machi\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Multiply & Accumulate (low) +;; A0 is implicit here for RXV2 +(define_insn "maclo" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MACLO)] + "" + "maclo\t%0, %1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "maclo_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MACLO_A1)] + "" + "maclo\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Multiply Low-order word and High-order word +(define_insn "mullh_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MULLH_A0)] + "" + "mullh\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mullh_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MULLH_A1)] + "" + "mullh\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Multiply (high) +;; A0 is implicit here for RXV2 +(define_insn "mulhi" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MULHI)] + "" + "mulhi\t%0, %1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mulhi_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MULHI_A1)] + "" + "mulhi\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Multiply (low) +;; A0 is implicit here for RXV2 +(define_insn "mullo" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MULLO)] + "" + "mullo\t%0, %1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mullo_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MULLO_A1)] + "" + "mullo\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Multiply-SuBtract Low-order word and High-order word +(define_insn "msblh_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MSBLH_A0)] + "" + "msblh\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "msblh_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MSBLH_A1)] + "" + "msblh\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "msbhi_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MSBHI_A0)] + "" + "msbhi\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "msbhi_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MSBHI_A1)] + "" + "msbhi\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "msblo_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MSBLO_A0)] + "" + "msblo\t%0, %1, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "msblo_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "register_operand" "r")] + UNSPEC_BUILTIN_MSBLO_A1)] + "" + "msblo\t%0, %1, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + + +;; Move from Accumulator (high) +;; A0 is implicit here for RXV2 +(define_insn "mvfachi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] + UNSPEC_BUILTIN_MVFACHI))] + "" + "mvfachi\t%0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfachi_A0" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACHI_A0))] + "" + "mvfachi\t%1, A0, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfachi_A1" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACHI_A1))] + "" + "mvfachi\t%1, A1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Move from Accumulator (middle) +;; A0 is implicit here for RXV2 +(define_insn "mvfacmi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] + UNSPEC_BUILTIN_MVFACMI))] + "" + "mvfacmi\t%0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfacmi_A0" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACMI_A0))] + "" + "mvfacmi\t%1, A0, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfacmi_A1" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACMI_A1))] + "" + "mvfacmi\t%1, A1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfaclo_A0" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACLO_A0))] + "" + "mvfaclo\t%1, A0, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfaclo_A1" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACLO_A1))] + "" + "mvfaclo\t%1, A1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfacgu_A0" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACGU_A0))] + "" + "mvfacgu\t%1, A0, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvfacgu_A1" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] + UNSPEC_BUILTIN_MVFACGU_A1))] + "" + "mvfacgu\t%1, A1, %0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Move to Accumulator (high) +;; A0 is implicit here for RXV2 +(define_insn "mvtachi" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] + UNSPEC_BUILTIN_MVTACHI)] + "" + "mvtachi\t%0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvtachi_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] + UNSPEC_BUILTIN_MVTACHI_A1)] + "" + "mvtachi\t%0, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; Move to Accumulator (low) +;; A0 is implicit here for RXV2 +(define_insn "mvtaclo" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] + UNSPEC_BUILTIN_MVTACLO)] + "" + "mvtaclo\t%0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvtaclo_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] + UNSPEC_BUILTIN_MVTACLO_A1)] + "" + "mvtaclo\t%0, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvtacgu_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] + UNSPEC_BUILTIN_MVTACGU_A0)] + "" + "mvtacgu\t%0, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "mvtacgu_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] + UNSPEC_BUILTIN_MVTACGU_A1)] + "" + "mvtacgu\t%0, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) ;; Round Accumulator +(define_insn "rdacw_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] + UNSPEC_BUILTIN_RDACW_A0)] + "" + "rdacw\t%0, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "rdacw_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] + UNSPEC_BUILTIN_RDACW_A1)] + "" + "rdacw\t%0, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "rdacl_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] + UNSPEC_BUILTIN_RDACL_A0)] + "" + "rdacl\t%0, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "rdacl_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] + UNSPEC_BUILTIN_RDACL_A1)] + "" + "rdacl\t%0, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +;; A0 is implicit here for RXV2 (define_insn "racw" [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_BUILTIN_RACW)] "" "racw\t%0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "racw_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] + UNSPEC_BUILTIN_RACW_A1)] + "" + "racw\t%0, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "racl_A0" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] + UNSPEC_BUILTIN_RACL_A0)] + "" + "racl\t%0, A0" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] +) + +(define_insn "racl_A1" + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] + UNSPEC_BUILTIN_RACL_A1)] + "" + "racl\t%0, A1" + [(set_attr "length" "3") + (set_attr "insn_group" "IML")] ) ;; Repeat multiply and accumulate + (define_insn "rmpa" [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3) (reg:SI 4) (reg:SI 5) (reg:SI 6)] @@ -2728,6 +4658,59 @@ (set_attr "timings" "1010")] ) + +(define_insn "rmpa8" + [(set (match_operand:DI 3 "register_operand" "=r") (unspec_volatile:DI [ (match_operand:SI 0 "register_operand" "+r") (match_operand:SI 1 "register_operand" "+r") (match_operand: SI 2 "register_operand" "+r") + (match_dup 3)(match_operand:SI 4 "register_operand" "r")] + UNSPEC_BUILTIN_RMPA8)) + (clobber (reg:SI 1)) + (clobber (reg:SI 2)) + (clobber (reg:SI 3)) + (clobber (reg:SI 4)) + (clobber (reg:SI 5)) + (clobber (reg:SI 6))] + "rx_allow_string_insns" + "rmpa.B" + [(set_attr "length" "2") + (set_attr "timings" "1010") + (set_attr "insn_group" "ISNG")] +) + + +(define_insn "rmpa16" + [(set (match_operand:DI 3 "register_operand" "=r") (unspec_volatile:DI [ (match_operand:SI 0 "register_operand" "+r") (match_operand:SI 1 "register_operand" "+r") (match_operand: SI 2 "register_operand" "+r") + (match_dup 3)(match_operand:SI 4 "register_operand" "r")] + UNSPEC_BUILTIN_RMPA16)) + (clobber (reg:SI 1)) + (clobber (reg:SI 2)) + (clobber (reg:SI 3)) + (clobber (reg:SI 4)) + (clobber (reg:SI 5)) + (clobber (reg:SI 6))] + "rx_allow_string_insns" + "rmpa.W" + [(set_attr "length" "2") + (set_attr "timings" "1010") + (set_attr "insn_group" "ISNG")] +) + +(define_insn "rmpa32" + [(set (match_operand:DI 3 "register_operand" "=r") (unspec_volatile:DI [ (match_operand:SI 0 "register_operand" "+r") (match_operand:SI 1 "register_operand" "+r") (match_operand: SI 2 "register_operand" "+r") + (match_dup 3) (match_operand:SI 4 "register_operand" "r")] + UNSPEC_BUILTIN_RMPA32)) + (clobber (reg:SI 1)) + (clobber (reg:SI 2)) + (clobber (reg:SI 3)) + (clobber (reg:SI 4)) + (clobber (reg:SI 5)) + (clobber (reg:SI 6))] + "rx_allow_string_insns" + "rmpa.L" + [(set_attr "length" "2") + (set_attr "timings" "1010") + (set_attr "insn_group" "ISNG")] +) + ;;---------- Arithmetic ------------------------ ;; Byte swap (two 16-bit values). @@ -2737,7 +4720,8 @@ UNSPEC_BUILTIN_REVW))] "" "revw\t%1, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "IEP")] ) ;; Round to integer. @@ -2748,10 +4732,24 @@ (clobber (reg:CC CC_REG))] "" "round\t%1, %0" - [(set_attr "timings" "22,44") - (set_attr "length" "3,5")] + [(set_attr "timings" "22,44") + (set_attr "length" "3,5") + (set_attr "insn_group" "IFE,ISNG")] ) +(define_insn "lrintdf2" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:DF 1 "register_operand" "DFPUreg")] + UNSPEC_BUILTIN_DROUND) + ) + (clobber (match_scratch:DF 2 "=&DFPUreg")) + ] + "flag_dfpu" + "dround\t%1, %2\n\tdmov.L\t%L2, %0" + [(set_attr "timings" "22") + (set_attr "length" "3") + (set_attr "insn_group" "ISNG")] +) ;;---------- Control Registers ------------------------ ;; Clear Processor Status Word @@ -2761,7 +4759,8 @@ (clobber (reg:CC CC_REG))] "" "clrpsw\t%F0" - [(set_attr "length" "2")] + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] ) ;; Set Processor Status Word @@ -2771,7 +4770,8 @@ (clobber (reg:CC CC_REG))] "" "setpsw\t%F0" - [(set_attr "length" "2")] + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] ) ;; Move from control register @@ -2781,7 +4781,8 @@ UNSPEC_BUILTIN_MVFC))] "" "mvfc\t%C1, %0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "ISNG")] ) ;; Move to control register @@ -2794,7 +4795,13 @@ (clobber (reg:CC CC_REG))] "" "mvtc\t%1, %C0" - [(set_attr "length" "3,7")] + [(set_attr "length" "3,7") + (set_attr "insn_group" "ISNG,ISNG")] + ;; 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 @@ -2803,7 +4810,8 @@ UNSPEC_BUILTIN_MVTIPL)] "" "mvtipl\t%0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "ISNG")] ) ;;---------- Interrupts ------------------------ @@ -2815,7 +4823,8 @@ "" "brk" [(set_attr "length" "1") - (set_attr "timings" "66")] + (set_attr "timings" "66") + (set_attr "insn_group" "ISNG")] ) ;; Interrupt @@ -2824,7 +4833,8 @@ UNSPEC_BUILTIN_INT)] "" "int\t%0" - [(set_attr "length" "3")] + [(set_attr "length" "3") + (set_attr "insn_group" "ISNG")] ) ;; Wait @@ -2833,7 +4843,8 @@ UNSPEC_BUILTIN_WAIT)] "" "wait" - [(set_attr "length" "2")] + [(set_attr "length" "2") + (set_attr "insn_group" "ISNG")] ) ;;---------- CoProcessor Support ------------------------ @@ -2851,7 +4862,8 @@ UNSPEC_BUILTIN_MVFCP))] "" "; mvfcp\t%1, %0, %2" - [(set_attr "length" "5")] + [(set_attr "length" "5") + (set_attr "insn_group" "ISNG")] ) ;;---------- Misc ------------------------ @@ -2861,7 +4873,8 @@ [(const_int 0)] "" "nop" - [(set_attr "length" "1")] + [(set_attr "length" "1") + (set_attr "insn_group" "IEX")] ) (define_expand "pid_addr" @@ -2871,6 +4884,7 @@ "" ) + (define_insn "movdi" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (match_operand:DI 1 "general_operand" "rmi"))] @@ -2880,11 +4894,474 @@ (set_attr "timings" "22")] ) -(define_insn "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=rm") - (match_operand:DF 1 "general_operand" "rmi"))] - "TARGET_ENABLE_LRA" - { return rx_gen_move_template (operands, false); } - [(set_attr "length" "16") - (set_attr "timings" "22")] +(define_insn "exchange" + [(unspec_volatile:SI [(match_operand:register_modes 0 "register_operand" "+r,r") + (match_operand:register_modes 1 "general_operand" "+r,Q")] + UNSPEC_BUILTIN_XCHG)] + "" + "xchg\t%Q1, %0" + [(set_attr "length" "3,6") + (set_attr "timings" "22") + (set_attr "insn_group" "ISNG, ISNG")] +) + +;;====BCLR peepholes==== + +;; mov.L #-2, ra +;; rotl rb, ra +;; and [rc].B, ra +;; mov.b ra [rc] +;; convert to: +;; bclr rb, [rc].B +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (set (match_operand:SI 2 "register_operand" "") + (sign_extend:SI (match_operand:QI 3 "rx_restricted_mem_operand" ""))) + (parallel [(set (match_dup 0) + (and:SI (match_dup 0) + (match_dup 2))) + (clobber (reg:CC CC_REG))]) + (set (match_dup 3) (match_operand:QI 4 "register_operand" ""))] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && MEM_P(operands[3]) && REG_P(operands[4]) && (REGNO (operands[0]) == REGNO (operands[4])) && peep2_regno_dead_p (5, REGNO (operands[0])) && peep2_regno_dead_p (5, REGNO (operands[2]))" +[(set (match_dup 3) + (and:QI (not:QI (ashift:QI (const_int 1) + (match_dup 1))) + (match_dup 3)))] +) + +;; the only difference to the above peephole is the order of the operands in the and +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (set (match_operand:SI 2 "register_operand" "") + (sign_extend:SI (match_operand:QI 3 "rx_restricted_mem_operand" ""))) + (parallel [(set (match_dup 0) + (and:SI (match_dup 2) + (match_dup 0))) + (clobber (reg:CC CC_REG))]) + (set (match_dup 3) (match_operand:QI 4 "register_operand" ""))] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && MEM_P(operands[3]) && REG_P(operands[4]) && (REGNO (operands[0]) == REGNO (operands[4])) && peep2_regno_dead_p (5, REGNO (operands[0])) && peep2_regno_dead_p (5, REGNO (operands[2]))" +[(set (match_dup 3) + (and:QI (not:QI (ashift:QI (const_int 1) + (match_dup 1))) + (match_dup 3)))] +) + +;; mov.L #-2, ra +;; rotl rb, ra +;; and ra, rc +;; convert to: +;; bclr rb, rc +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (parallel [(set (match_operand:SI 2 "register_operand" "") + (and:SI (match_dup 0) + (match_dup 2))) + (clobber (reg:CC CC_REG))])] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && peep2_regno_dead_p (3, REGNO (operands[0]))" +[(set (match_dup 2) + (and:SI (not:SI (ashift:SI (const_int 1) + (match_dup 1))) + (match_dup 2)))] +) + +;; the only difference to the above peephole is the order of the operands in the and +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (parallel [(set (match_operand:SI 2 "register_operand" "") + (and:SI (match_dup 2) + (match_dup 0))) + (clobber (reg:CC CC_REG))])] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && peep2_regno_dead_p (3, REGNO (operands[0]))" +[(set (match_dup 2) + (and:SI (not:SI (ashift:SI (const_int 1) + (match_dup 1))) + (match_dup 2)))] +) + +;; mov.b [ra], rb +;; and #imm, rb +;; mov.b rb [ra] +;; convert to: +;; bclr #imm, [ra].B +;;(define_peephole +;;[(set (match_operand:SI 0 "register_operand" "r") +;; (sign_extend:SI (match_operand:QI 1 "rx_restricted_mem_operand" "Q"))) +;; (parallel [(set (match_dup 0) +;; (and:SI (match_dup 0) +;; (match_operand:SI 2 "immediate_operand" "i"))) +;; (clobber (reg:CC CC_REG))]) +;; (set (match_dup 1) +;; (match_operand:QI 3 "register_operand" "r"))] +;;"(REGNO (operands[0]) == REGNO (operands[3])) && (exact_log2 (0xFFFFFFFF & ~ ;;;;INTVAL (operands[2])) >= 0) && +;; dead_or_set_p (insn, operands[0])" +;;{ +;; operands[0] = gen_rtx_CONST_INT(QImode, exact_log2 (0xFFFFFFFF & ~ INTVAL ;;;;(operands[2]))); +;; return "bclr %0, %1.B"; +;;} +;;) + +;; and #imm, ra +;; convert to: +;; btst #imm, ra +;; or +;; bclr #imm, ra +(define_peephole +[(parallel [(set (match_operand:SI 0 "register_operand" "r") + (and:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "i"))) + (clobber (reg:CC CC_REG))])] +;; "(exact_log2 (INTVAL (operands[2])) >= 0) && (exact_log2 (INTVAL (operands[2])) <= 31)" +"(REGNO (operands[0]) == REGNO (operands[1]))" +{ + rtx note; + HOST_WIDE_INT val = INTVAL (operands[2]); + + /* check if dest reg is unused. only then we can replace the and with an btst + otherwise we can replace it with an bclr see below */ + for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) + if (REG_NOTE_KIND (note) == REG_UNUSED) + if((exact_log2 (INTVAL (operands[2])) >= 0) && + (exact_log2 (INTVAL (operands[2])) <= 31) && + (REGNO (XEXP (note, 0)) == REGNO(operands[0]))) + { + operands[2] = gen_rtx_CONST_INT(SImode, exact_log2 (INTVAL (operands[2]))); + return "btst %2, %0"; + } + else if((REGNO (XEXP (note, 0)) == CC_REG) && + (exact_log2(0xFFFFFFFF & ~ val) >= 0) && (exact_log2(0xFFFFFFFF & ~ val) <= 31)) + { + operands[2] = gen_rtx_CONST_INT(SImode, exact_log2(0xFFFFFFFF & ~ val)); + return "bclr %2, %0"; + } + /* otherwise we don't do eny replacement */ + return "and %2, %0"; +} +) + +;; mov.L #-2, ra +;; rotl rb, ra +;; mov.W [rc], rd +;; and ra, rd +;; convert to: +;; mov.W [rc], ra +;; bclr rb, ra +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (set (match_operand:SI 2 "register_operand" "") + (sign_extend:SI (match_operand:HI 3 "memory_operand" ""))) + (parallel [(set (match_dup 0) + (and:SI (match_dup 0) + (match_dup 2))) + (clobber (reg:CC CC_REG))]) +] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && MEM_P(operands[3]) && peep2_regno_dead_p (4, REGNO (operands[2]))" +[(set (match_dup 0) (sign_extend:SI (match_dup 3))) + (set (match_dup 0) + (and:SI (not:SI + (ashift:SI + (const_int 1) + (match_dup 1))) + (match_dup 0)))] +) + +;; the only difference to the above peephole is the order of the operands in the and +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (set (match_operand:SI 2 "register_operand" "") + (sign_extend:SI (match_operand:HI 3 "memory_operand" ""))) + (parallel [(set (match_dup 0) + (and:SI (match_dup 2) + (match_dup 0))) + (clobber (reg:CC CC_REG))]) +] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && MEM_P(operands[3]) && peep2_regno_dead_p (4, REGNO (operands[2]))" +[(set (match_dup 0) (sign_extend:SI (match_dup 3))) + (set (match_dup 0) + (and:SI (not:SI + (ashift:SI + (const_int 1) + (match_dup 1))) + (match_dup 0)))] +) + +;; mov.L #-2, ra +;; rotl rb, ra +;; and [rd], ra +;; convert to: +;; mov.L [rd], ra +;; bclr rb, ra +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (parallel [(set (match_dup 0) + (and:SI (match_dup 0) + (match_operand:SI 2 "memory_operand" ""))) + (clobber (reg:CC CC_REG))]) +] +"REG_P(operands[0]) && REG_P(operands[1]) && MEM_P(operands[2])" +[(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) + (and:SI (not:SI + (ashift:SI + (const_int 1) + (match_dup 1))) + (match_dup 0)))] +) + +;; mov.L #-2, ra +;; rotl rb, ra +;; mov.L [rd], rc +;; and rc, ra +;; convert to: +;; mov.L [rd], ra +;; bclr rb, ra +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (set (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "memory_operand" "")) + (parallel [(set (match_dup 0) + (and:SI (match_dup 2) + (match_dup 0))) + (clobber (reg:CC CC_REG))]) +] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && MEM_P(operands[3]) && peep2_regno_dead_p (4, REGNO (operands[2]))" +[(set (match_dup 0) (match_dup 3)) + (set (match_dup 0) + (and:SI (not:SI + (ashift:SI + (const_int 1) + (match_dup 1))) + (match_dup 0)))] +) + +;; the only difference to the above peephole is the order of the operands in the and +(define_peephole2 +[(set (match_operand:SI 0 "register_operand" "") + (const_int -2)) + (parallel [(set (match_dup 0) + (rotate:SI (match_dup 0) + (match_operand:SI 1 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (set (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "memory_operand" "")) + (parallel [(set (match_dup 0) + (and:SI (match_dup 0) + (match_dup 2))) + (clobber (reg:CC CC_REG))]) +] +"REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && MEM_P(operands[3]) && peep2_regno_dead_p (4, REGNO (operands[2]))" +[(set (match_dup 0) (match_dup 3)) + (set (match_dup 0) + (and:SI (not:SI + (ashift:SI + (const_int 1) + (match_dup 1))) + (match_dup 0)))] +) + +;;and to tst +(define_peephole2 + [(parallel [ + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (and:SI (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "rx_speed_source_operand" "")) + (const_int 0))) + (set (match_dup 0) + (and:SI (match_dup 0) + (match_dup 1))) + ])] + "reload_completed && peep2_reg_dead_p (1, operands[0])" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS (and:SI (match_dup 0) + (match_dup 1)) + (const_int 0)))] + "" +) + +;;====BTST Peepholes==== + +;;convert tst #nr, ra to btst #;log2(nr), ra +(define_peephole2 + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "immediate_operand" "")) + (const_int 0)))] + "REG_P(operands[0]) && (!REG_P(operands[1]) && !MEM_P(operands[1])) && (exact_log2 (INTVAL (operands[1])) >= 0) && + (operands[1] = gen_rtx_CONST_INT(QImode, exact_log2 (INTVAL (operands[1]))), 1)" +[(set (reg:CC_ZS CC_REG) + (compare:CC_ZS + (and:SI (match_dup 0) + (ashift:SI + (const_int 1) + (match_dup 1))) + (const_int 0)))] + ) + +(define_peephole2 + [(parallel [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS (and:SI (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "const_int_operand" "")) + (const_int 0))) + (set (match_operand:SI 2 "register_operand" "") + (and:SI (match_dup 0) (match_dup 1)))]) + (set (match_operand:SI 3 "register_operand" "") + (if_then_else:SI (match_operator 6 "rx_z_comparison_operator" + [(reg:CC_ZS CC_REG) (const_int 0)]) + (match_operand:SI 4 "immediate_operand" "") + (match_operand:SI 5 "register_operand" "")))] + "exact_log2 (INTVAL (operands[1])) >= 0 && + rtx_equal_p (operands[3], operands[5]) && INTVAL (operands[4]) == 0 && + ((GET_CODE (operands[6]) == EQ) || (GET_CODE (operands[6]) == NE))" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS (and:SI (match_dup 3) + (ashift:SI (const_int 1) + (match_operand:SI 7 "rx_speed_source_operand" ""))) + (const_int 0))) + (set (match_dup 3) + (if_then_else:SI (match_operator 8 "rx_z_comparison_operator" + [(reg:CC_ZS CC_REG) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + { + HOST_WIDE_INT mask = INTVAL (operands[1]); + int pos = ctz_hwi (mask); + operands[7] = GEN_INT (pos); + /* Invert the condition: EQ -> NE, NE -> EQ */ + if (GET_CODE (operands[6]) == EQ) + operands[8] = gen_rtx_NE (VOIDmode, operands[6], const0_rtx); + else /* NE */ + operands[8] = gen_rtx_EQ (VOIDmode, operands[6], const0_rtx); + } +) + +(define_peephole2 + [(parallel [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS (and:SI (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "const_int_operand" "")) + (const_int 0))) + (set (match_operand:SI 2 "register_operand" "") + (and:SI (match_dup 0) (match_dup 1)))]) + (set (match_operand:SI 3 "register_operand" "") + (if_then_else:SI (match_operator 6 "rx_z_comparison_operator" + [(reg:CC_ZS CC_REG) (const_int 0)]) + (match_operand:SI 4 "immediate_operand" "") + (match_operand:SI 5 "register_operand" "")))] + "rtx_equal_p (operands[3], operands[5]) && INTVAL (operands[4]) == 0 && + ((GET_CODE (operands[6]) == EQ) || (GET_CODE (operands[6]) == NE))" + [(set (reg:CC_ZS CC_REG) + (compare:CC_ZS (and:SI (match_dup 3) (match_dup 1)) (const_int 0))) + (set (match_dup 3) + (if_then_else:SI (match_operator 8 "rx_z_comparison_operator" + [(reg:CC_ZS CC_REG) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + { + /* Invert the condition: EQ -> NE, NE -> EQ */ + if (GET_CODE (operands[6]) == EQ) + operands[8] = gen_rtx_NE (VOIDmode, operands[6], const0_rtx); + else /* NE */ + operands[8] = gen_rtx_EQ (VOIDmode, operands[6], const0_rtx); + } +) + +;;====XCHG Peepholes==== + +(define_peephole2 + [ + (set (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "rx_compare_operand" "")) + (set (match_dup 1) + (match_operand:SI 2 "register_operand" "")) + (set (match_dup 2) (match_dup 0)) + ] + "REG_P(operands[0]) && (REG_P(operands[1]) || MEM_P(operands[1])) && REG_P(operands[2]) && peep2_regno_dead_p (3, REGNO (operands[0]))" + [(unspec_volatile:SI [(match_dup 2) (match_dup 1)] UNSPEC_BUILTIN_XCHG)] +) + +(define_peephole2 + [ + (set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:HI 1 "rx_compare_operand" ""))) + (set (match_dup 1) + (match_operand:HI 2 "register_operand" "")) + (set (match_dup 2) (match_operand:HI 3 "register_operand" "")) + ] + "REG_P(operands[0]) && (REG_P(operands[1]) || MEM_P(operands[1])) && REG_P(operands[2]) && (REGNO (operands[0]) == REGNO (operands[3])) && peep2_regno_dead_p (3, REGNO (operands[0]))" + [(unspec_volatile:SI [(match_dup 2) (match_dup 1)] UNSPEC_BUILTIN_XCHG)] +) + +(define_peephole2 + [ + (set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:QI 1 "rx_compare_operand" ""))) + (set (match_dup 1) + (match_operand:QI 2 "register_operand" "")) + (set (match_dup 2) (match_operand:QI 3 "register_operand" "")) + ] + "REG_P(operands[0]) && (REG_P(operands[1]) || MEM_P(operands[1])) && REG_P(operands[2]) && (REGNO (operands[0]) == REGNO (operands[3])) && peep2_regno_dead_p (3, REGNO (operands[0]))" + [(unspec_volatile:SI [(match_dup 2) (match_dup 1)] UNSPEC_BUILTIN_XCHG)] +) + +;; mov.L [ra], rt +;; add rv, rt +;; mov.L rt, [ra] +;; to: +;; add [ra], rv +;; mov.L rv, [ra] +(define_peephole2 + [(set (match_operand:SI 0 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" ""))) + (parallel [(set (match_dup 0) + (plus:SI (match_dup 0) + (match_operand:SI 2 "register_operand" ""))) + (clobber (reg:CC CC_REG))]) + (set (mem:SI (match_dup 1)) + (match_dup 0))] + "REG_P(operands[0]) && REG_P(operands[1]) && REG_P(operands[2]) && (REGNO(operands[0]) != REGNO(operands[2])) && + peep2_regno_dead_p(3, REGNO(operands[0])) && peep2_regno_dead_p(3, REGNO(operands[2]))" + [(parallel [(set (match_dup 2) + (plus:SI (match_dup 2) + (mem:SI (match_dup 1)))) + (clobber (reg:CC CC_REG))]) + (set (mem:SI (match_dup 1)) + (match_dup 2))] + "" ) diff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt index 949ed9e83be87..937c2140663db 100644 --- a/gcc/config/rx/rx.opt +++ b/gcc/config/rx/rx.opt @@ -24,12 +24,14 @@ config/rx/rx-opts.h ; The default is -fpu -m32bit-doubles. +; -dfpu enables -m64bit-doubles. + m64bit-doubles Target RejectNegative Mask(64BIT_DOUBLES) Store doubles in 64 bits. m32bit-doubles -Target RejectNegative InverseMask(64BIT_DOUBLES) +Target RejectNegative Mask(32BIT_DOUBLES) Stores doubles in 32 bits. This is the default. nofpu @@ -43,10 +45,27 @@ fpu Target RejectNegative InverseMask(NO_USE_FPU) Enable the use of RX FPU instructions. This is the default. +mdfpu +Target RejectNegative Var(flag_dfpu) Init(0) +Enable the use of RX DFPU instructions. + +mtfu= +Target RejectNegative Joined Var(rx_tfu_type) ToLower Enum(rx_tfu_types) Init(RX_TFUUNINIT) +Enable the use of RX TFU instructions. + +Enum +Name(rx_tfu_types) Type(enum rx_tfu_types) + +EnumValue +Enum(rx_tfu_types) String(intrinsic) Value(RX_INTRINSIC) + +EnumValue +Enum(rx_tfu_types) String(intrinsic,mathlib) Value(RX_MATHLIB) + ;--------------------------------------------------- mcpu= -Target RejectNegative Joined Var(rx_cpu_type) ToLower Enum(rx_cpu_types) Init(RX600) +Target RejectNegative Joined Var(rx_cpu_type) ToLower Enum(rx_cpu_types) Init(RX_CPUUNINIT) Specify the target RX cpu type. Enum @@ -64,6 +83,66 @@ Enum(rx_cpu_types) String(rx600) Value(RX600) EnumValue Enum(rx_cpu_types) String(rx100) Value(RX100) +EnumValue +Enum(rx_cpu_types) String(rx64m) Value(RX64M) + +EnumValue +Enum(rx_cpu_types) String(rx66t) Value(RX66T) + +EnumValue +Enum(rx_cpu_types) String(rx71m) Value(RX71M) + +EnumValue +Enum(rx_cpu_types) String(rx72t) Value(RX72T) + +EnumValue +Enum(rx_cpu_types) String(rx230) Value(RX230) + +EnumValue +Enum(rx_cpu_types) String(rx13t) Value(RX13T) + +EnumValue +Enum(rx_cpu_types) String(rx140) Value(RX140) +;--------------------------------------------------- + +mnosave-tfu +Target RejectNegative Mask(NO_SAVE_TFU) Undocumented +Code for saving and restoring the output of the trigonometric function unit (v2) is generated for all interrupt functions. + + +;--------------------------------------------------- + +mtfu-version= +Target RejectNegative Joined Var(rx_tfu_version) ToLower Enum(rx_tfu_versions) Init(RX_TFUVUNINIT) +Specify RX TFU version. + +Enum +Name(rx_tfu_versions) Type(enum rx_tfu_versions) + +EnumValue +Enum(rx_tfu_versions) String(v1) Value(RX_TFUV1) + +EnumValue +Enum(rx_tfu_versions) String(v2) Value(RX_TFUV2) + +;--------------------------------------------------- + +misa= +Target RejectNegative Joined Var(rx_isa_version) ToLower Enum(rx_isa_versions) Init(RX_ISAUNINIT) +Specify RX ISA version. + +Enum +Name(rx_isa_versions) Type(enum rx_isa_versions) + +EnumValue +Enum(rx_isa_versions) String(v1) Value(RX_ISAV1) + +EnumValue +Enum(rx_isa_versions) String(v2) Value(RX_ISAV2) + +EnumValue +Enum(rx_isa_versions) String(v3) Value(RX_ISAV3) + ;--------------------------------------------------- mbig-endian-data @@ -83,7 +162,7 @@ Maximum size of global and static variables which can be placed into the small d ;--------------------------------------------------- mrelax -Target +Target Mask(RELAX) Enable linker relaxation. ;--------------------------------------------------- @@ -94,18 +173,6 @@ Maximum size in bytes of constant values allowed as operands. ;--------------------------------------------------- -mint-register= -Target RejectNegative Joined UInteger Var(rx_deferred_options) Defer -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. - -;--------------------------------------------------- - mpid Target Mask(PID) Enables Position-Independent-Data (PID) mode. @@ -118,10 +185,6 @@ Warn when multiple, different, fast interrupt handlers are in the compilation un ;--------------------------------------------------- -mgcc-abi -Target RejectNegative Mask(GCC_ABI) -Enable the use of the old, broken, ABI where all stacked function arguments are aligned to 32-bits. - mrx-abi Target RejectNegative InverseMask(GCC_ABI) Enable the use the standard RX ABI where all stacked function arguments are naturally aligned. This is the default. @@ -140,6 +203,29 @@ Enables or disables the use of the SMOVF, SMOVB, SMOVU, SUNTIL, SWHILE and RMPA ;--------------------------------------------------- +mno-balign +Target RejectNegative Mask(NOBALIGN) +Do not use .balign + +;--------------------------------------------------- + +mrxv2-fsqrt +Target RejectNegative Mask(RX_SQRT) +Enable to use of FSQRT hardware instruction for RXv2 instruction set + +;--------------------------------------------------- + +morder +Target Undocumented Joined Var(flag_morder) MissingArgError(Please use morder0, morder1 or morder2. The default is morder0) + +;--------------------------------------------------- + mjsr Target Mask(JSR) Always use JSR, never BSR, for calls. + +;--------------------------------------------------- + +mrxpeephole +Target Var(flag_rxpeephole) Init(0) +Coremark improvement. diff --git a/gcc/config/rx/rx.opt.urls b/gcc/config/rx/rx.opt.urls index 7af4bd249d82b..931a4aee170a3 100644 --- a/gcc/config/rx/rx.opt.urls +++ b/gcc/config/rx/rx.opt.urls @@ -12,9 +12,24 @@ UrlSuffix(gcc/RX-Options.html#index-nofpu) fpu UrlSuffix(gcc/RX-Options.html#index-fpu) +mdfpu +UrlSuffix(gcc/RX-Options.html#index-mdfpu) + +mtfu= +UrlSuffix(gcc/RX-Options.html#index-mtfu) + mcpu= UrlSuffix(gcc/RX-Options.html#index-mcpu-11) +mnosave-tfu +UrlSuffix(gcc/RX-Options.html#index-mnosave-tfu) + +mtfu-version= +UrlSuffix(gcc/RX-Options.html#index-mtfu-version) + +misa= +UrlSuffix(gcc/RX-Options.html#index-misa-1) + mbig-endian-data UrlSuffix(gcc/RX-Options.html#index-mbig-endian-data) @@ -30,25 +45,27 @@ UrlSuffix(gcc/RX-Options.html#index-mrelax-7) mmax-constant-size= UrlSuffix(gcc/RX-Options.html#index-mmax-constant-size) -mint-register= -UrlSuffix(gcc/RX-Options.html#index-mint-register) - -msave-acc-in-interrupts -UrlSuffix(gcc/RX-Options.html#index-msave-acc-in-interrupts) - mpid UrlSuffix(gcc/RX-Options.html#index-mpid) mwarn-multiple-fast-interrupts UrlSuffix(gcc/RX-Options.html#index-mwarn-multiple-fast-interrupts) -; skipping UrlSuffix for 'mgcc-abi' due to finding no URLs - -; skipping UrlSuffix for 'mlra' due to finding no URLs +mlra +UrlSuffix(gcc/RX-Options.html#index-mlra-3) mallow-string-insns UrlSuffix(gcc/RX-Options.html#index-mallow-string-insns) +mno-balign +UrlSuffix(gcc/RX-Options.html#index-mno-balign) + +mrxv2-fsqrt +UrlSuffix(gcc/RX-Options.html#index-mrxv2-fsqrt) + +morder +UrlSuffix(gcc/RX-Options.html#index-morder) + mjsr UrlSuffix(gcc/RX-Options.html#index-mjsr) diff --git a/gcc/config/rx/t-rx b/gcc/config/rx/t-rx index 72b9e31e4b0a7..c837fcec44ca5 100644 --- a/gcc/config/rx/t-rx +++ b/gcc/config/rx/t-rx @@ -18,20 +18,131 @@ # License along with GCC; see the file COPYING3. If not see # . +rx-pragma.o: $(srcdir)/config/rx/rx-pragma.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< + # Enable multilibs: -MULTILIB_OPTIONS = m64bit-doubles mnofpu mbig-endian-data mpid -MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data pid +MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data mjsr mdfpu +MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data jsr dfpu # If necessary uncomment the next two lines to generate multilibs # using the old, broken, ABI. # MULTILIB_OPTIONS += mgcc-abi # MULTILIB_DIRNAMES += gcc-abi + MULTILIB_OPTIONS += mno-allow-string-insns MULTILIB_DIRNAMES += no-strings + +MULTILIB_OPTIONS += mcpu=rx64m +MULTILIB_DIRNAMES += rxv2 + MULTILIB_MATCHES = nofpu=mnofpu nofpu=mcpu?rx200 nofpu=mcpu?rx100 MULTILIB_EXCEPTIONS = MULTILIB_EXTRA_OPTS = + +MULTILIB_OPTIONS += misa=v3 +MULTILIB_DIRNAMES += rxv3 +MULTILIB_EXCEPTIONS += *mcpu=*/*misa=v3* + +MULTILIB_REQUIRED = +MULTILIB_REQUIRED += m64bit-doubles +MULTILIB_REQUIRED += nofpu +MULTILIB_REQUIRED += mbig-endian-data +MULTILIB_REQUIRED += mjsr +MULTILIB_REQUIRED += mno-allow-string-insns +MULTILIB_REQUIRED += mcpu=rx64m +MULTILIB_REQUIRED += misa=v3 +MULTILIB_REQUIRED += mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += mjsr/mcpu=rx64m +MULTILIB_REQUIRED += mjsr/misa=v3 +MULTILIB_REQUIRED += mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mjsr +MULTILIB_REQUIRED += mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data +MULTILIB_REQUIRED += nofpu/mjsr +MULTILIB_REQUIRED += nofpu/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/misa=v3 +MULTILIB_REQUIRED += nofpu/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mjsr/misa=v3 +MULTILIB_REQUIRED += nofpu/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data +MULTILIB_REQUIRED += m64bit-doubles/mjsr +MULTILIB_REQUIRED += m64bit-doubles/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 + +MULTILIB_REQUIRED += m64bit-doubles/mdfpu/misa=v3 diff --git a/gcc/config/rx/t-zephyr b/gcc/config/rx/t-zephyr index cad0d02a5eb05..23a4e3a1798de 100644 --- a/gcc/config/rx/t-zephyr +++ b/gcc/config/rx/t-zephyr @@ -1,5 +1,5 @@ # Makefile fragment for building GCC for the Renesas RX target. -# Copyright (C) 2008-2022 Free Software Foundation, Inc. +# Copyright (C) 2008-2024 Free Software Foundation, Inc. # Contributed by Red Hat. # # This file is part of GCC. @@ -18,20 +18,131 @@ # License along with GCC; see the file COPYING3. If not see # . +rx-pragma.o: $(srcdir)/config/rx/rx-pragma.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< + # Enable multilibs: -MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data mpid -MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data pid +MULTILIB_OPTIONS = m64bit-doubles nofpu mbig-endian-data mjsr mdfpu +MULTILIB_DIRNAMES = 64-bit-double no-fpu-libs big-endian-data jsr dfpu # If necessary uncomment the next two lines to generate multilibs # using the old, broken, ABI. # MULTILIB_OPTIONS += mgcc-abi # MULTILIB_DIRNAMES += gcc-abi + MULTILIB_OPTIONS += mno-allow-string-insns MULTILIB_DIRNAMES += no-strings + +MULTILIB_OPTIONS += mcpu=rx64m +MULTILIB_DIRNAMES += rxv2 + MULTILIB_MATCHES = nofpu=mnofpu nofpu=mcpu?rx200 nofpu=mcpu?rx100 MULTILIB_EXCEPTIONS = MULTILIB_EXTRA_OPTS = + +MULTILIB_OPTIONS += misa=v3 +MULTILIB_DIRNAMES += rxv3 +MULTILIB_EXCEPTIONS += *mcpu=*/*misa=v3* + +MULTILIB_REQUIRED = +MULTILIB_REQUIRED += m64bit-doubles +MULTILIB_REQUIRED += nofpu +MULTILIB_REQUIRED += mbig-endian-data +MULTILIB_REQUIRED += mjsr +MULTILIB_REQUIRED += mno-allow-string-insns +MULTILIB_REQUIRED += mcpu=rx64m +MULTILIB_REQUIRED += misa=v3 +MULTILIB_REQUIRED += mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += mjsr/mcpu=rx64m +MULTILIB_REQUIRED += mjsr/misa=v3 +MULTILIB_REQUIRED += mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mjsr +MULTILIB_REQUIRED += mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data +MULTILIB_REQUIRED += nofpu/mjsr +MULTILIB_REQUIRED += nofpu/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/misa=v3 +MULTILIB_REQUIRED += nofpu/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mjsr/misa=v3 +MULTILIB_REQUIRED += nofpu/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data +MULTILIB_REQUIRED += m64bit-doubles/mjsr +MULTILIB_REQUIRED += m64bit-doubles/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mjsr/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mno-allow-string-insns/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mno-allow-string-insns +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/misa=v3 +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/mcpu=rx64m +MULTILIB_REQUIRED += m64bit-doubles/nofpu/mbig-endian-data/mjsr/mno-allow-string-insns/misa=v3 + +MULTILIB_REQUIRED += m64bit-doubles/mdfpu/misa=v3 diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 19481c07db6a4..d700daa09e5f1 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -440,7 +440,7 @@ (define_attr "needs_delay_slot" "yes,no" (const_string "no")) -(define_attr "banked" "yes,no" +(define_attr "banked" "yes,no" (cond [(match_test "sh_loads_bankedreg_p (insn)") (const_string "yes")] (const_string "no"))) @@ -1653,7 +1653,7 @@ (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))]) -;; The tree optimiziers canonicalize +;; The tree optimiziers canonicalize ;; reg + (reg & 1) ;; into ;; (reg + 1) & -2 @@ -3086,7 +3086,7 @@ rtx tmp_t_reg = NULL_RTX; /* If we're going to emit a shift sequence that clobbers the T_REG, - try to find the previous insn that sets the T_REG and emit the + try to find the previous insn that sets the T_REG and emit the shift insn before that insn, to remove the T_REG dependency. If the insn that sets the T_REG cannot be found, store the T_REG in a temporary reg and restore it after the shift. */ @@ -3118,7 +3118,7 @@ prev_set_t_insn = NULL; tmp_t_reg = gen_reg_rtx (SImode); emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); - } + } } rtx shift_result = gen_reg_rtx (SImode); @@ -3188,7 +3188,7 @@ rtx tmp_t_reg = NULL_RTX; /* If we're going to emit a shift sequence that clobbers the T_REG, - try to find the previous insn that sets the T_REG and emit the + try to find the previous insn that sets the T_REG and emit the shift insn before that insn, to remove the T_REG dependency. If the insn that sets the T_REG cannot be found, store the T_REG in a temporary reg and restore it after the shift. */ @@ -3219,7 +3219,7 @@ prev_set_t_insn = NULL; tmp_t_reg = gen_reg_rtx (SImode); emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ())); - } + } } rtx shift_result = gen_reg_rtx (SImode); @@ -3737,8 +3737,8 @@ rtx tmp1 = gen_reg_rtx (SImode); emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2])))); - emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2])); - emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2])); + emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2])); + emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2])); emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1)); emit_move_insn (operands[0], dst); DONE; @@ -4560,7 +4560,7 @@ emit_move_insn (operands[0], operands[1]); - emit_jump_insn (INTVAL (operands[3]) + emit_jump_insn (INTVAL (operands[3]) ? gen_branch_true (skip_neg_label) : gen_branch_false (skip_neg_label)); @@ -5843,7 +5843,7 @@ XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr); insn = emit_insn (gen_movsf_ie (reg0, mem2)); add_reg_note (insn, REG_INC, XEXP (addr, 0)); - + emit_insn (gen_movsf_ie (reg1, operands[1])); /* If we have modified the stack pointer, the value that we have @@ -5912,7 +5912,7 @@ operands[0] = copy_rtx (operands[0]); XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr); - + insn = emit_insn (gen_movsf_ie (operands[0], reg0)); add_reg_note (insn, REG_INC, XEXP (addr, 0)); break; @@ -6570,7 +6570,7 @@ [(const_int 0)] { rtx lab = PATTERN (gen_call_site ()); - + sh_expand_sym_label2reg (operands[2], operands[0], lab, false); emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab))); DONE; @@ -8180,7 +8180,7 @@ if (! currently_expanding_to_rtl) FAIL; - + sh_emit_compare_and_set (operands, SImode); DONE; }) @@ -8197,7 +8197,7 @@ if (! currently_expanding_to_rtl) FAIL; - + sh_emit_compare_and_set (operands, DImode); DONE; }) @@ -8567,7 +8567,7 @@ { if (! currently_expanding_to_rtl) FAIL; - + sh_emit_compare_and_set (operands, SFmode); DONE; }) @@ -8581,7 +8581,7 @@ { if (! currently_expanding_to_rtl) FAIL; - + sh_emit_compare_and_set (operands, DFmode); DONE; }) @@ -10483,7 +10483,7 @@ ;; The following peepholes fold load sequences for which reload was not ;; able to generate a displacement addressing move insn. -;; This can happen when reload has to transform a move insn +;; This can happen when reload has to transform a move insn ;; without displacement into one with displacement. Or when reload can't ;; fit a displacement into the insn's constraints. In the latter case, the ;; load destination reg remains at r0, which reload compensates by inserting @@ -10790,12 +10790,12 @@ sh_remove_overlapping_post_inc (operands[2], operands[3]))); recog_data_d prev_recog_data = recog_data; - bool i_invalid = insn_invalid_p (i, false); + bool i_invalid = insn_invalid_p (i, false); recog_data = prev_recog_data; - + if (i_invalid) FAIL; - + sh_check_add_incdec_notes (i); emit_insn (gen_tstsi_t (operands[2], @@ -10830,14 +10830,14 @@ sh_remove_overlapping_post_inc (operands[2], operands[3]))); recog_data_d prev_recog_data = recog_data; - bool i_invalid = insn_invalid_p (i, false); + bool i_invalid = insn_invalid_p (i, false); recog_data = prev_recog_data; - + if (i_invalid) FAIL; - + sh_check_add_incdec_notes (i); - + emit_insn (gen_tstsi_t (operands[2], gen_rtx_REG (SImode, (REGNO (operands[1]))))); }) diff --git a/libgcc/config/rx/rx-lib.h b/libgcc/config/rx/rx-lib.h index c83516fd64b0e..208962c68d9e6 100644 --- a/libgcc/config/rx/rx-lib.h +++ b/libgcc/config/rx/rx-lib.h @@ -1,5 +1,10 @@ -#ifndef __RX_64BIT_DOUBLES__ +#if defined __RX_64BIT_DOUBLES__ +#undef FLOAT_ONLY +#elif defined __RX_32BIT_DOUBLES__ #define DF SF #define FLOAT_ONLY +#else +#error "RX double size not defined" #endif +#define LIBGCC2_FLOAT_BIT_ORDER_MISMATCH 0