The CB<cond> family of instructions does not support using the CS or CC
condition codes; instead the synonyms HS and LO must be used. GCC has
traditionally used the CS and CC names. To work around this while
avoiding test churn, add new `j` and `J` format specifiers; they will be
used in the next commit when generating CB<cond> instructions.

Also reformat the definition of the `aarch64_cond_code` enum while we're
in the same neighbourhood, to make the relationship between each code
and its inverse more obvious.

gcc/ChangeLog:

        * config/aarch64/aarch64.cc (aarch64_cond_code): Reformat.
        (aarch64_print_operand): Add new 'j' and 'J' format specifiers.
---
 gcc/config/aarch64/aarch64.cc | 36 +++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 74c4b155b92..9e45a31f159 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -918,11 +918,18 @@ static const scoped_attribute_specs *const 
aarch64_attribute_table[] =
   &aarch64_arm_attribute_table
 };
 
-typedef enum aarch64_cond_code
-{
-  AARCH64_EQ = 0, AARCH64_NE, AARCH64_CS, AARCH64_CC, AARCH64_MI, AARCH64_PL,
-  AARCH64_VS, AARCH64_VC, AARCH64_HI, AARCH64_LS, AARCH64_GE, AARCH64_LT,
-  AARCH64_GT, AARCH64_LE, AARCH64_AL, AARCH64_NV
+/* The condition codes come in opposing pairs.  To get the inverse of a given
+   condition, simply flip the LSB.  */
+typedef enum aarch64_cond_code {
+  AARCH64_EQ = 0x00,       AARCH64_NE = 0x01,
+  AARCH64_CS = 0x02,       AARCH64_CC = 0x03,
+  AARCH64_HS = AARCH64_CS, AARCH64_LO = AARCH64_CC,
+  AARCH64_MI = 0x04,       AARCH64_PL = 0x05,
+  AARCH64_VS = 0x06,       AARCH64_VC = 0x07,
+  AARCH64_HI = 0x08,       AARCH64_LS = 0x09,
+  AARCH64_GE = 0x0A,       AARCH64_LT = 0x0B,
+  AARCH64_GT = 0x0C,       AARCH64_LE = 0x0D,
+  AARCH64_AL = 0x0E,       AARCH64_NV = 0x0F,
 }
 aarch64_cc;
 
@@ -12370,6 +12377,9 @@ sizetochar (int size)
                        of regs.
      'm':              Print a condition (eq, ne, etc).
      'M':              Same as 'm', but invert condition.
+     'j':              Same as 'm', but use use `hs` and `lo`
+                       instead of `cs` and `cc`.
+     'J':              Same as 'j', but invert condition.
      'N':              Take the duplicated element in a vector constant
                        and print the negative of it in decimal.
      'b/h/s/d/q':      Print a scalar FP/SIMD register name.
@@ -12499,12 +12509,14 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 
     case 'M':
     case 'm':
+    case 'j':
+    case 'J':
       {
         int cond_code;
        /* CONST_TRUE_RTX means al/nv (al is the default, don't print it).  */
        if (x == const_true_rtx)
          {
-           if (code == 'M')
+           if (code == 'M' || code == 'J')
              fputs ("nv", f);
            return;
          }
@@ -12517,12 +12529,20 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 
         cond_code = aarch64_get_condition_code (x);
         gcc_assert (cond_code >= 0);
-       if (code == 'M')
+       if (code == 'M' || code == 'J')
          cond_code = AARCH64_INVERSE_CONDITION_CODE (cond_code);
        if (GET_MODE (XEXP (x, 0)) == CC_NZCmode)
          fputs (aarch64_sve_condition_codes[cond_code], f);
        else
-         fputs (aarch64_condition_codes[cond_code], f);
+         {
+           auto name = aarch64_condition_codes[cond_code];
+           if (code == 'j' || code == 'J')
+             {
+               if (cond_code == AARCH64_CS) name = "hs";
+               if (cond_code == AARCH64_CC) name = "lo";
+             }
+           fputs (name, f);
+         }
       }
       break;
 
-- 
2.45.2

Reply via email to