Hi, The patch adds three help functions to output ccmp instructions.
OK for trunk? Thanks! -Zhenqiang ChangeLog: 2014-06-23 Zhenqiang Chen <zhenqiang.c...@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 --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