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; }
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); }
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 */
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 */
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 */
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); }
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; }