From: Nick Clifton Date: Wed, 30 Jun 2010 08:50:14 +0000 (+0000) Subject: rx-modes.def: New file. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aea8fc973762254dfd518d202975bc043aba4ba9;p=gcc.git rx-modes.def: New file. * config/rx/rx-modes.def: New file. * config/rx/rx.h (FIRST_PSEUDO_REGISTER): Increase to 17. (CC_REGNUM): Define. (FIXED_REGISTERS, CALL_USED_REGISTERS, REGISTER_NAMES): Add cc register. (CC_NO_CARRY, NOTICE_UPDATE_CC): Delete. (SELECT_CC_MODE): Define. * config/rx/rx.md (CC_REG): Define. Update all patterns to use (reg:CC CC_REG) instead of (cc0). (attr "cc"): Delete. (cbranchsi4): Do not split compare and branch here. Instead move it to... (cbranchsi4_): ... here. New patterns. (cmpsi): Call rx-compare_redundant to find out if it is necessary to emit the compare instruction. * config/rx/rx.c (rx_gen-cond_branch_template): Remove tests of cc_status flags. (rx_get_stack_layout): Iterate up to before CC_REGNUM not FIRST_PSEUDO_REGNUM. (rx_expand_prologue, rx_expand_epilogue): Likewise. (rx_notice_update_cc): Delete. (rx_cc_modes_compatible): New function. (flags_needed_for_conditional): New function. (flags_from_mode): New function. (rx_compare_redundant): New function - scans backwards through insn list to find out if condition flags are already set correctly. (TARGET_CC_MODES_COMPATIBLE): Define. * config/rx/rx-protos.h (rx_compare_redundant): Prototype. * config/rx/rx.h (BRANCH_COST): Define. (REGISTER_MOVE_COST): Define. * config/rx/predicates (rx_source_operand): Allow all constant types. * config/rx/rx.md (addsi3): Add alternative for swapped operands. (tstsi4): New pattern. * config/rx/rx.c (rx_memory_move_cost): Define. (TARGET_MEMORY_MOVE_COST): Define. From-SVN: r161592 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb8f81e5223..bd7f730d6c2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,44 @@ +2010-06-30 Nick Clifton + + * config/rx/rx-modes.def: New file. + * config/rx/rx.h (FIRST_PSEUDO_REGISTER): Increase to 17. + (CC_REGNUM): Define. + (FIXED_REGISTERS, CALL_USED_REGISTERS, REGISTER_NAMES): Add cc + register. + (CC_NO_CARRY, NOTICE_UPDATE_CC): Delete. + (SELECT_CC_MODE): Define. + * config/rx/rx.md (CC_REG): Define. Update all patterns to use + (reg:CC CC_REG) instead of (cc0). + (attr "cc"): Delete. + (cbranchsi4): Do not split compare and branch here. Instead move + it to... + (cbranchsi4_): ... here. New patterns. + (cmpsi): Call rx-compare_redundant to find out if it is necessary + to emit the compare instruction. + * config/rx/rx.c (rx_gen-cond_branch_template): Remove tests of + cc_status flags. + (rx_get_stack_layout): Iterate up to before CC_REGNUM not + FIRST_PSEUDO_REGNUM. + (rx_expand_prologue, rx_expand_epilogue): Likewise. + (rx_notice_update_cc): Delete. + (rx_cc_modes_compatible): New function. + (flags_needed_for_conditional): New function. + (flags_from_mode): New function. + (rx_compare_redundant): New function - scans backwards through + insn list to find out if condition flags are already set + correctly. + (TARGET_CC_MODES_COMPATIBLE): Define. + * config/rx/rx-protos.h (rx_compare_redundant): Prototype. + + * config/rx/rx.h (BRANCH_COST): Define. + (REGISTER_MOVE_COST): Define. + * config/rx/predicates (rx_source_operand): Allow all constant + types. + * config/rx/rx.md (addsi3): Add alternative for swapped operands. + (tstsi4): New pattern. + * config/rx/rx.c (rx_memory_move_cost): Define. + (TARGET_MEMORY_MOVE_COST): Define. + 2010-06-30 Manuel López-Ibáñez * tree.h (block_may_fallthru): Declare here. diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md index d7a363ebb88..94e5f5630c2 100644 --- a/gcc/config/rx/predicates.md +++ b/gcc/config/rx/predicates.md @@ -50,9 +50,9 @@ ;; and a restricted subset of memory addresses are allowed. (define_predicate "rx_source_operand" - (match_code "const_int,reg,mem") + (match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem") { - if (CONST_INT_P (op)) + if (CONSTANT_P (op)) return rx_is_legitimate_constant (op); if (! MEM_P (op)) diff --git a/gcc/config/rx/rx-modes.def b/gcc/config/rx/rx-modes.def new file mode 100644 index 00000000000..5936b672b6b --- /dev/null +++ b/gcc/config/rx/rx-modes.def @@ -0,0 +1,26 @@ +/* Definitions of target machine for GNU compiler, for ARM. + Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc. + Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) + and Martin Simmons (@harleqn.co.uk). + More major hacks by Richard Earnshaw (rearnsha@arm.com) + Minor hacks by Nick Clifton (nickc@cygnus.com) + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +CC_MODE (CC_ZS); +CC_MODE (CC_ZSO); +CC_MODE (CC_ZSC); diff --git a/gcc/config/rx/rx-protos.h b/gcc/config/rx/rx-protos.h index a2a28c12579..166290de5e7 100644 --- a/gcc/config/rx/rx-protos.h +++ b/gcc/config/rx/rx-protos.h @@ -31,6 +31,7 @@ extern int rx_initial_elimination_offset (int, int); extern void rx_set_optimization_options (void); #ifdef RTX_CODE +extern bool rx_compare_redundant (rtx); extern void rx_emit_stack_popm (rtx *, bool); extern void rx_emit_stack_pushm (rtx *); extern void rx_expand_epilogue (bool); diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 8d9e462dd5c..2219efe8559 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -707,12 +707,6 @@ rx_gen_cond_branch_template (rtx condition, bool reversed) { enum rtx_code code = GET_CODE (condition); - if ((cc_status.flags & CC_NO_OVERFLOW) && ! rx_float_compare_mode) - gcc_assert (code != GT && code != GE && code != LE && code != LT); - - if ((cc_status.flags & CC_NO_CARRY) || rx_float_compare_mode) - gcc_assert (code != GEU && code != GTU && code != LEU && code != LTU); - if (reversed) { if (rx_float_compare_mode) @@ -1063,7 +1057,7 @@ rx_get_stack_layout (unsigned int * lowest, return; } - for (save_mask = high = low = 0, reg = 1; reg < FIRST_PSEUDO_REGISTER; reg++) + for (save_mask = high = low = 0, reg = 1; reg < CC_REGNUM; reg++) { if (df_regs_ever_live_p (reg) && (! call_used_regs[reg] @@ -1241,7 +1235,7 @@ rx_expand_prologue (void) if (mask) { /* Push registers in reverse order. */ - for (reg = FIRST_PSEUDO_REGISTER; reg --;) + for (reg = CC_REGNUM; reg --;) if (mask & (1 << reg)) { insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg))); @@ -1270,7 +1264,7 @@ rx_expand_prologue (void) { acc_low = acc_high = 0; - for (reg = 1; reg < FIRST_PSEUDO_REGISTER; reg ++) + for (reg = 1; reg < CC_REGNUM; reg ++) if (mask & (1 << reg)) { if (acc_low == 0) @@ -1543,7 +1537,8 @@ rx_expand_epilogue (bool is_sibcall) if (register_mask) { acc_low = acc_high = 0; - for (reg = 1; reg < FIRST_PSEUDO_REGISTER; reg ++) + + for (reg = 1; reg < CC_REGNUM; reg ++) if (register_mask & (1 << reg)) { if (acc_low == 0) @@ -1574,7 +1569,7 @@ rx_expand_epilogue (bool is_sibcall) if (register_mask) { - for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg ++) + for (reg = 0; reg < CC_REGNUM; reg ++) if (register_mask & (1 << reg)) emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg))); } @@ -1674,54 +1669,6 @@ rx_initial_elimination_offset (int from, int to) return stack_size; } -/* Update the status of the condition - codes (cc0) based on the given INSN. */ - -void -rx_notice_update_cc (rtx body, rtx insn) -{ - switch (get_attr_cc (insn)) - { - case CC_NONE: - /* Insn does not affect cc0 at all. */ - break; - case CC_CLOBBER: - /* Insn doesn't leave cc0 in a usable state. */ - CC_STATUS_INIT; - break; - case CC_SET_ZSOC: - /* The insn sets all the condition code bits. */ - CC_STATUS_INIT; - cc_status.value1 = SET_DEST (body); - break; - case CC_SET_ZSO: - /* Insn sets the Z,S and O flags, but not the C flag. */ - CC_STATUS_INIT; - cc_status.flags |= CC_NO_CARRY; - /* Do not set the value1 field in this case. The final_scan_insn() - function naively believes that if cc_status.value1 is set then - it can eliminate *any* comparison against that value, even if - the type of comparison cannot be satisfied by the range of flag - bits being set here. See gcc.c-torture/execute/20041210-1.c - for an example of this in action. */ - break; - case CC_SET_ZSC: - /* Insn sets the Z,S and C flags, but not the O flag. */ - CC_STATUS_INIT; - cc_status.flags |= CC_NO_OVERFLOW; - /* See comment above regarding cc_status.value1. */ - break; - case CC_SET_ZS: - /* Insn sets the Z and S flags, but not the O or C flags. */ - CC_STATUS_INIT; - cc_status.flags |= (CC_NO_CARRY | CC_NO_OVERFLOW); - /* See comment above regarding cc_status.value1. */ - break; - default: - gcc_unreachable (); - } -} - /* Decide if a variable should go into one of the small data sections. */ static bool @@ -2517,6 +2464,220 @@ rx_trampoline_init (rtx tramp, tree fndecl, rtx chain) } } + +static enum machine_mode +rx_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) +{ + if (m1 == CCmode) + return m2; + if (m2 == CCmode) + return m1; + if (m1 == m2) + return m1; + if (m1 == CC_ZSmode) + return m1; + if (m2 == CC_ZSmode) + return m2; + return VOIDmode; +} + +#define CC_FLAG_S (1 << 0) +#define CC_FLAG_Z (1 << 1) +#define CC_FLAG_O (1 << 2) +#define CC_FLAG_C (1 << 3) + +static unsigned int +flags_needed_for_conditional (rtx conditional) +{ + switch (GET_CODE (conditional)) + { + case LE: + case GT: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O; + + case LEU: + case GTU: return CC_FLAG_Z | CC_FLAG_C; + + case LT: + case GE: return CC_FLAG_S | CC_FLAG_O; + + case LTU: + case GEU: return CC_FLAG_C; + + case EQ: + case NE: return CC_FLAG_Z; + + default: gcc_unreachable (); + } +} + +static unsigned int +flags_from_mode (enum machine_mode mode) +{ + switch (mode) + { + case CCmode: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O | CC_FLAG_C; + case CC_ZSmode: return CC_FLAG_S | CC_FLAG_Z; + case CC_ZSOmode: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_O; + case CC_ZSCmode: return CC_FLAG_S | CC_FLAG_Z | CC_FLAG_C; + default: gcc_unreachable (); + } +} + +/* Returns true if a compare insn is redundant because it + would only set flags that are already set correctly. */ + +bool +rx_compare_redundant (rtx cmp) +{ + unsigned int flags_needed; + unsigned int flags_set; + rtx next; + rtx prev; + rtx source; + rtx dest; + static rtx cc_reg = NULL_RTX; + + if (cc_reg == NULL_RTX) + cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); + + /* We can only eliminate compares against 0. */ + if (GET_CODE (XEXP (SET_SRC (PATTERN (cmp)), 1)) != CONST_INT + || INTVAL (XEXP (SET_SRC (PATTERN (cmp)), 1)) != 0) + return false; + + /* Locate the branch insn that follows the + compare and which tests the bits in the PSW. */ + next = cmp; + do + { + /* If we have found an insn that sets or clobbers the CC + register and it was not the IF_THEN_ELSE insn that we + are looking for, then the comparison is redundant. */ + if (next != cmp && reg_mentioned_p (cc_reg, PATTERN (next))) + return true; + + next = next_nonnote_insn (next); + + /* If we run out of insns without finding the + user then the comparison is unnecessary. */ + if (next == NULL_RTX) + return true; + + /* If we have found another comparison + insn then the first one is redundant. */ + if (INSN_P (next) + && GET_CODE (PATTERN (next)) == SET + && REG_P (SET_DEST (PATTERN (next))) + && REGNO (SET_DEST (PATTERN (next))) == CC_REGNUM) + return true; + + /* If we have found another arithmetic/logic insn that + sets the PSW flags then the comparison is redundant. */ + if (INSN_P (next) + && GET_CODE (PATTERN (next)) == PARALLEL + && GET_CODE (XVECEXP (PATTERN (next), 0, 1)) == SET + && REG_P (SET_DEST (XVECEXP (PATTERN (next), 0, 1))) + && REGNO (SET_DEST (XVECEXP (PATTERN (next), 0, 1))) == CC_REGNUM) + return true; + + /* If we have found an unconditional branch then the + PSW flags might be carried along with the jump, so + the comparison is necessary. */ + if (INSN_P (next) && JUMP_P (next)) + { + if (GET_CODE (PATTERN (next)) != SET) + /* If the jump does not involve setting the PC + then it is a return of some kind, and we know + that the comparison is not used. */ + return true; + + if (GET_CODE (SET_SRC (PATTERN (next))) != IF_THEN_ELSE) + return false; + } + } + while (! INSN_P (next) + || DEBUG_INSN_P (next) + || GET_CODE (PATTERN (next)) != SET + || GET_CODE (SET_SRC (PATTERN (next))) != IF_THEN_ELSE); + + flags_needed = flags_needed_for_conditional (XEXP (SET_SRC (PATTERN (next)), 0)); + + /* Now look to see if there was a previous + instruction which set the PSW bits. */ + source = XEXP (SET_SRC (PATTERN (cmp)), 0); + prev = cmp; + do + { + /* If this insn uses/sets/clobbers the CC register + and it is not the insn that we are looking for + below, then we must need the comparison. */ + if (prev != cmp && reg_mentioned_p (cc_reg, PATTERN (prev))) + return false; + + prev = prev_nonnote_insn (prev); + + if (prev == NULL_RTX) + return false; + + /* If we encounter an insn which changes the contents of + the register which is the source of the comparison then + we will definitely need the comparison. */ + if (INSN_P (prev) + && GET_CODE (PATTERN (prev)) == SET + && rtx_equal_p (SET_DEST (PATTERN (prev)), source)) + { + /* Unless this instruction is a simple register move + instruction. In which case we can continue our + scan backwards, but now using the *source* of this + set instruction. */ + if (REG_P (SET_SRC (PATTERN (prev)))) + source = SET_SRC (PATTERN (prev)); + /* We can also survive a sign-extension if the test is + for EQ/NE. Note the same does not apply to zero- + extension as this can turn a non-zero bit-pattern + into zero. */ + else if (flags_needed == CC_FLAG_Z + && GET_CODE (SET_SRC (PATTERN (prev))) == SIGN_EXTEND) + source = XEXP (SET_SRC (PATTERN (prev)), 0); + else + return false; + } + + /* A label means a possible branch into the + code here, so we have to stop scanning. */ + if (LABEL_P (prev)) + return false; + } + while (! INSN_P (prev) + || DEBUG_INSN_P (prev) + || GET_CODE (PATTERN (prev)) != PARALLEL + || GET_CODE (XVECEXP (PATTERN (prev), 0, 1)) != SET + || ! REG_P (SET_DEST (XVECEXP (PATTERN (prev), 0, 1))) + || REGNO (SET_DEST (XVECEXP (PATTERN (prev), 0, 1))) != CC_REGNUM); + + flags_set = flags_from_mode (GET_MODE (SET_DEST (XVECEXP (PATTERN (prev), 0, 1)))); + + dest = SET_DEST (XVECEXP (PATTERN (prev), 0, 0)); + /* The destination of the previous arithmetic/logic instruction + must match the source in the comparison operation. For registers + we ignore the mode as there may have been a sign-extension involved. */ + if (! rtx_equal_p (source, dest)) + { + if (REG_P (source) && REG_P (dest) && REGNO (dest) == REGNO (source)) + ; + else + return false; + } + + return ((flags_set & flags_needed) == flags_needed); +} + +static int +rx_memory_move_cost (enum machine_mode mode, enum reg_class regclass, bool in) +{ + return 2 + memory_move_secondary_cost (mode, regclass, in); +} + #undef TARGET_FUNCTION_VALUE #define TARGET_FUNCTION_VALUE rx_function_value @@ -2610,6 +2771,12 @@ rx_trampoline_init (rtx tramp, tree fndecl, rtx chain) #undef TARGET_PRINT_OPERAND_ADDRESS #define TARGET_PRINT_OPERAND_ADDRESS rx_print_operand_address +#undef TARGET_CC_MODES_COMPATIBLE +#define TARGET_CC_MODES_COMPATIBLE rx_cc_modes_compatible + +#undef TARGET_MEMORY_MOVE_COST +#define TARGET_MEMORY_MOVE_COST rx_memory_move_cost + 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 afaa07b0bc5..b3a12690b08 100644 --- a/gcc/config/rx/rx.h +++ b/gcc/config/rx/rx.h @@ -207,7 +207,7 @@ enum reg_class #define BASE_REG_CLASS GR_REGS #define INDEX_REG_CLASS GR_REGS -#define FIRST_PSEUDO_REGISTER 16 +#define FIRST_PSEUDO_REGISTER 17 #define REGNO_REG_CLASS(REGNO) ((REGNO) < FIRST_PSEUDO_REGISTER \ ? GR_REGS : NO_REGS) @@ -219,6 +219,7 @@ enum reg_class #define STATIC_CHAIN_REGNUM 8 #define TRAMPOLINE_TEMP_REGNUM 9 #define STRUCT_VAL_REGNUM 15 +#define CC_REGNUM 16 /* This is the register which is used to hold the address of the start of the small data area, if that feature is being used. Note - this @@ -245,12 +246,12 @@ enum reg_class #define FIXED_REGISTERS \ { \ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 \ } #define CONDITIONAL_REGISTER_USAGE \ @@ -351,7 +352,7 @@ typedef unsigned int CUMULATIVE_ARGS; #define REGISTER_NAMES \ { \ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" \ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc" \ }; #define ADDITIONAL_REGISTER_NAMES \ @@ -609,9 +610,6 @@ typedef unsigned int CUMULATIVE_ARGS; they contain are always computed between two same-section symbols. */ #define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) -#define CC_NO_CARRY 0400 -#define NOTICE_UPDATE_CC(EXP, INSN) rx_notice_update_cc (EXP, INSN) - extern int rx_float_compare_mode; /* This is a version of REG_P that also returns TRUE for SUBREGs. */ @@ -646,3 +644,16 @@ extern int rx_float_compare_mode; /* 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 SELECT_CC_MODE(OP,X,Y) \ + (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CC_ZSmode : \ + (GET_CODE (X) == PLUS || GET_CODE (X) == MINUS ? CC_ZSCmode : \ + (GET_CODE (X) == ABS ? CC_ZSOmode : \ + (GET_CODE (X) == AND || GET_CODE (X) == NOT || GET_CODE (X) == IOR \ + || GET_CODE (X) == XOR || GET_CODE (X) == ROTATE \ + || GET_CODE (X) == ROTATERT || GET_CODE (X) == ASHIFTRT \ + || GET_CODE (X) == LSHIFTRT || GET_CODE (X) == ASHIFT ? CC_ZSmode : \ + CCmode)))) diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 6fe25259472..aeba85ffe39 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -47,6 +47,7 @@ (define_constants [ (SP_REG 0) + (CC_REG 16) (UNSPEC_LOW_REG 0) (UNSPEC_HIGH_REG 1) @@ -86,14 +87,6 @@ ] ) -;; Condition code settings: -;; none - insn does not affect the condition code bits -;; set_zs - insn sets z,s to usable values; -;; set_zso - insn sets z,s,o to usable values; -;; set_zsoc - insn sets z,s,o,c to usable values; -;; clobber - value of cc0 is unknown -(define_attr "cc" "none,set_zs,set_zso,set_zsoc,set_zsc,clobber" (const_string "none")) - (define_attr "length" "" (const_int 8)) (include "predicates.md") @@ -156,77 +149,120 @@ ;; Comparisons +;; Note - we do not specify the two instructions necessary to perform +;; a compare-and-branch in the cbranchsi4 pattern because that would +;; allow the comparison to be moved away from the jump before the reload +;; pass has completed. That would be problematical because reload can +;; generate ADDSI3 instructions which would corrupt the PSW flags. + (define_expand "cbranchsi4" - [(set (cc0) (compare:CC (match_operand:SI 1 "register_operand") - (match_operand:SI 2 "rx_source_operand"))) - (set (pc) - (if_then_else (match_operator:SI 0 "comparison_operator" - [(cc0) (const_int 0)]) + [(set (pc) + (if_then_else (match_operator:SI 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "rx_source_operand")]) (label_ref (match_operand 3 "")) - (pc)))] + (pc))) + ] "" "" ) +(define_insn_and_split "*cbranchsi4_" + [(set (pc) + (if_then_else (most_cond:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "rx_source_operand" "riQ")) + (label_ref (match_operand 2 "" "")) + (pc))) + ] + "" + "#" + "reload_completed" + [(const_int 0)] + " + /* We contstruct the split by hand as otherwise the JUMP_LABEL + attribute is not set correctly on the jump insn. */ + emit_insn (gen_cmpsi (operands[0], operands[1])); + + emit_jump_insn (gen_conditional_branch (operands[2], + gen_rtx_fmt_ee (, CCmode, + gen_rtx_REG (CCmode, CC_REG), const0_rtx))); + " +) + (define_expand "cbranchsf4" - [(set (cc0) (compare:CC (match_operand:SF 1 "register_operand") - (match_operand:SF 2 "rx_source_operand"))) - (set (pc) - (if_then_else (match_operator:SI 0 "comparison_operator" - [(cc0) (const_int 0)]) + [(set (pc) + (if_then_else (match_operator:SF 0 "comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "rx_source_operand")]) (label_ref (match_operand 3 "")) - (pc)))] - "ALLOW_RX_FPU_INSNS && (cfun == NULL || !cfun->can_throw_non_call_exceptions)" + (pc))) + ] + "ALLOW_RX_FPU_INSNS" "" ) -;; The TST instruction is not used as it does not set the Carry flag, -;; so for example, the LessThan comparison cannot be tested. -;; -;; (define_insn "tstsi" -;; [(set (cc0) -;; (match_operand:SI 0 "rx_source_operand" "r,i,Q")))] -;; "" -;; { -;; rx_float_compare_mode = false; -;; return "tst\t%Q0"; -;; } -;; [(set_attr "cc" "set_zs") -;; (set_attr "timings" "11,11,33") -;; (set_attr "length" "3,7,6")] -;; ) +(define_insn_and_split "*cbranchsf4_" + [(set (pc) + (if_then_else (most_cond:SF (match_operand:SF 0 "register_operand" "r") + (match_operand:SF 1 "rx_source_operand" "rFiQ")) + (label_ref (match_operand 2 "" "")) + (pc))) + ] + "ALLOW_RX_FPU_INSNS" + "#" + "&& reload_completed" + [(const_int 0)] + " + /* We contstruct the split by hand as otherwise the JUMP_LABEL + attribute is not set correctly on the jump insn. */ + emit_insn (gen_cmpsf (operands[0], operands[1])); + + emit_jump_insn (gen_conditional_branch (operands[2], + gen_rtx_fmt_ee (, CCmode, + gen_rtx_REG (CCmode, CC_REG), const0_rtx))); + " +) + +(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")) + (const_int 0)))] + "" + { + rx_float_compare_mode = false; + return "tst\t%Q1, %0"; + } + [(set_attr "timings" "11,11,33") + (set_attr "length" "3,7,6")] +) (define_insn "cmpsi" - [(set (cc0) (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")))] + [(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")))] "" { rx_float_compare_mode = false; + if (rx_compare_redundant (insn)) + return "; Compare Eliminated: cmp %Q1, %0"; return "cmp\t%Q1, %0"; } - [(set_attr "cc" "set_zsoc") - (set_attr "timings" "11,11,11,11,11,11,33") + [(set_attr "timings" "11,11,11,11,11,11,33") (set_attr "length" "2,2,3,4,5,6,5")] ) -;; This pattern is disabled if the function can throw non-call exceptions, -;; because it could generate a floating point exception, which would -;; introduce an edge into the flow graph between this insn and the -;; conditional branch insn to follow, thus breaking the cc0 relationship. -;; Run the g++ test g++.dg/eh/080514-1.C to see this happen. +;; ??? g++.dg/eh/080514-1.C to see this happen. (define_insn "cmpsf" - [(set (cc0) - (compare:CC (match_operand:SF 0 "register_operand" "r,r,r") - (match_operand:SF 1 "rx_source_operand" "r,i,Q")))] - "ALLOW_RX_FPU_INSNS && (cfun == NULL || !cfun->can_throw_non_call_exceptions)" + [(set (reg:CC_ZSO CC_REG) + (compare:CC_ZSO (match_operand:SF 0 "register_operand" "r,r,r") + (match_operand:SF 1 "rx_source_operand" "r,iF,Q")))] + "ALLOW_RX_FPU_INSNS" { rx_float_compare_mode = true; return "fcmp\t%1, %0"; } - [(set_attr "cc" "set_zso") - (set_attr "timings" "11,11,33") + [(set_attr "timings" "11,11,33") (set_attr "length" "3,7,5")] ) @@ -234,17 +270,17 @@ (define_expand "b" [(set (pc) - (if_then_else (most_cond (cc0) (const_int 0)) + (if_then_else (most_cond (reg:CC CC_REG) (const_int 0)) (label_ref (match_operand 0)) (pc)))] "" "" ) -(define_insn "*conditional_branch" +(define_insn "conditional_branch" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) + [(reg:CC CC_REG) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "" @@ -253,14 +289,13 @@ } [(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 "cc" "clobber")] ;; FIXME: This clobber is wrong. + (set_attr "timings" "33")] ;; The timing assumes that the branch is taken. ) (define_insn "*reveresed_conditional_branch" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) + [(reg:CC CC_REG) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] "" @@ -269,38 +304,37 @@ } [(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 "cc" "clobber")] ;; FIXME: This clobber is wrong. + (set_attr "timings" "33")] ;; The timing assumes that the branch is taken. ) (define_insn "jump" - [(set (pc) (label_ref (match_operand 0 "" "")))] + [(set (pc) + (label_ref (match_operand 0 "" "")))] "" "bra\t%0" [(set_attr "length" "4") - (set_attr "timings" "33") - (set_attr "cc" "clobber")] ;; FIXME: This clobber is wrong. + (set_attr "timings" "33")] ) (define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "r"))] + [(set (pc) + (match_operand:SI 0 "register_operand" "r"))] "" "jmp\t%0" [(set_attr "length" "2") - (set_attr "timings" "33") - (set_attr "cc" "clobber")] ;; FIXME: This clobber is wrong. + (set_attr "timings" "33")] ) (define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "register_operand" "r")) + [(set (pc) + (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" { return flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0" : "\n1:\tbra\t%0") : "jmp\t%0"; } - [(set_attr "cc" "clobber") ;; FIXME: This clobber is wrong. - (set_attr "timings" "33") + [(set_attr "timings" "33") (set_attr "length" "2")] ) @@ -324,11 +358,10 @@ ) (define_insn "pop_and_return" - [(match_parallel 1 "rx_rtsd_vector" + [(match_parallel 1 "rx_rtsd_vector" [(set:SI (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI - 0 "const_int_operand" "n")))])] + (match_operand:SI 0 "const_int_operand" "n")))])] "reload_completed" { rx_emit_stack_popm (operands, false); @@ -385,13 +418,13 @@ (define_insn "call_internal" [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol")) - (match_operand:SI 1 "general_operand" "g,g"))] + (match_operand:SI 1 "general_operand" "g,g")) + (clobber (reg:CC CC_REG))] "" "@ jsr\t%0 bsr\t%A0" [(set_attr "length" "2,4") - (set_attr "cc" "clobber") (set_attr "timings" "33")] ) @@ -413,13 +446,13 @@ (define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=r,r") (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol")) - (match_operand:SI 2 "general_operand" "g,g")))] + (match_operand:SI 2 "general_operand" "g,g"))) + (clobber (reg:CC CC_REG))] "" "@ jsr\t%1 bsr\t%A1" [(set_attr "length" "2,4") - (set_attr "cc" "clobber") (set_attr "timings" "33")] ) @@ -564,11 +597,10 @@ ) (define_insn "stack_pushm" - [(match_parallel 1 "rx_store_multiple_vector" + [(match_parallel 1 "rx_store_multiple_vector" [(set:SI (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) - (match_operand:SI - 0 "const_int_operand" "n")))])] + (match_operand:SI 0 "const_int_operand" "n")))])] "reload_completed" { rx_emit_stack_pushm (operands); @@ -591,11 +623,10 @@ ) (define_insn "stack_popm" - [(match_parallel 1 "rx_load_multiple_vector" + [(match_parallel 1 "rx_load_multiple_vector" [(set:SI (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI - 0 "const_int_operand" "n")))])] + (match_operand:SI 0 "const_int_operand" "n")))])] "reload_completed" { rx_emit_stack_popm (operands, true); @@ -605,29 +636,29 @@ (set_attr "timings" "45")] ;; The timing is a guesstimate average timing. ) +;; FIXME: Add memory destination options ? (define_insn "cstoresi4" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r") - (match_operator:SI - 1 "comparison_operator" - [(match_operand:SI - 2 "register_operand" "r,r,r,r,r,r,r") - (match_operand:SI - 3 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")]))] + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SI 2 "register_operand" "r,r,r,r,r,r,r") + (match_operand:SI 3 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")])) + (clobber (reg:CC CC_REG))] ;; Because the cc flags are set based on comparing ops 2 & 3 not the value in op 0. "" { rx_float_compare_mode = false; return "cmp\t%Q3, %Q2\n\tsc%B1.L\t%0"; } - [(set_attr "cc" "clobber") ;; Because cc0 is set based on comparing ops 2 & 3 not the value in op 0. - (set_attr "timings" "22,22,22,22,22,22,44") + [(set_attr "timings" "22,22,22,22,22,22,44") (set_attr "length" "5,5,6,7,8,9,8")] ) (define_expand "movsicc" - [(set (match_operand:SI 0 "register_operand") - (if_then_else:SI (match_operand:SI 1 "comparison_operator") - (match_operand:SI 2 "nonmemory_operand") - (match_operand:SI 3 "immediate_operand")))] + [(parallel + [(set (match_operand:SI 0 "register_operand") + (if_then_else:SI (match_operand:SI 1 "comparison_operator") + (match_operand:SI 2 "nonmemory_operand") + (match_operand:SI 3 "immediate_operand"))) + (clobber (reg:CC CC_REG))])] ;; See cstoresi4 "" { if (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE) @@ -638,22 +669,18 @@ ) (define_insn "*movsieq" - [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (if_then_else:SI (eq (match_operand:SI - 3 "register_operand" "r,r,r") - (match_operand:SI - 4 "rx_source_operand" "riQ,riQ,riQ")) - (match_operand:SI - 1 "nonmemory_operand" "0,i,r") - (match_operand:SI - 2 "immediate_operand" "i,i,i")))] + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (if_then_else:SI (eq (match_operand:SI 3 "register_operand" "r,r,r") + (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")) + (match_operand:SI 1 "nonmemory_operand" "0,i,r") + (match_operand:SI 2 "immediate_operand" "i,i,i"))) + (clobber (reg:CC CC_REG))] ;; See cstoresi4 "" "@ cmp\t%Q4, %Q3\n\tstnz\t%2, %0 cmp\t%Q4, %Q3\n\tmov.l\t%2, %0\n\tstz\t%1, %0 cmp\t%Q4, %Q3\n\tmov.l\t%1, %0\n\tstnz\t%2, %0" - [(set_attr "cc" "clobber") ;; See cstoresi4 - (set_attr "length" "13,19,15") + [(set_attr "length" "13,19,15") (set_attr "timings" "22,33,33")] ) @@ -662,14 +689,14 @@ (if_then_else:SI (ne (match_operand:SI 3 "register_operand" "r,r,r") (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")) (match_operand:SI 1 "nonmemory_operand" "0,i,r") - (match_operand:SI 2 "immediate_operand" "i,i,i")))] + (match_operand:SI 2 "immediate_operand" "i,i,i"))) + (clobber (reg:CC CC_REG))] ;; See cstoresi4 "" "@ cmp\t%Q4, %Q3\n\tstz\t%2, %0 cmp\t%Q4, %Q3\n\tmov.l\t%2, %0\n\tstnz\t%1, %0 cmp\t%Q4, %Q3\n\tmov.l\t%1, %0\n\tstz\t%2, %0" - [(set_attr "cc" "clobber") ;; See cstoresi4 - (set_attr "length" "13,19,15") + [(set_attr "length" "13,19,15") (set_attr "timings" "22,33,33")] ) @@ -677,24 +704,24 @@ (define_insn "abssi2" [(set (match_operand:SI 0 "register_operand" "=r,r") - (abs:SI (match_operand:SI 1 "register_operand" "0,r")))] + (abs:SI (match_operand:SI 1 "register_operand" "0,r"))) + (set (reg:CC_ZSO CC_REG) + (compare:CC_ZSO (abs:SI (match_dup 1)) + (const_int 0)))] "" "@ abs\t%0 abs\t%1, %0" - [(set_attr "cc" "set_zso") - (set_attr "length" "2,3")] + [(set_attr "length" "2,3")] ) (define_insn "addsi3" - [(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,0") - (match_operand:SI - 2 "rx_source_operand" - "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,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,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 (reg:CC_ZSC CC_REG) ;; See subsi3 + (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "@ add\t%2, %0 @@ -704,35 +731,38 @@ add\t%2, %0 add\t%2, %0 add\t%2, %0 + add\t%1, %0 add\t%2, %1, %0 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 "cc" "set_zsc") ;; See subsi3 - (set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,33") - (set_attr "length" "2,2,2,3,4,5,6,3,3,4,5,6,5")] + [(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")] ) (define_insn "adddi3" [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r") (plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0,0") (match_operand:DI 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q")))] + "r,Sint08,Sint16,Sint24,i,Q"))) + (set (reg:CC_ZSC CC_REG) ;; See subsi3 + (compare:CC_ZSC (plus:DI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "add\t%L2, %L0\n\tadc\t%H2, %H0" - [(set_attr "cc" "set_zsc") ;; See subsi3 - (set_attr "timings" "22,22,22,22,22,44") + [(set_attr "timings" "22,22,22,22,22,44") (set_attr "length" "5,7,9,11,13,11")] ) (define_insn "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")))] + (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (and:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "@ and\t%2, %0 @@ -744,8 +774,7 @@ and\t%1, %0 and\t%2, %1, %0 and\t%Q2, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "11,11,11,11,11,11,11,33,33") + [(set_attr "timings" "11,11,11,11,11,11,11,33,33") (set_attr "length" "2,2,3,4,5,6,2,5,5")] ) @@ -770,12 +799,11 @@ (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")))] + (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + (clobber (reg:CC CC_REG))] "" "div\t%Q2, %0" - [(set_attr "cc" "clobber") - (set_attr "timings" "1111") ;; Strictly speaking the timing should be + [(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")] ) @@ -783,12 +811,11 @@ (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")))] + (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))) + (clobber (reg:CC CC_REG))] "" "divu\t%Q2, %0" - [(set_attr "cc" "clobber") - (set_attr "timings" "1010") ;; Strictly speaking the timing should be + [(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")] ) @@ -816,12 +843,9 @@ ;; mulsidi3 pattern. Immediate mode addressing is not supported ;; because gcc cannot handle the expression: (zero_extend (const_int)). (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,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"))))] "! TARGET_BIG_ENDIAN_DATA" "emulu\t%Q2, %0" [(set_attr "length" "3,6") @@ -872,33 +896,39 @@ (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") - (neg:SI (match_operand:SI 1 "register_operand" "0,r")))] + (neg:SI (match_operand:SI 1 "register_operand" "0,r"))) + (set (reg:CC CC_REG) + (compare:CC (neg:SI (match_dup 1)) + (const_int 0)))] ;; The NEG instruction does not comply with -fwrapv semantics. ;; See gcc.c-torture/execute/pr22493-1.c for an example of this. "! flag_wrapv" "@ neg\t%0 neg\t%1, %0" - [(set_attr "length" "2,3") - (set_attr "cc" "set_zsoc")] + [(set_attr "length" "2,3")] ) (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") - (not:SI (match_operand:SI 1 "register_operand" "0,r")))] + (not:SI (match_operand:SI 1 "register_operand" "0,r"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (not:SI (match_dup 1)) + (const_int 0)))] "" "@ not\t%0 not\t%1, %0" - [(set_attr "cc" "set_zs") - (set_attr "length" "2,3")] + [(set_attr "length" "2,3")] ) (define_insn "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")))] + (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (ior:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "@ or\t%2, %0 @@ -910,74 +940,89 @@ or\t%1, %0 or\t%2, %1, %0 or\t%Q2, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "11,11,11,11,11,11,11,11,33") + [(set_attr "timings" "11,11,11,11,11,11,11,11,33") (set_attr "length" "2,2,3,4,5,6,2,3,5")] ) (define_insn "rotlsi3" [(set (match_operand:SI 0 "register_operand" "=r") (rotate:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "rx_shift_operand" "rn")))] + (match_operand:SI 2 "rx_shift_operand" "rn"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (rotate:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "rotl\t%2, %0" - [(set_attr "cc" "set_zs") - (set_attr "length" "3")] + [(set_attr "length" "3")] ) (define_insn "rotrsi3" [(set (match_operand:SI 0 "register_operand" "=r") (rotatert:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "rx_shift_operand" "rn")))] + (match_operand:SI 2 "rx_shift_operand" "rn"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (rotatert:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "rotr\t%2, %0" - [(set_attr "cc" "set_zs") - (set_attr "length" "3")] + [(set_attr "length" "3")] ) (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") - (match_operand:SI 2 "rx_shift_operand" "r,n,n")))] + (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (ashiftrt:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "@ shar\t%2, %0 shar\t%2, %0 shar\t%2, %1, %0" - [(set_attr "cc" "set_zs") - (set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3")] ) (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") - (match_operand:SI 2 "rx_shift_operand" "r,n,n")))] + (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (lshiftrt:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "@ shlr\t%2, %0 shlr\t%2, %0 shlr\t%2, %1, %0" - [(set_attr "cc" "set_zs") - (set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3")] ) (define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r") - (match_operand:SI 2 "rx_shift_operand" "r,n,n")))] + (match_operand:SI 2 "rx_shift_operand" "r,n,n"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (ashift:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "@ shll\t%2, %0 shll\t%2, %0 shll\t%2, %1, %0" - [(set_attr "cc" "set_zs") - (set_attr "length" "3,2,3")] + [(set_attr "length" "3,2,3")] ) (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")))] + (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q"))) + (set (reg:CC_ZSC CC_REG) + ;; Note - we do not acknowledge that the SUB instruction sets the Overflow + ;; flag because its interpretation is different from comparing the result + ;; against zero. Compile and run gcc.c-torture/execute/cmpsi-1.c to see this. + (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "@ sub\t%2, %0 @@ -985,22 +1030,20 @@ add\t%N2, %0 sub\t%2, %1, %0 sub\t%Q2, %0" - [(set_attr "cc" "set_zsc") ;; Note - we do not acknowledge that the SUB - ;; instruction sets the Overflow flag because its interpretation is - ;; different from comparing the result against zero. Compile and run - ;; gcc.c-torture/execute/cmpsi-1.c to see this. - (set_attr "timings" "11,11,11,11,33") + [(set_attr "timings" "11,11,11,11,33") (set_attr "length" "2,2,6,3,5")] ) (define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=r,r") (minus:DI (match_operand:DI 1 "register_operand" "0,0") - (match_operand:DI 2 "rx_source_operand" "r,Q")))] + (match_operand:DI 2 "rx_source_operand" "r,Q"))) + (set (reg:CC_ZSC CC_REG) ;; See subsi3 + (compare:CC_ZSC (minus:DI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "sub\t%L2, %L0\n\tsbb\t%H2, %H0" - [(set_attr "cc" "set_zsc") ;; See subsi3 - (set_attr "timings" "22,44") + [(set_attr "timings" "22,44") (set_attr "length" "5,11")] ) @@ -1008,11 +1051,13 @@ [(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") (match_operand:SI 2 "rx_source_operand" - "r,Sint08,Sint16,Sint24,i,Q")))] + "r,Sint08,Sint16,Sint24,i,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (xor:SI (match_dup 1) (match_dup 2)) + (const_int 0)))] "" "xor\t%Q2, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "11,11,11,11,11,33") + [(set_attr "timings" "11,11,11,11,11,33") (set_attr "length" "3,4,5,6,7,6")] ) @@ -1021,64 +1066,76 @@ (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")))] + (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (plus:SF (match_dup 1) (match_dup 2)) + (const_int 0)))] "ALLOW_RX_FPU_INSNS" "fadd\t%2, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "44,44,66") + [(set_attr "timings" "44,44,66") (set_attr "length" "3,7,5")] ) (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")))] + (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (div:SF (match_dup 1) (match_dup 2)) + (const_int 0)))] "ALLOW_RX_FPU_INSNS" "fdiv\t%2, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "1616,1616,1818") + [(set_attr "timings" "1616,1616,1818") (set_attr "length" "3,7,5")] ) (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")))] + (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (mult:SF (match_dup 1) (match_dup 2)) + (const_int 0)))] "ALLOW_RX_FPU_INSNS" "fmul\t%2, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "33,33,55") + [(set_attr "timings" "33,33,55") (set_attr "length" "3,7,5")] ) (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")))] + (match_operand:SF 2 "rx_source_operand" "r,F,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (minus:SF (match_dup 1) (match_dup 2)) + (const_int 0)))] "ALLOW_RX_FPU_INSNS" "fsub\t%Q2, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "44,44,66") + [(set_attr "timings" "44,44,66") (set_attr "length" "3,7,5")] ) (define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "=r,r") - (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))] + (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (fix:SI (match_dup 1)) + (const_int 0)))] "ALLOW_RX_FPU_INSNS" "ftoi\t%Q1, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "22,44") + [(set_attr "timings" "22,44") (set_attr "length" "3,5")] ) (define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=r,r") - (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))] + (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q"))) + (set (reg:CC_ZS CC_REG) + (compare:CC_ZS (float:SF (match_dup 1)) + (const_int 0)))] "ALLOW_RX_FPU_INSNS" "itof\t%Q1, %0" - [(set_attr "cc" "set_zs") - (set_attr "timings" "22,44") + [(set_attr "timings" "22,44") (set_attr "length" "3,6")] ) @@ -1090,8 +1147,8 @@ ;; of three instructions at a time. (define_insn "bitset" - [(set:SI (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "0") + [(set:SI (match_operand:SI 0 "register_operand" "=r") + (ior:SI (match_operand:SI 1 "register_operand" "0") (ashift:SI (const_int 1) (match_operand:SI 2 "nonmemory_operand" "ri"))))] "" @@ -1100,8 +1157,8 @@ ) (define_insn "bitset_in_memory" - [(set:QI (match_operand:QI 0 "memory_operand" "=m") - (ior:QI (match_operand:QI 1 "memory_operand" "0") + [(set:QI (match_operand:QI 0 "memory_operand" "=m") + (ior:QI (match_operand:QI 1 "memory_operand" "0") (ashift:QI (const_int 1) (match_operand:QI 2 "nonmemory_operand" "ri"))))] "" @@ -1275,14 +1332,10 @@ ) (define_expand "insv" - [(set:SI (zero_extract:SI (match_operand:SI - 0 "nonimmediate_operand") ;; Destination - (match_operand - 1 "immediate_operand") ;; # of bits to set - (match_operand - 2 "immediate_operand")) ;; Starting bit - (match_operand - 3 "immediate_operand"))] ;; Bits to insert + [(set:SI (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand") ;; Destination + (match_operand 1 "immediate_operand") ;; # of bits to set + (match_operand 2 "immediate_operand")) ;; Starting bit + (match_operand 3 "immediate_operand"))] ;; Bits to insert "" { if (rx_expand_insv (operands)) @@ -1337,8 +1390,7 @@ (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR) (clobber (reg:SI 1)) (clobber (reg:SI 2)) - (clobber (reg:SI 3)) - ] + (clobber (reg:SI 3))] "" "smovu" [(set_attr "length" "2") @@ -1352,11 +1404,11 @@ (clobber (reg:SI 1)) (clobber (reg:SI 2)) (clobber (reg:SI 3)) - ] + (clobber (reg:CC CC_REG)) + ] "" "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 "cc" "clobber") (set_attr "timings" "1111")] ;; The timing is a guesstimate. ) @@ -1439,17 +1491,12 @@ ) (define_expand "cmpstrnsi" - [(set (match_operand:SI - 0 "register_operand") ;; Result - (unspec_volatile:SI [(match_operand:BLK - 1 "memory_operand") ;; String1 - (match_operand:BLK - 2 "memory_operand")] ;; String2 + [(set (match_operand:SI 0 "register_operand") ;; Result + (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1 + (match_operand:BLK 2 "memory_operand")] ;; String2 UNSPEC_CMPSTRN)) - (use (match_operand:SI - 3 "register_operand")) ;; Max Length - (match_operand:SI - 4 "immediate_operand")] ;; Known Align + (use (match_operand:SI 3 "register_operand")) ;; Max Length + (match_operand:SI 4 "immediate_operand")] ;; Known Align "" { rtx str1 = gen_rtx_REG (SImode, 1); @@ -1466,15 +1513,11 @@ ) (define_expand "cmpstrsi" - [(set (match_operand:SI - 0 "register_operand") ;; Result - (unspec_volatile:SI [(match_operand:BLK - 1 "memory_operand") ;; String1 - (match_operand:BLK - 2 "memory_operand")] ;; String2 + [(set (match_operand:SI 0 "register_operand") ;; Result + (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1 + (match_operand:BLK 2 "memory_operand")] ;; String2 UNSPEC_CMPSTRN)) - (match_operand:SI - 3 "immediate_operand")] ;; Known Align + (match_operand:SI 3 "immediate_operand")] ;; Known Align "" { rtx str1 = gen_rtx_REG (SImode, 1); @@ -1498,7 +1541,8 @@ (use (match_operand:BLK 2 "memory_operand" "m")) (clobber (reg:SI 1)) (clobber (reg:SI 2)) - (clobber (reg:SI 3))] + (clobber (reg:SI 3)) + (clobber (reg:CC CC_REG))] "" "scmpu ; Perform the string comparison mov #-1, %0 ; Set up -1 result (which cannot be created @@ -1639,11 +1683,11 @@ (define_insn "lrintsf2" [(set (match_operand:SI 0 "register_operand" "=r,r") (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")] - UNSPEC_BUILTIN_ROUND))] + UNSPEC_BUILTIN_ROUND)) + (clobber (reg:CC CC_REG))] "" "round\t%1, %0" - [(set_attr "cc" "clobber") - (set_attr "timings" "22,44") + [(set_attr "timings" "22,44") (set_attr "length" "3,5")] ) @@ -1663,22 +1707,20 @@ (define_insn "clrpsw" [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_BUILTIN_CLRPSW) - (clobber (cc0))] + (clobber (reg:CC CC_REG))] "" "clrpsw\t%F0" - [(set_attr "length" "2") - (set_attr "cc" "clobber")] + [(set_attr "length" "2")] ) ;; Set Processor Status Word (define_insn "setpsw" [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_BUILTIN_SETPSW) - (clobber (cc0))] + (clobber (reg:CC CC_REG))] "" "setpsw\t%F0" - [(set_attr "length" "2") - (set_attr "cc" "clobber")] + [(set_attr "length" "2")] ) ;; Move from control register