int
crx_const_double_ok (rtx op)
{
  if (GET_MODE (op) == DFmode)
  {
    REAL_VALUE_TYPE r;
    long l[2];
    REAL_VALUE_FROM_CONST_DOUBLE (r, op);
    REAL_VALUE_TO_TARGET_DOUBLE (r, l);
    return (UNSIGNED_INT_FITS_N_BITS (l[0], 4) &&
	    UNSIGNED_INT_FITS_N_BITS (l[1], 4)) ? 1 : 0;
  }

  if (GET_MODE (op) == SFmode)
  {
    REAL_VALUE_TYPE r;
    long l;
    REAL_VALUE_FROM_CONST_DOUBLE (r, op);
    REAL_VALUE_TO_TARGET_SINGLE (r, l);
    return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
  }

  return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) &&
	  UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4)) ? 1 : 0;
}
예제 #2
0
파일: lm32.c 프로젝트: boomeer/gcc
void
lm32_print_operand (FILE * file, rtx op, int letter)
{
  enum rtx_code code;

  code = GET_CODE (op);

  if (code == SIGN_EXTEND)
    op = XEXP (op, 0), code = GET_CODE (op);
  else if (code == REG || code == SUBREG)
    {
      int regnum;

      if (code == REG)
	regnum = REGNO (op);
      else
	regnum = true_regnum (op);

      fprintf (file, "%s", reg_names[regnum]);
    }
  else if (code == HIGH)
    output_addr_const (file, XEXP (op, 0));  
  else if (code == MEM)
    output_address (XEXP (op, 0));
  else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
    fprintf (file, "%s", reg_names[0]);
  else if (GET_CODE (op) == CONST_DOUBLE)
    {
      if ((CONST_DOUBLE_LOW (op) != 0) || (CONST_DOUBLE_HIGH (op) != 0))
	output_operand_lossage ("only 0.0 can be loaded as an immediate");
      else
	fprintf (file, "0");
    }
  else if (code == EQ)
    fprintf (file, "e  ");
  else if (code == NE)
    fprintf (file, "ne ");
  else if (code == GT)
    fprintf (file, "g  ");
  else if (code == GTU)
    fprintf (file, "gu ");
  else if (code == LT)
    fprintf (file, "l  ");
  else if (code == LTU)
    fprintf (file, "lu ");
  else if (code == GE)
    fprintf (file, "ge ");
  else if (code == GEU)
    fprintf (file, "geu");
  else if (code == LE)
    fprintf (file, "le ");
  else if (code == LEU)
    fprintf (file, "leu");
  else
    output_addr_const (file, op);
}
예제 #3
0
파일: sched-vis.c 프로젝트: ChaosJohn/gcc
void
print_value (pretty_printer *pp, const_rtx x, int verbose)
{
  char tmp[1024];

  if (!x)
    {
      pp_string (pp, "(nil)");
      return;
    }
  switch (GET_CODE (x))
    {
    case CONST_INT:
      pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
		 (unsigned HOST_WIDE_INT) INTVAL (x));
      break;
    case CONST_DOUBLE:
      if (FLOAT_MODE_P (GET_MODE (x)))
	{
	  real_to_decimal (tmp, CONST_DOUBLE_REAL_VALUE (x),
			   sizeof (tmp), 0, 1);
	  pp_string (pp, tmp);
	}
      else
	pp_printf (pp, "<%wx,%wx>",
		   (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
		   (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
      break;
    case CONST_FIXED:
      fixed_to_decimal (tmp, CONST_FIXED_VALUE (x), sizeof (tmp));
      pp_string (pp, tmp);
      break;
    case CONST_STRING:
      pp_printf (pp, "\"%s\"", XSTR (x, 0));
      break;
    case SYMBOL_REF:
      pp_printf (pp, "`%s'", XSTR (x, 0));
      break;
    case LABEL_REF:
      pp_printf (pp, "L%d", INSN_UID (XEXP (x, 0)));
      break;
    case CONST:
    case HIGH:
    case STRICT_LOW_PART:
      pp_printf (pp, "%s(", GET_RTX_NAME (GET_CODE (x)));
      print_value (pp, XEXP (x, 0), verbose);
      pp_right_paren (pp);
      break;
    case REG:
      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
	{
	  if (ISDIGIT (reg_names[REGNO (x)][0]))
	    pp_modulo (pp);
	  pp_string (pp, reg_names[REGNO (x)]);
	}
      else
	pp_printf (pp, "r%d", REGNO (x));
      if (verbose)
	pp_printf (pp, ":%s", GET_MODE_NAME (GET_MODE (x)));
      break;
    case SUBREG:
      print_value (pp, SUBREG_REG (x), verbose);
      pp_printf (pp, "#%d", SUBREG_BYTE (x));
      break;
    case SCRATCH:
    case CC0:
    case PC:
      pp_string (pp, GET_RTX_NAME (GET_CODE (x)));
      break;
    case MEM:
      pp_left_bracket (pp);
      print_value (pp, XEXP (x, 0), verbose);
      pp_right_bracket (pp);
      break;
    case DEBUG_EXPR:
      pp_printf (pp, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
      break;
    default:
      print_exp (pp, x, verbose);
      break;
    }
}				/* print_value */
예제 #4
0
void
print_value (char *buf, const_rtx x, int verbose)
{
  char t[BUF_LEN];
  char *cur = buf;

  if (!x)
    {
      safe_concat (buf, buf, "(nil)");
      return;
    }
  switch (GET_CODE (x))
    {
    case CONST_INT:
      sprintf (t, HOST_WIDE_INT_PRINT_HEX,
	       (unsigned HOST_WIDE_INT) INTVAL (x));
      cur = safe_concat (buf, cur, t);
      break;
    case CONST_DOUBLE:
      if (FLOAT_MODE_P (GET_MODE (x)))
	real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
      else
	sprintf (t,
		 "<" HOST_WIDE_INT_PRINT_HEX "," HOST_WIDE_INT_PRINT_HEX ">",
		 (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x),
		 (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x));
      cur = safe_concat (buf, cur, t);
      break;
    case CONST_FIXED:
      fixed_to_decimal (t, CONST_FIXED_VALUE (x), sizeof (t));
      cur = safe_concat (buf, cur, t);
      break;
    case CONST_STRING:
      cur = safe_concat (buf, cur, "\"");
      cur = safe_concat (buf, cur, XSTR (x, 0));
      cur = safe_concat (buf, cur, "\"");
      break;
    case SYMBOL_REF:
      cur = safe_concat (buf, cur, "`");
      cur = safe_concat (buf, cur, XSTR (x, 0));
      cur = safe_concat (buf, cur, "'");
      break;
    case LABEL_REF:
      sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
      cur = safe_concat (buf, cur, t);
      break;
    case CONST:
      print_value (t, XEXP (x, 0), verbose);
      cur = safe_concat (buf, cur, "const(");
      cur = safe_concat (buf, cur, t);
      cur = safe_concat (buf, cur, ")");
      break;
    case HIGH:
      print_value (t, XEXP (x, 0), verbose);
      cur = safe_concat (buf, cur, "high(");
      cur = safe_concat (buf, cur, t);
      cur = safe_concat (buf, cur, ")");
      break;
    case REG:
      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
	{
	  int c = reg_names[REGNO (x)][0];
	  if (ISDIGIT (c))
	    cur = safe_concat (buf, cur, "%");

	  cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
	}
      else
	{
	  sprintf (t, "r%d", REGNO (x));
	  cur = safe_concat (buf, cur, t);
	}
      if (verbose
#ifdef INSN_SCHEDULING
	  && !current_sched_info
#endif
	 )
	{
	  sprintf (t, ":%s", GET_MODE_NAME (GET_MODE (x)));
	  cur = safe_concat (buf, cur, t);
	}
      break;
    case SUBREG:
      print_value (t, SUBREG_REG (x), verbose);
      cur = safe_concat (buf, cur, t);
      sprintf (t, "#%d", SUBREG_BYTE (x));
      cur = safe_concat (buf, cur, t);
      break;
    case STRICT_LOW_PART:
      print_value (t, XEXP (x, 0), verbose);
      cur = safe_concat (buf, cur, "strict_low_part(");
      cur = safe_concat (buf, cur, t);
      cur = safe_concat (buf, cur, ")");
      break;
    case SCRATCH:
      cur = safe_concat (buf, cur, "scratch");
      break;
    case CC0:
      cur = safe_concat (buf, cur, "cc0");
      break;
    case PC:
      cur = safe_concat (buf, cur, "pc");
      break;
    case MEM:
      print_value (t, XEXP (x, 0), verbose);
      cur = safe_concat (buf, cur, "[");
      cur = safe_concat (buf, cur, t);
      cur = safe_concat (buf, cur, "]");
      break;
    case DEBUG_EXPR:
      sprintf (t, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
      cur = safe_concat (buf, cur, t);
      break;
    default:
      print_exp (t, x, verbose);
      cur = safe_concat (buf, cur, t);
      break;
    }
}				/* print_value */
예제 #5
0
static void
print_value (char *buf, rtx x, int verbose)
{
  char t[BUF_LEN];
  char *cur = buf;

  switch (GET_CODE (x))
    {
    case CONST_INT:
      sprintf (t, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
      cur = safe_concat (buf, cur, t);
      break;
    case CONST_DOUBLE:
      if (FLOAT_MODE_P (GET_MODE (x)))
	real_to_decimal (t, CONST_DOUBLE_REAL_VALUE (x), sizeof (t), 0, 1);
      else
	sprintf (t, "<0x%lx,0x%lx>", (long) CONST_DOUBLE_LOW (x), (long) CONST_DOUBLE_HIGH (x));
      cur = safe_concat (buf, cur, t);
      break;
    case CONST_STRING:
      cur = safe_concat (buf, cur, "\"");
      cur = safe_concat (buf, cur, XSTR (x, 0));
      cur = safe_concat (buf, cur, "\"");
      break;
    case SYMBOL_REF:
      cur = safe_concat (buf, cur, "`");
      cur = safe_concat (buf, cur, XSTR (x, 0));
      cur = safe_concat (buf, cur, "'");
      break;
    case LABEL_REF:
      sprintf (t, "L%d", INSN_UID (XEXP (x, 0)));
      cur = safe_concat (buf, cur, t);
      break;
    case CONST:
      print_value (t, XEXP (x, 0), verbose);
      cur = safe_concat (buf, cur, "const(");
      cur = safe_concat (buf, cur, t);
      cur = safe_concat (buf, cur, ")");
      break;
    case HIGH:
      print_value (t, XEXP (x, 0), verbose);
      cur = safe_concat (buf, cur, "high(");
      cur = safe_concat (buf, cur, t);
      cur = safe_concat (buf, cur, ")");
      break;
    case REG:
      if (REGNO (x) < FIRST_PSEUDO_REGISTER)
	{
	  int c = reg_names[REGNO (x)][0];
	  if (ISDIGIT (c))
	    cur = safe_concat (buf, cur, "%");

	  cur = safe_concat (buf, cur, reg_names[REGNO (x)]);
	}
      else
	{
	  sprintf (t, "r%d", REGNO (x));
	  cur = safe_concat (buf, cur, t);
	}
      break;
    case SUBREG:
      print_value (t, SUBREG_REG (x), verbose);
      cur = safe_concat (buf, cur, t);
      sprintf (t, "#%d", SUBREG_BYTE (x));
      cur = safe_concat (buf, cur, t);
      break;
    case SCRATCH:
      cur = safe_concat (buf, cur, "scratch");
      break;
    case CC0:
      cur = safe_concat (buf, cur, "cc0");
      break;
    case PC:
      cur = safe_concat (buf, cur, "pc");
      break;
    case MEM:
      print_value (t, XEXP (x, 0), verbose);
      cur = safe_concat (buf, cur, "[");
      cur = safe_concat (buf, cur, t);
      cur = safe_concat (buf, cur, "]");
      break;
    default:
      print_exp (t, x, verbose);
      cur = safe_concat (buf, cur, t);
      break;
    }
}				/* print_value */
예제 #6
0
void
lm32_print_operand (FILE *file, rtx op, int letter)
{
    register enum rtx_code code;

    if (! op)
    {
        error ("PRINT_OPERAND null pointer");
        abort ();
    }

    code = GET_CODE (op);

    if (code == SIGN_EXTEND)
        op = XEXP (op, 0), code = GET_CODE (op);
    else if (code == REG || code == SUBREG)
    {
        int regnum;

        if (code == REG)
            regnum = REGNO (op);
        else
            regnum = true_regnum (op);

        if (   (letter == 'H' && !WORDS_BIG_ENDIAN)
                || (letter == 'L' && WORDS_BIG_ENDIAN))
        {
            abort();
            regnum++;
        }

        fprintf (file, "%s", reg_names[regnum]);
    }
    else if (code == MEM)
        output_address (XEXP (op, 0));
    else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
        fprintf (file, "%s", reg_names[0]);
    else if (GET_CODE (op) == CONST_DOUBLE)
    {
        if ((CONST_DOUBLE_LOW (op) != 0) || (CONST_DOUBLE_HIGH (op) != 0))
            output_operand_lossage ("Only 0.0 can be loaded as an immediate");
        else
            fprintf (file, "0");
    }
    else if (code == EQ)
        fprintf (file, "e  ");
    else if (code == NE)
        fprintf (file, "ne ");
    else if (code == GT)
        fprintf (file, "g  ");
    else if (code == GTU)
        fprintf (file, "gu ");
    else if (code == LT)
        fprintf (file, "l  ");
    else if (code == LTU)
        fprintf (file, "lu ");
    else if (code == GE)
        fprintf (file, "ge ");
    else if (code == GEU)
        fprintf (file, "geu");
    else if (code == LE)
        fprintf (file, "le ");
    else if (code == LEU)
        fprintf (file, "leu");
    else
        output_addr_const (file, op);
}
예제 #7
0
static bool
vax_rtx_costs (rtx x, int code, int outer_code, int *total)
{
  enum machine_mode mode = GET_MODE (x);
  int i = 0;				   /* may be modified in switch */
  const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */

  switch (code)
    {
      /* On a VAX, constants from 0..63 are cheap because they can use the
	 1 byte literal constant format.  Compare to -1 should be made cheap
	 so that decrement-and-branch insns can be formed more easily (if
	 the value -1 is copied to a register some decrement-and-branch
	 patterns will not match).  */
    case CONST_INT:
      if (INTVAL (x) == 0)
	return true;
      if (outer_code == AND)
	{
          *total = ((unsigned HOST_WIDE_INT) ~INTVAL (x) <= 077) ? 1 : 2;
	  return true;
	}
      if ((unsigned HOST_WIDE_INT) INTVAL (x) <= 077
	  || (outer_code == COMPARE
	      && INTVAL (x) == -1)
	  || ((outer_code == PLUS || outer_code == MINUS)
	      && (unsigned HOST_WIDE_INT) -INTVAL (x) <= 077))
	{
	  *total = 1;
	  return true;
	}
      /* FALLTHRU */

    case CONST:
    case LABEL_REF:
    case SYMBOL_REF:
      *total = 3;
      return true;

    case CONST_DOUBLE:
      if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
	*total = vax_float_literal (x) ? 5 : 8;
      else
        *total = ((CONST_DOUBLE_HIGH (x) == 0
		   && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x) < 64)
		  || (outer_code == PLUS
		      && CONST_DOUBLE_HIGH (x) == -1
		      && (unsigned HOST_WIDE_INT)-CONST_DOUBLE_LOW (x) < 64))
		 ? 2 : 5;
      return true;

    case POST_INC:
      *total = 2;
      return true;		/* Implies register operand.  */

    case PRE_DEC:
      *total = 3;
      return true;		/* Implies register operand.  */

    case MULT:
      switch (mode)
	{
	case DFmode:
	  *total = 16;		/* 4 on VAX 9000 */
	  break;
	case SFmode:
	  *total = 9;		/* 4 on VAX 9000, 12 on VAX 2 */
	  break;
	case DImode:
	  *total = 16;		/* 6 on VAX 9000, 28 on VAX 2 */
	  break;
	case SImode:
	case HImode:
	case QImode:
	  *total = 10;		/* 3-4 on VAX 9000, 20-28 on VAX 2 */
	  break;
	default:
	  *total = MAX_COST;	/* Mode is not supported.  */
	  return true;
	}
      break;

    case UDIV:
      if (mode != SImode)
	{
	  *total = MAX_COST;	/* Mode is not supported.  */
	  return true;
	}
      *total = 17;
      break;

    case DIV:
      if (mode == DImode)
	*total = 30;		/* Highly variable.  */
      else if (mode == DFmode)
	/* divide takes 28 cycles if the result is not zero, 13 otherwise */
	*total = 24;
      else
	*total = 11;		/* 25 on VAX 2 */
      break;

    case MOD:
      *total = 23;
      break;

    case UMOD:
      if (mode != SImode)
	{
	  *total = MAX_COST;	/* Mode is not supported.  */
	  return true;
	}
      *total = 29;
      break;

    case FLOAT:
      *total = (6		/* 4 on VAX 9000 */
		+ (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode));
      break;

    case FIX:
      *total = 7;		/* 17 on VAX 2 */
      break;

    case ASHIFT:
    case LSHIFTRT:
    case ASHIFTRT:
      if (mode == DImode)
	*total = 12;
      else
	*total = 10;		/* 6 on VAX 9000 */
      break;

    case ROTATE:
    case ROTATERT:
      *total = 6;		/* 5 on VAX 2, 4 on VAX 9000 */
      if (GET_CODE (XEXP (x, 1)) == CONST_INT)
	fmt = "e"; 		/* all constant rotate counts are short */
      break;

    case PLUS:
    case MINUS:
      *total = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
      /* Small integer operands can use subl2 and addl2.  */
      if ((GET_CODE (XEXP (x, 1)) == CONST_INT)
	  && (unsigned HOST_WIDE_INT)(INTVAL (XEXP (x, 1)) + 63) < 127)
	fmt = "e";
      break;

    case IOR:
    case XOR:
      *total = 3;
      break;

    case AND:
      /* AND is special because the first operand is complemented.  */
      *total = 3;
      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
	{
	  if ((unsigned HOST_WIDE_INT)~INTVAL (XEXP (x, 0)) > 63)
	    *total = 4;
	  fmt = "e";
	  i = 1;
	}
      break;

    case NEG:
      if (mode == DFmode)
	*total = 9;
      else if (mode == SFmode)
	*total = 6;
      else if (mode == DImode)
	*total = 4;
      else
	*total = 2;
      break;

    case NOT:
      *total = 2;
      break;

    case ZERO_EXTRACT:
    case SIGN_EXTRACT:
      *total = 15;
      break;

    case MEM:
      if (mode == DImode || mode == DFmode)
	*total = 5;		/* 7 on VAX 2 */
      else
	*total = 3;		/* 4 on VAX 2 */
      x = XEXP (x, 0);
      if (GET_CODE (x) != REG && GET_CODE (x) != POST_INC)
	*total += vax_address_cost_1 (x);
      return true;

    case FLOAT_EXTEND:
    case FLOAT_TRUNCATE:
    case TRUNCATE:
      *total = 3;		/* FIXME: Costs need to be checked  */
      break;

    default:
      return false;
    }

  /* Now look inside the expression.  Operands which are not registers or
     short constants add to the cost.

     FMT and I may have been adjusted in the switch above for instructions
     which require special handling.  */

  while (*fmt++ == 'e')
    {
      rtx op = XEXP (x, i);

      i += 1;
      code = GET_CODE (op);

      /* A NOT is likely to be found as the first operand of an AND
	 (in which case the relevant cost is of the operand inside
	 the not) and not likely to be found anywhere else.  */
      if (code == NOT)
	op = XEXP (op, 0), code = GET_CODE (op);

      switch (code)
	{
	case CONST_INT:
	  if ((unsigned HOST_WIDE_INT)INTVAL (op) > 63
	      && GET_MODE (x) != QImode)
	    *total += 1;	/* 2 on VAX 2 */
	  break;
	case CONST:
	case LABEL_REF:
	case SYMBOL_REF:
	  *total += 1;		/* 2 on VAX 2 */
	  break;
	case CONST_DOUBLE:
	  if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
	    {
	      /* Registers are faster than floating point constants -- even
		 those constants which can be encoded in a single byte.  */
	      if (vax_float_literal (op))
		*total += 1;
	      else
		*total += (GET_MODE (x) == DFmode) ? 3 : 2;
	    }
	  else
	    {
	      if (CONST_DOUBLE_HIGH (op) != 0
		  || (unsigned)CONST_DOUBLE_LOW (op) > 63)
		*total += 2;
	    }
	  break;
	case MEM:
	  *total += 1;		/* 2 on VAX 2 */
	  if (GET_CODE (XEXP (op, 0)) != REG)
	    *total += vax_address_cost_1 (XEXP (op, 0));
	  break;
	case REG:
	case SUBREG:
	  break;
	default:
	  *total += 1;
	  break;
	}
    }
  return true;
}