/* This file contains the definitions and documentation for the goal functions
   used in the Superoptimizer.

   Copyright (C) 1992 Free Software Foundation, Inc.

   This program 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 2, or (at your option) any
   later version.

   This program 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 this program; see the file COPYING.  If not, write to the Free
   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* The fields in the cpp macro call "DEF_GOAL()" are:

   1. The internal name of the goal function.

   2. The number of input operands.

   3. The printed name of the instruction.

   4. C code that implements the function.

   */

DEF_GOAL (EQ,             2, "eq",          { r = v0 == v1; })
DEF_GOAL (NE,             2, "ne",          { r = v0 != v1; })
DEF_GOAL (LES,            2, "les",         { r = (signed_word) v0 <= (signed_word) v1; })
DEF_GOAL (GES,            2, "ges",         { r = (signed_word) v0 >= (signed_word) v1; })
DEF_GOAL (LTS,            2, "lts",         { r = (signed_word) v0 < (signed_word) v1; })
DEF_GOAL (GTS,            2, "gts",         { r = (signed_word) v0 > (signed_word) v1; })
DEF_GOAL (LEU,            2, "leu",         { r = (unsigned_word) v0 <= (unsigned_word) v1; })
DEF_GOAL (GEU,            2, "geu",         { r = (unsigned_word) v0 >= (unsigned_word) v1; })
DEF_GOAL (LTU,            2, "ltu",         { r = (unsigned_word) v0 < (unsigned_word) v1; })
DEF_GOAL (GTU,            2, "gtu",         { r = (unsigned_word) v0 > (unsigned_word) v1; })
DEF_GOAL (LESU,           2, "lesu",        { r = (signed_word) v0 < 0 || (unsigned_word) v0 <= (unsigned_word) v1; })
DEF_GOAL (GESU,           2, "gesu",        { r = (signed_word) v0 >= 0 && (unsigned_word) v0 >= (unsigned_word) v1; })
DEF_GOAL (LTSU,           2, "ltsu",        { r = (signed_word) v0 < 0 || (unsigned_word) v0 < (unsigned_word) v1; })
DEF_GOAL (GTSU,           2, "gtsu",        { r = (signed_word) v0 >= 0 && (unsigned_word) v0 > (unsigned_word) v1; })

DEF_GOAL (EQ0,            1, "eq0",         { r = v0 == 0; })
DEF_GOAL (NE0,            1, "ne0",         { r = v0 != 0; })
DEF_GOAL (LES0,           1, "les0",        { r = (signed_word) v0 <= 0; })
DEF_GOAL (GES0,           1, "ges0",        { r = (signed_word) v0 >= 0; })
DEF_GOAL (LTS0,           1, "lts0",        { r = (signed_word) v0 < 0; })
DEF_GOAL (GTS0,           1, "gts0",        { r = (signed_word) v0 > 0; })

DEF_GOAL (NEQ,            2, "neq",         { r = -(v0 == v1); })
DEF_GOAL (NNE,            2, "nne",         { r = -(v0 != v1); })
DEF_GOAL (NLES,           2, "nles",        { r = -((signed_word) v0 <= (signed_word) v1); })
DEF_GOAL (NGES,           2, "nges",        { r = -((signed_word) v0 >= (signed_word) v1); })
DEF_GOAL (NLTS,           2, "nlts",        { r = -((signed_word) v0 < (signed_word) v1); })
DEF_GOAL (NGTS,           2, "ngts",        { r = -((signed_word) v0 > (signed_word) v1); })
DEF_GOAL (NLEU,           2, "nleu",        { r = -((unsigned_word) v0 <= (unsigned_word) v1); })
DEF_GOAL (NGEU,           2, "ngeu",        { r = -((unsigned_word) v0 >= (unsigned_word) v1); })
DEF_GOAL (NLTU,           2, "nltu",        { r = -((unsigned_word) v0 < (unsigned_word) v1); })
DEF_GOAL (NGTU,           2, "ngtu",        { r = -((unsigned_word) v0 > (unsigned_word) v1); })

DEF_GOAL (NEQ0,           1, "neq0",        { r = -(v0 == 0); })
DEF_GOAL (NNE0,           1, "nne0",        { r = -(v0 != 0); })
DEF_GOAL (NLES0,          1, "nles0",       { r = -((signed_word) v0 <= 0); })
DEF_GOAL (NGES0,          1, "nges0",       { r = -((signed_word) v0 >= 0); })
DEF_GOAL (NLTS0,          1, "nlts0",       { r = -((signed_word) v0 < 0); })
DEF_GOAL (NGTS0,          1, "ngts0",       { r = -((signed_word) v0 > 0); })

DEF_GOAL (MAXS,           2, "maxs",        { r = (signed_word) v0 > (signed_word) v1 ? v0 : v1; })
DEF_GOAL (MINS,           2, "mins",        { r = (signed_word) v0 < (signed_word) v1 ? v0 : v1; })
DEF_GOAL (MAXU,           2, "maxu",        { r = (unsigned_word) v0 > (unsigned_word) v1 ? v0 : v1; })
DEF_GOAL (MINU,           2, "minu",        { r = (unsigned_word) v0 < (unsigned_word) v1 ? v0 : v1; })
DEF_GOAL (CMPS,           2, "cmps",        { r = (signed_word) v0 > (signed_word) v1? 1 : ((signed_word) v0 < (signed_word) v1 ? -1 : 0); })
DEF_GOAL (CMPU,           2, "cmpu",        { r = (unsigned_word) v0 > (unsigned_word) v1? 1 : ((unsigned_word) v0 < (unsigned_word) v1 ? -1 : 0); })
DEF_GOAL (SGN,            1, "sgn",         { r = (signed_word) v0 > 0 ? 1 : ((signed_word) v0 < 0 ? -1 : 0); })
DEF_GOAL (ABS,            1, "abs",         { r = (signed_word) v0 < 0 ? -v0 : v0; })
DEF_GOAL (NABS,           1, "nabs",        { r = (signed_word) v0 > 0 ? -v0 : v0; })
DEF_GOAL (GRAY,           1, "gray",        { r = ((~(v0 ^ (v0 << 1)) & (1 << 31)) | ((v0 << 1) & ~(1 << 31)) | (v0 >> 31)); })
DEF_GOAL (GRAY2,          1, "gray2",       { v0 = ((~(v0 ^ (v0 << 1)) & (1 << 31)) | ((v0 << 1) & ~(1 << 31)) | (v0 >> 31)); r = ((~(v0 ^ (v0 << 1)) & (1 << 31)) | ((v0 << 1) & ~(1 << 31)) | (v0 >> 31)); })
DEF_GOAL (DIVIDE_BY_2,    1, "divide_by_2", { r = (signed_word) v0 / 2; })
DEF_GOAL (DIVIDE_BY_4,    1, "divide_by_4", { r = (signed_word) v0 / 4; })
DEF_GOAL (DIVIDE_BY_2e30,    1, "divide_by_2e30", { r = (signed_word) v0 / (1<<30); })
DEF_GOAL (DIVIDE_BY_2e31,    1, "divide_by_2e31", { r = (signed_word) v0 / (1<<31); })

DEF_GOAL (EQ_PLUS,        3, "eq+",         { r = (v0 == v1) + v2; })
DEF_GOAL (NE_PLUS,        3, "ne+",         { r = (v0 != v1) + v2; })
DEF_GOAL (LES_PLUS,       3, "les+",        { r = ((signed_word) v0 <= (signed_word) v1) + v2; })
DEF_GOAL (GES_PLUS,       3, "ges+",        { r = ((signed_word) v0 >= (signed_word) v1) + v2; })
DEF_GOAL (LTS_PLUS,       3, "lts+",        { r = ((signed_word) v0 < (signed_word) v1) + v2; })
DEF_GOAL (GTS_PLUS,       3, "gts+",        { r = ((signed_word) v0 > (signed_word) v1) + v2; })
DEF_GOAL (LEU_PLUS,       3, "leu+",        { r = ((unsigned_word) v0 <= (unsigned_word) v1) + v2; })
DEF_GOAL (GEU_PLUS,       3, "geu+",        { r = ((unsigned_word) v0 >= (unsigned_word) v1) + v2; })
DEF_GOAL (LTU_PLUS,       3, "ltu+",        { r = ((unsigned_word) v0 < (unsigned_word) v1) + v2; })
DEF_GOAL (GTU_PLUS,       3, "gtu+",        { r = ((unsigned_word) v0 > (unsigned_word) v1) + v2; })
DEF_GOAL (LESU_PLUS,      3, "lesu+",       { r = ((signed_word) v0 < 0 || (unsigned_word) v0 <= (unsigned_word) v1) + v2; })
DEF_GOAL (GESU_PLUS,      3, "gesu+",       { r = ((signed_word) v0 >= 0 && (unsigned_word) v0 >= (unsigned_word) v1) + v2; })
DEF_GOAL (LTSU_PLUS,      3, "ltsu+",       { r = ((signed_word) v0 < 0 || (unsigned_word) v0 < (unsigned_word) v1) + v2; })
DEF_GOAL (GTSU_PLUS,      3, "gtsu+",       { r = ((signed_word) v0 >= 0 && (unsigned_word) v0 > (unsigned_word) v1) + v2; })
DEF_GOAL (EQ0_PLUS,       2, "eq0+",        { r = (v0 == 0) + v1; })
DEF_GOAL (NE0_PLUS,       2, "ne0+",        { r = (v0 != 0) + v1; })
DEF_GOAL (LES0_PLUS,      2, "les0+",       { r = ((signed_word) v0 <= 0) + v1; })
DEF_GOAL (GES0_PLUS,      2, "ges0+",       { r = ((signed_word) v0 >= 0) + v1; })
DEF_GOAL (LTS0_PLUS,      2, "lts0+",       { r = ((signed_word) v0 < 0) + v1; })
DEF_GOAL (GTS0_PLUS,      2, "gts0+",       { r = ((signed_word) v0 > 0) + v1; })

DEF_SYNONYM (EQ_PLUS,        "peq")
DEF_SYNONYM (NE_PLUS,        "pne")
DEF_SYNONYM (LES_PLUS,       "ples")
DEF_SYNONYM (GES_PLUS,       "pges")
DEF_SYNONYM (LTS_PLUS,       "plts")
DEF_SYNONYM (GTS_PLUS,       "pgts")
DEF_SYNONYM (LEU_PLUS,       "pleu")
DEF_SYNONYM (GEU_PLUS,       "pgeu")
DEF_SYNONYM (LTU_PLUS,       "pltu")
DEF_SYNONYM (GTU_PLUS,       "pgtu")
DEF_SYNONYM (LESU_PLUS,      "plesu")
DEF_SYNONYM (GESU_PLUS,      "pgesu")
DEF_SYNONYM (LTSU_PLUS,      "pltsu")
DEF_SYNONYM (GTSU_PLUS,      "pgtsu")
DEF_SYNONYM (EQ0_PLUS,       "peq0")
DEF_SYNONYM (NE0_PLUS,       "pne0")
DEF_SYNONYM (LES0_PLUS,      "ples0")
DEF_SYNONYM (GES0_PLUS,      "pges0")
DEF_SYNONYM (LTS0_PLUS,      "plts0")
DEF_SYNONYM (GTS0_PLUS,      "pgts0")

DEF_GOAL (EQ_MINUS,       3, "eq-",         { r = v2 - (v0 == v1); })
DEF_GOAL (NE_MINUS,       3, "ne-",         { r = v2 - (v0 != v1); })
DEF_GOAL (LES_MINUS,      3, "les-",        { r = v2 - ((signed_word) v0 <= (signed_word) v1); })
DEF_GOAL (GES_MINUS,      3, "ges-",        { r = v2 - ((signed_word) v0 >= (signed_word) v1); })
DEF_GOAL (LTS_MINUS,      3, "lts-",        { r = v2 - ((signed_word) v0 < (signed_word) v1); })
DEF_GOAL (GTS_MINUS,      3, "gts-",        { r = v2 - ((signed_word) v0 > (signed_word) v1); })
DEF_GOAL (LEU_MINUS,      3, "leu-",        { r = v2 - ((unsigned_word) v0 <= (unsigned_word) v1); })
DEF_GOAL (GEU_MINUS,      3, "geu-",        { r = v2 - ((unsigned_word) v0 >= (unsigned_word) v1); })
DEF_GOAL (LTU_MINUS,      3, "ltu-",        { r = v2 - ((unsigned_word) v0 < (unsigned_word) v1); })
DEF_GOAL (GTU_MINUS,      3, "gtu-",        { r = v2 - ((unsigned_word) v0 > (unsigned_word) v1); })
DEF_GOAL (LESU_MINUS,     3, "lesu-",       { r = v2 - ((signed_word) v0 < 0 || (unsigned_word) v0 <= (unsigned_word) v1); })
DEF_GOAL (GESU_MINUS,     3, "gesu-",       { r = v2 - ((signed_word) v0 >= 0 && (unsigned_word) v0 >= (unsigned_word) v1); })
DEF_GOAL (LTSU_MINUS,     3, "ltsu-",       { r = v2 - ((signed_word) v0 < 0 || (unsigned_word) v0 < (unsigned_word) v1); })
DEF_GOAL (GTSU_MINUS,     3, "gtsu-",       { r = v2 - ((signed_word) v0 >= 0 && (unsigned_word) v0 > (unsigned_word) v1); })

DEF_GOAL (EQ0_MINUS,      2, "eq0-",        { r = v1 - (v0 == 0); })
DEF_GOAL (NE0_MINUS,      2, "ne0-",        { r = v1 - (v0 != 0); })
DEF_GOAL (LES0_MINUS,     2, "les0-",       { r = v1 - ((signed_word) v0 <= 0); })
DEF_GOAL (GES0_MINUS,     2, "ges0-",       { r = v1 - ((signed_word) v0 >= 0); })
DEF_GOAL (LTS0_MINUS,     2, "lts0-",       { r = v1 - ((signed_word) v0 < 0); })
DEF_GOAL (GTS0_MINUS,     2, "gts0-",       { r = v1 - ((signed_word) v0 > 0); })

DEF_GOAL (NEQ_AND,        3, "naeq",        { r = -(v0 == v1) & v2; })
DEF_GOAL (NNE_AND,        3, "nane",        { r = -(v0 != v1) & v2; })
DEF_GOAL (NLES_AND,       3, "nales",       { r = -((signed_word) v0 <= (signed_word) v1) & v2; })
DEF_GOAL (NGES_AND,       3, "nages",       { r = -((signed_word) v0 >= (signed_word) v1) & v2; })
DEF_GOAL (NLTS_AND,       3, "nalts",       { r = -((signed_word) v0 < (signed_word) v1) & v2; })
DEF_GOAL (NGTS_AND,       3, "nagts",       { r = -((signed_word) v0 > (signed_word) v1) & v2; })
DEF_GOAL (NLEU_AND,       3, "naleu",       { r = -((unsigned_word) v0 <= (unsigned_word) v1) & v2; })
DEF_GOAL (NGEU_AND,       3, "nageu",       { r = -((unsigned_word) v0 >= (unsigned_word) v1) & v2; })
DEF_GOAL (NLTU_AND,       3, "naltu",       { r = -((unsigned_word) v0 < (unsigned_word) v1) & v2; })
DEF_GOAL (NGTU_AND,       3, "nagtu",       { r = -((unsigned_word) v0 > (unsigned_word) v1) & v2; })

DEF_GOAL (NEQ0_AND,       2, "naeq0",       { r = -(v0 == 0) & v1; })
DEF_GOAL (NNE0_AND,       2, "nane0",       { r = -(v0 != 0) & v1; })
DEF_GOAL (NLES0_AND,      2, "nales0",      { r = -((signed_word) v0 <= 0) & v1; })
DEF_GOAL (NGES0_AND,      2, "nages0",      { r = -((signed_word) v0 >= 0) & v1; })
DEF_GOAL (NLTS0_AND,      2, "nalts0",      { r = -((signed_word) v0 < 0) & v1; })
DEF_GOAL (NGTS0_AND,      2, "nagts0",      { r = -((signed_word) v0 > 0) & v1; })

DEF_GOAL (FFS,            1, "ffs",         { r = ffs (v0); })
DEF_GOAL (MULTADJ,        3, "multadj",     { r = v1 + ((signed_word) v0 < 0 ? v2 : 0); })

DEF_GOAL (CMPBYTES,	2, "cmpbytes",
  {
    union { word w; char b[4]; } __r1;
    union { word w; char b[4]; } __r2;
    __r1.w = (v0); __r2.w = (v1);
    r = ((__r1.b[0] != __r2.b[0]) && (__r1.b[1] != __r2.b[1])
	 && (__r1.b[2] != __r2.b[2]) && (__r1.b[3] != __r2.b[3]));
  })

DEF_GOAL (ZDEPI_FOR_MOVSI, 1, "zfm",
	  {
	    word __t;
	    word __mask;
	    __mask = v0 & -v0;

	    __t = (v0 >> 4) + __mask;
	    __t &= ~(__mask - 1);

	    r = ((__t & (__t - 1)) == 0);
	  })

#ifdef __GNUC__
#if 0
DEF_GOAL (UDIV_QRNND,     3, "udiv_qrnnd",  ({ word t1, t2; udiv_qrnnd (t1, t2, v0, v1, v2); r = t1; }))
DEF_GOAL (UMOD_QRNND,     3, "umod_qrnnd",  ({ word t1, t2; udiv_qrnnd (t1, t2, v0, v1, v2); r = t2; }))
#endif
DEF_GOAL (UMULH,     2, "umulh",  ({ word t1; word t2; umul_ppmm (t1, t2, v0, v1); r = t1; }))
#endif /* __GNUC__ */

#if 0
DEF_GOAL (UDIV,           2, "udiv",        { r = v0 / v1; })
#endif

/*
Local variables:
mode:c
version-control: t
End:
*/
