/* Definitions of target machine for GNU compiler. Vax version.
- Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU CC.
/* Names to predefine in the preprocessor for this target machine. */
-#define CPP_PREDEFINES "-Dvax -Dunix"
+#define CPP_PREDEFINES "-Dvax -Dunix -Asystem(unix) -Asystem(bsd) -Acpu(vax) -Amachine(vax)"
/* If using g-format floating point, alter math.h. */
\f
/* Target machine storage layout */
+/* Define for software floating point emulation of VAX format
+ when cross compiling from a non-VAX host. */
+/* #define REAL_ARITHMETIC */
+
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields.
This is not true on the vax. */
to the start of the trampoline. */
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
+ emit_insn (gen_rtx (ASM_INPUT, VOIDmode, \
+ "movpsl -(sp)\n\tpushal 1(pc)\n\trei")); \
emit_move_insn (gen_rtx (MEM, HImode, TRAMP), \
gen_rtx (MEM, HImode, FNADDR)); \
emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 4)), CXT);\
/* 1 if X is an rtx for a constant that is a valid address. */
-#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+#define CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
+ || GET_CODE (X) == HIGH)
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
(This much is the easy part.) */
#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
{ register rtx xfoob = (X); \
- if (GET_CODE (xfoob) == REG) goto ADDR; \
+ if (GET_CODE (xfoob) == REG) \
+ { \
+ extern rtx *reg_equiv_mem; \
+ if (! reload_in_progress \
+ || reg_equiv_mem[REGNO (xfoob)] == 0 \
+ || INDIRECTABLE_ADDRESS_P (reg_equiv_mem[REGNO (xfoob)])) \
+ goto ADDR; \
+ } \
if (CONSTANT_ADDRESS_P (xfoob)) goto ADDR; \
if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \
xfoob = XEXP (X, 0); \
of a switch statement. If the code is computed here,
return it with a return statement. Otherwise, break from the switch. */
-#define CONST_COSTS(RTX,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). */
+
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
case CONST_INT: \
- /* Constant zero is super cheap due to clr instruction. */ \
- if ((RTX) == const0_rtx) return 0; \
- /* Constants of +/- 1 should also be super cheap since \
- may be used in decl/incl/aob/sob insns. */ \
- if ((RTX) == const1_rtx || (RTX) == constm1_rtx) return 0; \
- if ((unsigned) INTVAL (RTX) < 077) return 1; \
+ if (INTVAL (RTX) == 0) return 0; \
+ if ((OUTER_CODE) == AND) \
+ return ((unsigned) ~INTVAL (RTX) <= 077) ? 1 : 2; \
+ if ((unsigned) INTVAL (RTX) <= 077) return 1; \
+ if ((OUTER_CODE) == COMPARE && INTVAL (RTX) == -1) \
+ return 1; \
+ if ((OUTER_CODE) == PLUS && (unsigned) -INTVAL (RTX) <= 077)\
+ return 1; \
case CONST: \
case LABEL_REF: \
case SYMBOL_REF: \
return 3; \
case CONST_DOUBLE: \
- return 5;
-
-/* On most VAX models, shift are almost as expensive as multiplies, so
- we'd rather use multiply unless it can be done in an extremely small
- sequence. */
-#define RTX_COSTS(RTX,CODE) \
- case LSHIFT: \
- case ASHIFT: \
- case ASHIFTRT: \
- case LSHIFTRT: \
- case ROTATE: \
- case ROTATERT: \
- return COSTS_N_INSNS (4);
+ if (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT) \
+ return vax_float_literal (RTX) ? 5 : 8; \
+ else \
+ return (((CONST_DOUBLE_HIGH (RTX) == 0 \
+ && (unsigned) CONST_DOUBLE_LOW (RTX) < 64) \
+ || ((OUTER_CODE) == PLUS \
+ && CONST_DOUBLE_HIGH (RTX) == -1 \
+ && (unsigned)-CONST_DOUBLE_LOW (RTX) < 64)) \
+ ? 2 : 5);
+
+#define RTX_COSTS(RTX,CODE,OUTER_CODE) case FIX: case FLOAT: \
+ case MULT: case DIV: case UDIV: case MOD: case UMOD: \
+ case ASHIFT: case LSHIFTRT: case ASHIFTRT: \
+ case ROTATE: case ROTATERT: case PLUS: case MINUS: case IOR: \
+ case XOR: case AND: case NEG: case NOT: case ZERO_EXTRACT: \
+ case SIGN_EXTRACT: case MEM: return vax_rtx_cost(RTX)
+
+#define ADDRESS_COST(RTX) (1 + (GET_CODE (RTX) == REG ? 0 : vax_address_cost(RTX)))
/* Specify the cost of a branch insn; roughly the number of extra insns that
should be added to avoid a branch.
/* note that it is very hard to accidentally create a number that fits in a
double but not in a float, since their ranges are almost the same */
-#define CHECK_FLOAT_VALUE(mode, d) \
- if ((mode) == SFmode) \
- { \
- if ((d) > 1.7014117331926444e+38) \
- { error ("magnitude of constant too large for `float'"); \
- (d) = 1.7014117331926444e+38; } \
- else if ((d) < -1.7014117331926444e+38) \
- { error ("magnitude of constant too large for `float'"); \
- (d) = -1.7014117331926444e+38; } \
- else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \
- { warning ("`float' constant truncated to zero"); \
- (d) = 0.0; } \
- else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \
- { warning ("`float' constant truncated to zero"); \
- (d) = 0.0; } \
- }
+
+#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
+ ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
/* For future reference:
D Float: 9 bit, sign magnitude, excess 128 binary exponent
It is .dfloat or .gfloat, depending. */
#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
- fprintf (FILE, "\t.%cfloat 0%c%.20e\n", ASM_DOUBLE_CHAR, \
- ASM_DOUBLE_CHAR, (VALUE))
+do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr); \
+ fprintf (FILE, "\t.%cfloat 0%c%s\n", ASM_DOUBLE_CHAR, \
+ ASM_DOUBLE_CHAR, dstr); \
+ } while (0);
/* This is how to output an assembler line defining a `float' constant. */
#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
- fprintf (FILE, "\t.float 0f%.20e\n", (VALUE))
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr); \
+ fprintf (FILE, "\t.float 0f%s\n", dstr); } while (0);
/* This is how to output an assembler line defining an `int' constant. */
/* Print an instruction operand X on file FILE.
CODE is the code from the %-spec that requested printing this operand;
if `%z3' was used to print operand 3, then CODE is 'z'.
- On the Vax, the codes used are:
- `#', indicating that either `d' or `g' should be printed,
- depending on whether we're using dfloat or gfloat.
- `C', indicating the reverse of the condition name specified by the
- operand.
- `P', indicating one plus a constant operand
- `N', indicating the one's complement of a constant operand
- `H', indicating the low-order 16 bits of the one's complement of a constant
- `B', similarly for the low-order 8 bits. */
+
+VAX operand formatting codes:
+
+ letter print
+ C reverse branch condition
+ D 64-bit immediate operand
+ B the low 8 bits of the complement of a constant operand
+ H the low 16 bits of the complement of a constant operand
+ M a mask for the N highest bits of a word
+ N the complement of a constant integer operand
+ P constant operand plus 1
+ R 32 - constant operand
+ b the low 8 bits of a negated constant operand
+ h the low 16 bits of a negated constant operand
+ # 'd' or 'g' depending on whether dfloat or gfloat is used */
+
+/* The purpose of D is to get around a quirk or bug in vax assembler
+ whereby -1 in a 64-bit immediate operand means 0x00000000ffffffff,
+ which is not a 64-bit minus one. */
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '#')
if (CODE == '#') fputc (ASM_DOUBLE_CHAR, FILE); \
else if (CODE == 'C') \
fputs (rev_cond_name (X), FILE); \
+ else if (CODE == 'D' && GET_CODE (X) == CONST_INT && INTVAL (X) < 0) \
+ fprintf (FILE, "$0xffffffff%08x", INTVAL (X)); \
else if (CODE == 'P' && GET_CODE (X) == CONST_INT) \
fprintf (FILE, "$%d", INTVAL (X) + 1); \
else if (CODE == 'N' && GET_CODE (X) == CONST_INT) \
fprintf (FILE, "$%d", 32 - INTVAL (X)); \
else if (CODE == 'H' && GET_CODE (X) == CONST_INT) \
fprintf (FILE, "$%d", 0xffff & ~ INTVAL (X)); \
+ else if (CODE == 'h' && GET_CODE (X) == CONST_INT) \
+ fprintf (FILE, "$%d", (short) - INTVAL (x)); \
else if (CODE == 'B' && GET_CODE (X) == CONST_INT) \
fprintf (FILE, "$%d", 0xff & ~ INTVAL (X)); \
+ else if (CODE == 'b' && GET_CODE (X) == CONST_INT) \
+ fprintf (FILE, "$%d", 0xff & - INTVAL (X)); \
+ else if (CODE == 'M' && GET_CODE (X) == CONST_INT) \
+ fprintf (FILE, "$%d", ~((1 << INTVAL (x)) - 1)); \
else if (GET_CODE (X) == REG) \
fprintf (FILE, "%s", reg_names[REGNO (X)]); \
else if (GET_CODE (X) == MEM) \
output_address (XEXP (X, 0)); \
- else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode) \
- { union { double d; int i[2]; } u; \
- u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X); \
- fprintf (FILE, "$0%c%.20e", ASM_DOUBLE_CHAR, u.d); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode) \
+ { REAL_VALUE_TYPE r; char dstr[30]; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ REAL_VALUE_TO_DECIMAL (r, "%.20e", dstr); \
+ fprintf (FILE, "$0f%s", dstr); } \
+ else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode) \
+ { REAL_VALUE_TYPE r; char dstr[30]; \
+ REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
+ REAL_VALUE_TO_DECIMAL (r, "%.20e", dstr); \
+ fprintf (FILE, "$0%c%s", ASM_DOUBLE_CHAR, dstr); } \
else { putc ('$', FILE); output_addr_const (FILE, X); }}
/* Print a memory operand whose address is X, on file FILE.