rx-modes.def: New file.
authorNick Clifton <nickc@redhat.com>
Wed, 30 Jun 2010 08:50:14 +0000 (08:50 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Wed, 30 Jun 2010 08:50:14 +0000 (08:50 +0000)
        * 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_<code>): ... 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

gcc/ChangeLog
gcc/config/rx/predicates.md
gcc/config/rx/rx-modes.def [new file with mode: 0644]
gcc/config/rx/rx-protos.h
gcc/config/rx/rx.c
gcc/config/rx/rx.h
gcc/config/rx/rx.md

index bb8f81e52238777d525341a8523489f2f527dfe8..bd7f730d6c2eb880e18fb8e8abdf4f520ddab031 100644 (file)
@@ -1,3 +1,44 @@
+2010-06-30  Nick Clifton  <nickc@redhat.com>
+
+       * 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_<code>): ... 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  <manu@gcc.gnu.org>
 
        * tree.h (block_may_fallthru): Declare here.
index d7a363ebb88d10123ee2c70894f188027fbaa006..94e5f5630c231f3c02a7ebe98b9dac913d888169 100644 (file)
@@ -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 (file)
index 0000000..5936b67
--- /dev/null
@@ -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
+   <http://www.gnu.org/licenses/>.  */
+
+CC_MODE (CC_ZS);
+CC_MODE (CC_ZSO);
+CC_MODE (CC_ZSC);
index a2a28c125799aa2ac0a6d736faf5d648ace4ba1e..166290de5e72d7b95264e5bf70f286a05df5a3c6 100644 (file)
@@ -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);
index 8d9e462dd5c52fbf3f7793d5f2b4eba601cfec94..2219efe8559de8af6a15c8ffd9aa090d9176a48e 100644 (file)
@@ -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)
     }
 }
 \f
+
+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);
+}
+\f
 #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" */
index afaa07b0bc5bc92275a14a2ed67dd600d1b3beb2..b3a12690b08a52c7dc350c0519235dce8fbcfbe8 100644 (file)
@@ -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)
 \f
-#define CC_NO_CARRY                    0400
-#define NOTICE_UPDATE_CC(EXP, INSN)    rx_notice_update_cc (EXP, INSN)
-
 extern int rx_float_compare_mode;
 \f
 /* 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))))
index 6fe2525947260bc87dc71b6171414d2991603869..aeba85ffe391ed919d4f2d2df00a8f6874bd0b07 100644 (file)
@@ -47,6 +47,7 @@
 (define_constants
   [
    (SP_REG 0)
+   (CC_REG                16)
 
    (UNSPEC_LOW_REG         0)
    (UNSPEC_HIGH_REG        1)
   ]
 )
 
-;; 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")
 
 ;; 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_<code>"
+  [(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 (<most_cond:CODE>, 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_<code>"
+  [(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 (<most_cond:CODE>, 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")]
 )
 
 
 (define_expand "b<code>"
   [(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)))]
   ""
   }
   [(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 "" ""))))]
   ""
   }
   [(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")]
 )
 
 )
 
 (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);
 
 (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")]
 )
 
 (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")]
 )
 
 )
 
 (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);
 )
 
 (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);
    (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)
 )
 
 (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")]
 )
 
        (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")]
 )
 
 
 (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
   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
   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")]
 )
 
 (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")]
 )
 (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")]
 )
 ;; 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")
 
 (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
   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
   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")]
 )
 
   [(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")]
 )
 \f
 (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")]
 )
 \f
 ;; 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"))))]
   ""
 )
 
 (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"))))]
   ""
 )
 
 (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))
    (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")
    (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.
 )
 
 )
 
 (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);
 )
 
 (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);
    (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
 (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")]
 )
 
 (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