diff mbox

[7/10] aarch64: add function to output ccmp insn

Message ID CACgzC7CyRH51+A74+7y8V177EbLqmb3aauMyEunakn+SJig+BQ@mail.gmail.com
State New
Headers show

Commit Message

Zhenqiang Chen June 23, 2014, 7 a.m. UTC
Hi,

The patch adds three help functions to output ccmp instructions.

OK for trunk?

Thanks!
-Zhenqiang

ChangeLog:
2014-06-23  Zhenqiang Chen  <zhenqiang.chen@linaro.org>

        * config/aarch64/aarch64-protos.h (aarch64_output_ccmp): New prototype.
        * config/aarch64/aarch64.c (aarch64_code_to_nzcv): New function.
        (aarch64_mode_to_condition_code): New function.
        (aarch64_output_ccmp): New function.
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64-protos.h
b/gcc/config/aarch64/aarch64-protos.h
index 997ff50..ff1a0f4 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -247,6 +247,7 @@  void aarch64_print_operand (FILE *, rtx, char);
 void aarch64_print_operand_address (FILE *, rtx);

 bool aarch64_uimm5 (HOST_WIDE_INT);
+const char* aarch64_output_ccmp (rtx *, bool, int);

 /* Initialize builtins for SIMD intrinsics.  */
 void init_aarch64_simd_builtins (void);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index e5ede6e..5fe4826 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -9602,6 +9602,137 @@  aarch64_uimm5 (HOST_WIDE_INT val)
   return (val & (HOST_WIDE_INT) 0x1f) == val;
 }

+/* N Z C V.  */
+#define AARCH64_CC_V 1
+#define AARCH64_CC_C (1 << 1)
+#define AARCH64_CC_Z (1 << 2)
+#define AARCH64_CC_N (1 << 3)
+
+static unsigned int
+aarch64_code_to_nzcv (enum rtx_code code, bool inverse)
+{
+  switch (code)
+    {
+    case NE: /* NE, Z == 0.  */
+      return inverse ? AARCH64_CC_Z : 0;
+    case EQ: /* EQ, Z == 1.  */
+      return inverse ? 0 : AARCH64_CC_Z;
+    case LE: /* LE, !(Z == 0 && N == V).  */
+      return inverse ? AARCH64_CC_N | AARCH64_CC_V : AARCH64_CC_Z;
+    case GT: /* GT, Z == 0 && N == V.  */
+      return inverse ? AARCH64_CC_Z : AARCH64_CC_N | AARCH64_CC_V;
+    case LT: /* LT, N != V.  */
+      return inverse ? AARCH64_CC_N | AARCH64_CC_V : AARCH64_CC_N;
+    case GE: /* GE, N == V.  */
+      return inverse ? AARCH64_CC_N : AARCH64_CC_N | AARCH64_CC_V;
+    case LEU: /* LS, !(C == 1 && Z == 0).  */
+      return inverse ? AARCH64_CC_C: AARCH64_CC_Z;
+    case GTU: /* HI, C ==1 && Z == 0.  */
+      return inverse ? AARCH64_CC_Z : AARCH64_CC_C;
+    case LTU: /* CC, C == 0.  */
+      return inverse ? AARCH64_CC_C : 0;
+    case GEU: /* CS, C == 1.  */
+      return inverse ? 0 : AARCH64_CC_C;
+    default:
+      gcc_unreachable ();
+      return 0;
+    }
+}
+
+static unsigned
+aarch64_mode_to_condition_code (enum machine_mode mode, bool inverse)
+{
+  switch (mode)
+    {
+    case CC_DNEmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, EQ)
+                      : aarch64_get_condition_code_1 (CCmode, NE);
+    case CC_DEQmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, NE)
+                      : aarch64_get_condition_code_1 (CCmode, EQ);
+    case CC_DLEmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, GT)
+                      : aarch64_get_condition_code_1 (CCmode, LE);
+    case CC_DGTmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, LE)
+                      : aarch64_get_condition_code_1 (CCmode, GT);
+    case CC_DLTmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, GE)
+                      : aarch64_get_condition_code_1 (CCmode, LT);
+    case CC_DGEmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, LT)
+                      : aarch64_get_condition_code_1 (CCmode, GE);
+    case CC_DLEUmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, GTU)
+                      : aarch64_get_condition_code_1 (CCmode, LEU);
+    case CC_DGTUmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, LEU)
+                      : aarch64_get_condition_code_1 (CCmode, GTU);
+    case CC_DLTUmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, GEU)
+                      : aarch64_get_condition_code_1 (CCmode, LTU);
+    case CC_DGEUmode:
+      return inverse ? aarch64_get_condition_code_1 (CCmode, LTU)
+                      : aarch64_get_condition_code_1 (CCmode, GEU);
+    default:
+      gcc_unreachable ();
+    }
+}
+
+const char *
+aarch64_output_ccmp (rtx *operands, bool is_and, int which_alternative)
+{
+  char buf[32];
+  rtx cc = operands[0];
+  enum rtx_code code = GET_CODE (operands[5]);
+  unsigned char nzcv = aarch64_code_to_nzcv (code, is_and);
+  enum machine_mode mode = GET_MODE (cc);
+  unsigned int cond_code = aarch64_mode_to_condition_code (mode, !is_and);
+
+  gcc_assert (GET_MODE (operands[2]) == SImode
+             || GET_MODE (operands[2]) == DImode);
+
+  if (GET_MODE (operands[2]) == SImode)
+    switch (which_alternative)
+      {
+      case 0:
+       snprintf (buf, sizeof (buf), "ccmp\t%%w2, %%w3, #%u, %s",
+                 nzcv, aarch64_condition_codes[cond_code]);
+       break;
+      case 1:
+       snprintf (buf, sizeof (buf), "ccmp\t%%w2, #%%3, #%u, %s",
+                 nzcv, aarch64_condition_codes[cond_code]);
+       break;
+      case 2:
+       snprintf (buf, sizeof (buf), "ccmn\t%%w2, #%%n3, #%u, %s",
+                 nzcv, aarch64_condition_codes[cond_code]);
+       break;
+      default:
+       gcc_unreachable ();
+      }
+  else
+    switch (which_alternative)
+      {
+      case 0:
+       snprintf (buf, sizeof (buf), "ccmp\t%%x2, %%x3, #%u, %s",
+                 nzcv, aarch64_condition_codes[cond_code]);
+       break;
+      case 1:
+       snprintf (buf, sizeof (buf), "ccmp\t%%x2, #%%3, #%u, %s",
+                 nzcv, aarch64_condition_codes[cond_code]);
+       break;
+      case 2:
+       snprintf (buf, sizeof (buf), "ccmn\t%%x2, #%%n3, #%u, %s",
+                 nzcv, aarch64_condition_codes[cond_code]);
+       break;
+      default:
+       gcc_unreachable ();
+      }
+
+  output_asm_insn (buf, operands);
+  return "";
+}
+
#undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost